Prev: W7, Next: W9
Links: Zoom, ICA Form, Interviews, Calculator:
Slide:

# Meshes

📗 A mesh (not THREE.Mesh, more like THREE.Geometry) is a collection of triangles (called faces). For example, the sphere geometry is approximated by a lot of triangles: Doc. 
➩ The triangles share vertices.
➩ The triangles reuse vertices.
➩ A mesh uses index set representation.

# Built-In Geometries

📗 Some geometries can be constructed from 2D shapes or 3D curves.
➩ THREE.ShapeGeometry produces triangles representing a flat 2D shape (THREE.Shape): Doc.
➩ THREE.ExtrudeGeometry produces triangles representing extruded 2D shape (THREE.Shape): Doc.
➩ THREE.LatheGeometry produces triangles representing a surface of revolution around the Y axis (a list of points in 2D or THREE.Vector2): Doc.
➩ THREE.TubeGeometry produces triangles representing a generalized cylinder (circles moving along a path) along a curve (THREE.Curve): Doc.



# Shape and Extrude Example [ICA]

📗 Create a THREE.Shape for the THREE.ShapeGeometry and the THREE.ExtrudeGeometry: Doc.
📗 The following methods are the same as the ones in 2D (THREE.Shape is a child class of THREE.Path which provides this methods):
➩ THREE.Shape.moveTo(x, y); THREE.Shape.lineTo(x, y);
➩ THREE.Shape.arc(x, y, r, a0, a1); THREE.Shape.ellipse(x, y, rx, ry, a0, a1);
➩ THREE.Shape.quadraticCurveTo(x1, y1, x2, y2); THREE.Shape.bezierCurveTo(x1, y1, x2, y2, x3, y3);
Demo extrude

# Lathe Example [ICA]

📗 Create a list of THREE.Vector2 for the THREE.LatheGeometry.
Demo lathe

# Tube Example

