Convert SVG to 3D Paths with Three.js SVGLoader
This article explains how Three.js utilizes the
SVGLoader utility to translate two-dimensional XML-based
SVG data into three-dimensional geometry. We will explore the
step-by-step pipeline of parsing vector paths, converting them into 2D
shapes, and finally extruding those shapes into 3D meshes using
ExtrudeGeometry.
1. Parsing the SVG XML Data
The process begins when SVGLoader loads and parses an
SVG file. The loader scans the XML document for vector elements such as
<path>, <rect>,
<circle>, <ellipse>,
<line>, <polyline>, and
<polygon>.
For each vector element found, SVGLoader reads its
geometric attributes (like the d attribute in paths) and
style properties (such as fill color, stroke color, and opacity). It
then translates these elements into an array of SVGResult
objects, containing paths represented as Three.js
ShapePath instances.
2. Converting Vector Commands to ShapePaths
A ShapePath is a 2D representation in Three.js that
supports drawing commands similar to the HTML5 Canvas 2D Context.
SVGLoader translates standard SVG path commands into
Three.js drawing commands:
- M / m (Move to): Translated to
ShapePath.moveTo() - L / l (Line to): Translated to
ShapePath.lineTo() - C / c (Cubic Bezier Curve): Translated to
ShapePath.bezierCurveTo() - S / s (Smooth Cubic Bezier): Computed and converted
to
ShapePath.bezierCurveTo() - Q / q (Quadratic Bezier Curve): Translated to
ShapePath.quadraticCurveTo() - A / a (Elliptical Arc): Translated using mathematical approximations to native curves.
These commands construct a series of sub-paths within each
ShapePath object.
3. Extracting 2D Shapes and Handling Holes
To extrude geometry, Three.js requires solid 2D shapes.
SVGLoader converts the raw ShapePath data into
an array of Shape objects using the toShapes()
method:
const shapes = SVGPath.toShapes(isCCW);During this conversion, Three.js determines which paths are solid contours and which are “holes” (cutouts inside the shapes). This is achieved using path winding rules (clockwise versus counter-clockwise orientation):
- Solid shapes are defined by outer boundaries drawn in one direction.
- Holes are identified by nested paths drawn in the opposite direction.
- The
toShapes()method automatically associates the hole paths with their parent outer shapes, creating a hierarchy ofShapeobjects with populated.holesarrays.
4. Extruding Shapes into 3D Geometry
Once the 2D Shape objects are generated, they can be
transformed into 3D meshes using ExtrudeGeometry. This
geometry generator takes the 2D contours and projectively extends them
along the Z-axis.
const geometry = new THREE.ExtrudeGeometry(shapes, {
depth: 20, // How far to extrude the 2D shape along the Z-axis
bevelEnabled: true, // Adds a bevel to the edges
bevelThickness: 1,
bevelSize: 0.5,
bevelSegments: 3
});ExtrudeGeometry performs two main operations: 1.
Triangulating the 2D Face: It uses a triangulation
algorithm (such as Earcut) to fill the 2D shape (including any holes)
with flat triangles for the front and back caps. 2. Generating
Side Walls: It creates rectangular vertical strips of triangles
connecting the front cap vertices to the offset back cap vertices along
the extrusion depth.
5. Rendering the 3D Mesh
The final step is to combine the generated
ExtrudeGeometry with a material (such as
MeshStandardMaterial) and add it to the Three.js scene as a
Mesh.
Because SVGs use a 2D coordinate system where the Y-axis points downwards, the extruded 3D model will initially appear upside down in the Three.js 3D space. To correct this, developers typically invert the Y-axis or rotate the final mesh 180 degrees around the X-axis.