# Exploring Three.js Geometries: The Building Blocks of 3D

Welcome back to my Three.js learning journey! 👋 In my [previous post](https://blog.iamdipankarpaul.com/my-first-threejs-scene-building-a-3d-world-in-the-browser), I covered the basics of setting up a Three.js scene. Today, I'm diving deeper into **geometries** - the fundamental shapes that form every 3D object you see on the web.

Think of geometries like LEGO pieces. Each piece has a different shape, but they all work the same way - you attach them to materials, position them in your scene and you've got 3D objects.

## What Are Geometries?

In Three.js, a geometry defines the **shape** of a 3D object. It's essentially a collection of:

* **Vertices** (points in 3D space)
    
* **Faces** (triangles connecting those points)
    

Three.js provides many built-in geometries that cover most use cases. Today, we'll explore four essential shapes and understand when to use each one.

## Project Setup

Before we jump into different geometries, here's our basic HTML structure:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js Geometries Gallery</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            font-family: Arial, sans-serif;
        }
        canvas {
            display: block;
        }
        #info {
            position: absolute;
            top: 20px;
            left: 20px;
            color: white;
            background: rgba(0, 0, 0, 0.7);
            padding: 15px;
            border-radius: 8px;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <div id="info">
        <strong>Geometries Gallery</strong><br>
    </div>
    <script type="module" src="script.js"></script>
</body>
</html>
```

## Building Our Geometry Gallery

Now let's create a gallery showcasing different Three.js geometries. I'll arrange them in a nice grid pattern so we can see them all at once!

### Step 1: Scene Setup

```jsx
import * as THREE from "three";

const canvas = document.getElementById("canvas");

// Scene setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a1a); // Dark background

// Camera setup
const camera = new THREE.PerspectiveCamera(
    75, // Field of view
    window.innerWidth / window.innerHeight, // Aspect ratio
    0.1, // Near clipping plane
    1000 // Far clipping plane
);
camera.position.set(0, 3, 12); // Position camera to see all objects
camera.lookAt(0, 0, 0); // Look at center of scene
```

### Step 2: Lighting Setup

```jsx
// Ambient light - provides base illumination for all objects
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);

// Directional light - acts like sunlight from a specific direction
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 5);
scene.add(directionalLight);

