Geometry
1. Digest
Geometry forms the foundation of all 3D shapes in Three.js, defining the structure and form of meshes through vertices, faces, and mathematical parameters. This module explores both built-in geometry types and advanced vertex-level manipulation techniques to create dynamic, animated 3D forms.
Starting with basic geometries like BoxGeometry and SphereGeometry, you'll learn how to leverage Three.js's extensive geometry library alongside OrbitControls for interactive 3D navigation. The module then advances into vertex manipulation, demonstrating how to access and modify the raw position data that defines geometry shapes. Through practical examples, you'll create organic, wave-like animations by manipulating individual vertex positions in real-time, using techniques like sine wave mathematics combined with randomization to produce natural-looking deformations. This approach opens up possibilities for creating procedural animations, terrain generation, and morphing effects that go beyond static 3D models.
2. What is the purpose
The purpose of this chapter is to build a solid understanding of Three.js geometry fundamentals and vertex manipulation techniques. You'll learn how to work with built-in geometry primitives, understand the structure of geometry data at the vertex level, and create dynamic animations through direct manipulation of vertex positions.
Key learning objectives include:
- Understanding Three.js's various geometry types and their parameters
- Implementing OrbitControls for interactive 3D scene navigation
- Accessing and modifying geometry vertex position arrays
- Creating organic, procedural animations through mathematical transformations
- Understanding the relationship between geometry attributes and rendering updates
These skills are essential for creating interactive 3D visualizations, animated effects, procedural generation systems, and any application requiring dynamic mesh manipulation beyond static models.
3. Some code block and its explanation
Example 1: Basic Geometry Setup with OrbitControls
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
// Mesh with basic geometry
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({
color: 'hotpink',
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Controls for camera navigation
const controls = new OrbitControls(camera, renderer.domElement);
This example demonstrates the fundamental setup for working with geometries in Three.js. The BoxGeometry creates a cube with dimensions 1x1x1, paired with MeshStandardMaterial that responds to lighting. The DoubleSide parameter ensures both front and back faces are rendered. The OrbitControls provides intuitive mouse-based camera control, allowing users to rotate, zoom, and pan around the 3D scene - essential for inspecting geometry from all angles during development.
Example 2: Accessing Vertex Position Data
const geometry = new THREE.SphereGeometry(5, 64, 64);
const positionArray = geometry.attributes.position.array;
const randomArray = []
for(let i = 0; i < positionArray.length; i+=3) {
randomArray[i] = (Math.random()-0.5)*0.2
randomArray[i+1] = (Math.random()-0.5)*0.2
randomArray[i+2] = (Math.random()-0.5)*0.2
}
This code reveals how to access the underlying vertex data of any Three.js geometry. The geometry.attributes.position.array contains all vertex positions as a flat array where every three consecutive values represent x, y, z coordinates of a single vertex. By iterating through this array in steps of 3 (i+=3), we process each vertex individually. The randomArray stores random offsets for each vertex, which will be used to create variation in animation - this technique is fundamental for procedural effects and ensures each vertex moves uniquely.
Example 3: Real-time Vertex Animation
function draw() {
const time = clock.getElapsedTime();
for (let i = 0; i < positionArray.length; i += 3) {
positionArray[i] += Math.sin(time*3+randomArray[i]*50) * 0.002;
positionArray[i + 1] += Math.sin(time*3+randomArray[i+1]*50) * 0.002;
positionArray[i + 2] += Math.sin(time*3+randomArray[i+2]*50) * 0.002;
}
geometry.attributes.position.needsUpdate = true;
renderer.render(scene, camera);
window.requestAnimationFrame(draw);
}
This animation loop creates organic, wave-like motion by modifying vertex positions every frame. The Math.sin() function produces smooth oscillating values, with time*3 controlling the wave speed and randomArray[i]*50 creating phase shifts so each vertex oscillates at slightly different times. The multiplication by 0.002 keeps the movement subtle and realistic. Critically, geometry.attributes.position.needsUpdate = true must be set after modifying vertex data to signal Three.js that the GPU buffer needs updating - without this, changes won't be visible. This technique demonstrates the power of vertex-level manipulation for creating effects like water surfaces, terrain deformation, or morphing animations.
Example 4: Enhanced Material Properties for Geometry
const material = new THREE.MeshStandardMaterial({
color: 'orangered',
side: THREE.DoubleSide,
flatShading: true
})
Material properties significantly affect how geometry is rendered. The flatShading: true option creates a faceted, low-poly aesthetic by calculating lighting per face rather than per vertex, making individual triangles clearly visible. This is particularly effective when combined with vertex animation, as it emphasizes the geometric structure and creates a stylized visual effect. The MeshStandardMaterial ensures the geometry responds realistically to the ambient and directional lights in the scene, creating depth and dimensionality that makes 3D forms more readable and visually appealing.