📗 Create a THREE.Curve for the THREE.TubeGeometry.
📗 These are curves in 3D, but similar to 2D curves just with 3 coordinates (points are THREE.Vector3:
➩ THREE.LineCurve3(v1, v2);
➩ THREE.QuadraticBezierCurve3(v1, v2, v3);
➩ THREE.CubicBezierCurve3(v1, v2, v3, v4);
➩ THREE.CatmullRomCurve3([v1, v2, ...], closed, "catmullrom", tension);, default tension is 0.5.
Demo tube



# Good Meshes

📗 Good triangles have the following property:
➩ Not too small.
➩ Not too elongated.
📗 Good meshes have the following property:
➩ Consistency of handedness.
➩ Avoid cracking (share vertices).
➩ Avoid T-junctions.

# Mesh Construction

📗 Write down the index set representation of a square made up of two triangles.
📗 Change the vertex list so that there is a crack.
📗 Change the vertex list so that there is a T-junction.
Demo buffer

# THREE.js Meshes

📗 Information about meshes:
➩ Transformation.
➩ Material.
📗 Information about vertices:
➩ Positions.
➩ Normals.
➩ Colors.



# Buffer Geometry

📗 In THREE.js BufferGeometry is used to store meshes made up of triangles: Doc.
➩ It has efficient representations: typed arrays.
➩ Designed for easy transmission to hardware.
📗 Buffers are blocks of memory organized for efficient transmission and use:
➩ Fixed data type (not dynamic type).
➩ Fixed layout.
📗 In THREE.js, the vertices are stored in THREE.BufferAttribute(new Float32Array([x0, y0, z0, x1, y1, z1, ...], 3), or three floats per vertex: Doc.
📗 Interleaved buffers are buffers with multiple attributes with possibly different types (for example, position, normal, color) in one single array.

# Triangle Soup

📗 Given a list of vertices [x0, y0, z0, x1, y1, z1, ...], the triangles are constructed using an index set [v0, v1, v2, v3, v4, v5, ...] where [v0, v1, v2] are the indices of the first triangle, [v3, v4, v5] are the indices of the second triangle, ...
📗 For example, to create the mesh for let geometry = new THREE.BufferGeometry();,
➩ let vertices = new Float32Array([x0, y0, z0, x1, y1, z1, ...]);
➩ geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
➩ geometry.setIndex(v0, v1, v2, v3, v4, v5, ...);
➩ Non-index geometries are ones where vertices are repeated and the index array is assumed to be 0, 1, 2, 3, 4, 5, ....
📗 Attributes for color and normal can be set in a similar way.



# Polynomial Surfaces

📗 Similar to curve in 2D, surfaces in 3D can be represented by:
➩ Parametric: \(\left(x, y, z\right) = f\left(u, v\right)\).
➩ Implicit: \(f\left(x, y, z\right) = 0\).
➩ Procedural or subdivision.

# Cubic Polynomial Surface

📗 A cubic polynomial surface in parametric form is given by \(f\left(u, v\right) = a_{00} u^{0} v^{0} + a_{01} u^{1} v^{0} + a_{02} u^{2} v^{0} + ... + a_{33} u^{3} v^{3}\).
📗 Bezier surfaces, B-spline surfaces can be defined in a similar way as 2D curves (with basis function and control points).
📗 Subdivision schemes similar to 2D can be used to generate surfaces whose limit surfaces are Bezier or B-spline: Link or Wikipedia.
📗 Not in this course: Professor Sifakis sometimes offers the advanced graphics course CS839: Link.

# More on Subdivision Surfaces

📗 Catmull-Clark subdivision scheme split each face into quadrilaterals (quads): Link.
➩ It splits each triangle into three quads.
➩ It splits each quad into four smaller quads
➩ The quads have the original vertices, midpoints of the original edges, and centers of the original faces.
➩ The limit surface is a \(C\left(2\right)\) B-spline surface (except at some "extraordinary vertices", it is \(C\left(1\right)\).
📗 THREE.js no longer support quads (used to be called THREE.Face4 for quads and THREE.Face3 for triangles).
📗 Loop subdivision scheme uses triangles: Link and (ASU example) Link.
➩ It splits each triangle into four smaller triangles.
➩ The triangles have the original vertices, midpoints of the original edges, and centers of the original faces.
➩ The original vertices are then updated to be the weighted average of the neighboring vertices.
➩ The limit surface is a \(C\left(2\right)\) B-spline surface (except at some "extraordinary vertices", it is \(C\left(1\right)\).
📗 This can be done in THREE.js: Link.



# Loop Subdivision

📗 The "midpoint" of an edge \(AB\) is not always \(\dfrac{1}{2} A + \dfrac{1}{2} B\), for interior edges, where two triangles \(ABC\) and \(ABD\) share the edge \(AB\), the "midpoint" is defined as \(\dfrac{3}{8} A + \dfrac{3}{8} B + \dfrac{1}{8} C + \dfrac{1}{8} D\).
📗 For each vertex \(v\), it is updated to the weighted average of its neighbors \(v_{1}, v_{2}, ..., v_{n}\) (i.e. vertices with an edge connecting to \(v\)), by \(v' = \left(1 - n \beta\right) v + \beta \displaystyle\sum_{i=1}^{n} v_{i}\). Examples of \(\beta\):
➩ \(\beta = \dfrac{3}{16}\) if \(n = 3\) and \(\beta = \dfrac{3}{8 n}\) otherwise.
➩ \(\beta = \dfrac{1}{n} \left(\dfrac{5}{8} - \left(\dfrac{3}{8} + \dfrac{1}{4} \cos\left(\dfrac{2 \pi}{n}\right)\right)^{2}\right)\), in Loop's original paper.
Demo subdivision

# Catmull-Clark Subdivision

📗 The "midpoint" of an edge \(AB\) for interior edges between \(ABCD\) and \(ABEF\) is \(\dfrac{1}{4} \left(A + B + \dfrac{1}{4} \left(A + B + C + D\right) + \dfrac{1}{4} \left(A + B + E + F\right)\right.\).
📗 The vertex update formula (Catmull-Clark formula) is \(v' = \dfrac{f + 2 r + \left(n - 3\right) v}{n}\) where \(f\) is the face average and \(r\) is the edge average.

# Other Subdivision Schemes

📗 Modified butterfly subdivision: interpolating (all surfaces pass through the original vertices).
📗 \(\sqrt{3}\) subdivision: split a triangle into three triangles sharing the centroid vertex.



# Morphing

📗 Blending between multiple different meshes (sets of vertices) is called morphing: Wikipedia.
📗 Multiple meshes can be stored in the same geometry as morph targets.
📗 All meshes are sent to the hardware, and vertex interpolation is done between targets by changing the weights: \(p = w_{1} p_{1} + w_{2} p_{2} + w_{3} p_{3} + ...\) is the position of a vertex given the positions of the same vertex in 3 (or more) morph targets.
📗 In THREE.js, THREE.Mesh has properties THREE.Mesh.morphTargetDictionary (list of morph targets) and THREE.Mesh.morphTargetInfluences (weights on each morph target). An example: Link.

# Morph a Sphere [ICA]

📗 Compute the morph target (only one) to morph the sphere to a flat circle.
Demo morph

# Spot the Cow [ICA]

📗 Spot the cow: Link.
Demo morph_cow



# Skinning

📗 Transformation of a mesh apply to all vertices at the same time.
📗 There is limited animations that can be done with simple transformations.
📗 It is possible to apply multiple different transformations to different vertices of a single mesh, called skinning: Wikipedia.
➩ Pass multiple transformation matrices (matrix palette).
➩ Each vertex specifies which matrix it is part of (can be a vector of weights, which allows blending).
➩ A vertex can be in multiple transformations (multiple coordinate systems, weighted): \(p = w_{1} M_{1} p_{0} + w_{2} M_{2} p_{0} = \left(w_{1} M_{1} + w_{2} M_{2}\right) p_{0}\).
📗 Note: if \(M_{1}, M_{2}\) are rotations, \(w_{1} M_{1} + w_{2} M_{2}\) may not be a rotation, which could lead to artifacts.
📗 In THREE.js, THREE.SkinnedMesh can be used: Doc.

# Transformation Weights

📗 In Three.js a Bone represents the endpoint of a bone segment, and Three.js allows a maximum of 4 Bones to influence any vertex.
➩ The weights can be assigned manually based on vertex positions.
➩ The weights can be assigned automatically based on the distances to the Bones (the nearest 4 Bones), for example, \(w_{i} = \dfrac{\dfrac{1}{d_{i} + \varepsilon}}{\dfrac{1}{d_{1} + \varepsilon} + \dfrac{1}{d_{2} + \varepsilon} + \dfrac{1}{d_{3} + \varepsilon} + \dfrac{1}{d_{4} + \varepsilon}}\) for Bone i. The \(\varepsilon\) is added in case \(d_{i} = 0\).
Demo skinned
Demo skinned_cow

# Lecture Summary

📗 Triangle meshes
📗 Buffer geometries
📗 Vertex positions, colors, normals
📗 Surfaces and curves in 3D
📗 Polynomial surfaces
📗 Skinning and morphing


📗 Notes and code adapted from the course taught by Professor Michael Gleicher.
📗 If ICA submission does not work or in case of accidental submission by mistake, please use this form: Form.
📗 Please use Ctrl+F5 or Shift+F5 or Shift+Command+R or Incognito mode or Private Browsing to refresh the cached JavaScript: Code.
📗 You can expand all the examples and demos: , or print the notes: .

Prev: W7, Next: W9





Last Updated: October 21, 2026 at 4:11 AM