// Point light - adds a colored accent light
const pointLight = new THREE.PointLight(0x00ffff, 0.5);
pointLight.position.set(-5, 5, 5);
scene.add(pointLight);
```

### Step 3: Creating Different Geometries

Now for the fun part - let's create four essential geometry types!

```jsx
// ============================================
// SPHERE GEOMETRY - Perfect for balls, planets, bubbles
// ============================================
const sphereGeometry = new THREE.SphereGeometry(
    1,      // radius
    32,     // widthSegments (more = smoother)
    32      // heightSegments (more = smoother)
);
const sphereMaterial = new THREE.MeshStandardMaterial({
    color: 0xff6b6b,
    metalness: 0.3,
    roughness: 0.4
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(-4.5, 0, 0); // Position on the left
scene.add(sphere);

// ============================================
// CYLINDER GEOMETRY - Great for pillars, cans, tubes
// ============================================
const cylinderGeometry = new THREE.CylinderGeometry(
    1,      // radiusTop
    1,      // radiusBottom
    2,      // height
    32      // radialSegments (more = smoother circular edge)
);
const cylinderMaterial = new THREE.MeshStandardMaterial({
    color: 0x4ecdc4,
    metalness: 0.5,
    roughness: 0.3
});
const cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinder.position.set(-1.5, 0, 0); // Position center-left
scene.add(cylinder);

// ============================================
// CONE GEOMETRY - Perfect for traffic cones, mountains, party hats
// ============================================
const coneGeometry = new THREE.ConeGeometry(
    1,      // radius of base
    2,      // height
    32      // radialSegments
);
const coneMaterial = new THREE.MeshStandardMaterial({
    color: 0xffe66d,
    metalness: 0.2,
    roughness: 0.6
});
const cone = new THREE.Mesh(coneGeometry, coneMaterial);
cone.position.set(1.5, 0, 0); // Position center-right
scene.add(cone);

// ============================================
// TORUS GEOMETRY - Donut shape, great for rings, hoops
// ============================================
const torusGeometry = new THREE.TorusGeometry(
    1,      // radius of torus (donut size)
    0.4,    // tube radius (thickness of donut)
    16,     // radialSegments
    100     // tubularSegments (smoothness around the tube)
);
const torusMaterial = new THREE.MeshStandardMaterial({
    color: 0xa8e6cf,
    metalness: 0.6,
    roughness: 0.2
});
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.set(4.5, 0, 0); // Position on the right
scene.add(torus);
```

## Understanding Geometry Parameters

Let me break down what those numbers in each geometry mean and when you'd adjust them:

### SphereGeometry(radius, widthSegments, heightSegments)

* **radius**: Size of the sphere
    
* **widthSegments/heightSegments**: Higher numbers = smoother sphere, but more performance cost
    
* **Use for**: Planets, balls, bubbles, orbs
    

### CylinderGeometry(radiusTop, radiusBottom, height, radialSegments)

* **radiusTop/radiusBottom**: Make them different to create tapered shapes!
    
* **height**: How tall the cylinder is
    
* **radialSegments**: Higher = smoother circular edges
    
* **Use for**: Pillars, cans, tubes, tree trunks
    

### ConeGeometry(radius, height, radialSegments)

* **radius**: Base size
    
* **height**: How tall the cone is
    
* **radialSegments**: Smoothness of the base circle
    
* **Use for**: Party hats, mountains, traffic cones, arrowheads
    

### TorusGeometry(radius, tube, radialSegments, tubularSegments)

* **radius**: Overall donut size
    
* **tube**: Thickness of the donut ring
    
* **radialSegments/tubularSegments**: Smoothness
    
* **Use for**: Rings, hoops, tire shapes
    

### Step 4: Adding a Reference Grid

Let's add a grid to help visualize the 3D space:

```jsx
// Grid helper - shows the ground plane
const gridHelper = new THREE.GridHelper(20, 20, 0x444444, 0x222222);
gridHelper.position.y = -3;
scene.add(gridHelper);
```

### Step 5: Renderer Setup

```jsx
// Create renderer
const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: true // Smooth edges
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
```

### Step 6: Animation Loop

```jsx
// Animation loop - rotate all objects for better viewing
function animate() {
    requestAnimationFrame(animate);

    // Rotate all geometries on multiple axes
    const time = Date.now() * 0.001; // Convert to seconds

    sphere.rotation.x = time * 0.5;
    sphere.rotation.y = time * 0.7;

    cylinder.rotation.x = time * 0.3;
    cylinder.rotation.y = time * 0.5;

    cone.rotation.x = time * 0.4;
    cone.rotation.y = time * 0.6;

    torus.rotation.x = time * 0.6;
    torus.rotation.y = time * 0.4;

    renderer.render(scene, camera);
}

animate();

// Handle window resize
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});
```

## Complete Code

Here's the full code altogether:

```jsx
import * as THREE from "three";

const canvas = document.getElementById("canvas");

// Scene setup
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a1a);

// Camera setup
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
);
camera.position.set(0, 3, 12);
camera.lookAt(0, 0, 0);

// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 5);
scene.add(directionalLight);

const pointLight = new THREE.PointLight(0x00ffff, 0.5);
pointLight.position.set(-5, 5, 5);
scene.add(pointLight);

// SPHERE
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
const sphereMaterial = new THREE.MeshStandardMaterial({
    color: 0xff6b6b,
    metalness: 0.3,
    roughness: 0.4
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(-4.5, 0, 0);
scene.add(sphere);

// CYLINDER
const cylinderGeometry = new THREE.CylinderGeometry(1, 1, 2, 32);
const cylinderMaterial = new THREE.MeshStandardMaterial({
    color: 0x4ecdc4,
    metalness: 0.5,
    roughness: 0.3
});
const cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinder.position.set(-1.5, 0, 0);
scene.add(cylinder);

// CONE
const coneGeometry = new THREE.ConeGeometry(1, 2, 32);
const coneMaterial = new THREE.MeshStandardMaterial({
    color: 0xffe66d,
    metalness: 0.2,
    roughness: 0.6
});
const cone = new THREE.Mesh(coneGeometry, coneMaterial);
cone.position.set(1.5, 0, 0);
scene.add(cone);

// TORUS
const torusGeometry = new THREE.TorusGeometry(1, 0.4, 16, 100);
const torusMaterial = new THREE.MeshStandardMaterial({
    color: 0xa8e6cf,
    metalness: 0.6,
    roughness: 0.2
});
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.set(4.5, 0, 0);
scene.add(torus);

// Grid helper
const gridHelper = new THREE.GridHelper(20, 20, 0x444444, 0x222222);
gridHelper.position.y = -3;
scene.add(gridHelper);

// Renderer
const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);

// Animation loop
function animate() {
    requestAnimationFrame(animate);

    const time = Date.now() * 0.001;

    sphere.rotation.x = time * 0.5;
    sphere.rotation.y = time * 0.7;

    cylinder.rotation.x = time * 0.3;
    cylinder.rotation.y = time * 0.5;

    cone.rotation.x = time * 0.4;
    cone.rotation.y = time * 0.6;

    torus.rotation.x = time * 0.6;
    torus.rotation.y = time * 0.4;

    renderer.render(scene, camera);
}

animate();

// Resize handler
window.addEventListener('resize', () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
});
```

## When to Use Custom Geometries

You'd create custom geometries when:

1. **You need a specific shape** not available in Three.js built-ins
    
2. **You're loading geometry data** from external sources
    
3. **You want precise control** over every vertex and face
    
4. **Performance matters** and you need optimized shapes
    

Custom geometries are more work, but they give you complete control!

## The Core Concept: It's All Meshes

Here's the beautiful thing I realized - **every 3D object follows the same pattern**:

```jsx
const geometry = new THREE.SomeGeometry(parameters);
const material = new THREE.SomeMaterial({ properties });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
```

Whether it's a built-in sphere or a custom diamond shape, the workflow is identical.

## What I Learned

### 1\. **Geometry is Just Data**

A geometry is really just a bunch of numbers - coordinates for vertices (points) and how they connect to form triangles. Three.js provides built-in geometries so we don't have to calculate these by hand!

### 2\. **Segments Control Smoothness**

All those "segments" parameters? They control how many triangles make up the shape. More triangles = smoother curves, but worse performance. It's always a trade-off!

### 3\. **Every Shape Has Its Use Case**

* **Spheres**: Organic, round objects (planets, balls, bubbles)
    
* **Cylinders**: Structural elements (pillars, cans, tubes)
    
* **Cones**: Directional indicators (arrows, mountains, party hats)
    
* **Torus**: Circular objects with holes (rings, hoops, tires)
    

### 4\. **Material Properties Make It Real**

The same geometry looks entirely different with different materials. The `metalness` and `roughness` properties in `MeshStandardMaterial` are especially powerful for creating realistic surfaces.

### 5\. **The Mesh Pattern is Universal**

Whether it's a sphere or torus, the workflow is always the same. This consistency makes Three.js easy to learn!

### 6\. **Positioning is Key**

Using `position.set(x, y, z)` to arrange objects in your scene is crucial. I arranged mine in a row, but you can create any layout you want - stacks, circles, grids, whatever!

## **The key takeaway?**

**All geometries are just different shapes, but they work the same way.** Once you understand that pattern, you can create anything!

Try building this gallery yourself and experiment with:

* Changing segment counts to see the smoothness difference
    
* Mixing different materials on the same geometries
    
* Positioning shapes in interesting arrangements (maybe a pyramid or circle pattern?)
    
* Animating them in different ways
    

Happy experimenting. 🎨
