DeepWiki
BabylonJS/Babylon.js
explain how rebuildNormals in CSG2.toVertexData works.
Deep

How rebuildNormals Works in CSG2.toVertexData

The rebuildNormals option in CSG2.toVertexData() is a boolean parameter that controls whether the Manifold library recalculates surface normals for the resulting geometry.

Configuration

The rebuildNormals parameter is defined in the IVertexDataRebuildOptions interface and defaults to false when not specified. csg2.ts:78-83 csg2.ts:176-179

Mechanism

When rebuildNormals is enabled, the method checks if a normal component exists in the vertex structure. If both conditions are met, it passes the array [3, 4, 5] to the Manifold library's getMesh() method: csg2.ts:181-182

These indices [3, 4, 5] specify the positions in the vertex property array where the normals should be stored. This is based on the vertex structure layout where:

  • Indices 0, 1, 2 contain position data (x, y, z)
  • Indices 3, 4, 5 contain normal data (nx, ny, nz) csg2.ts:341-342 csg2.ts:357-359

Data Extraction

After the Manifold library processes the mesh, the method extracts the vertex data (including the recalculated normals if requested) from the returned manifoldMesh.vertProperties array and distributes it to the appropriate vertex buffers: csg2.ts:195-207

Notes

  • The rebuildNormals option only takes effect if the source geometry already has normals in its vertex structure. If no normal component exists, passing [3, 4, 5] would be meaningless, so the method passes undefined instead.
  • This same option is also available in the CSG2.toMesh() method, which internally calls toVertexData().
  • The recalculation is performed by the Manifold library (a WebAssembly-based geometry processing library), not by Babylon.js itself.
75/**
76 * Interface to customize the vertex data rebuild options
77 */
78export interface IVertexDataRebuildOptions {
79    /**
80     * Rebuild normals
81     */
82    rebuildNormals?: boolean;
83}
84
85interface IManifoldMesh {
86    numProp: number;
173     * @returns a new vertex data
174     */
175    public toVertexData(options?: Partial<IVertexDataRebuildOptions>): VertexData {
176        const localOptions = {
177            rebuildNormals: false,
178            ...options,
179        };
180        const vertexData = new VertexData();
181        const normalComponent = this._vertexStructure.find((c) => c.kind === VertexBuffer.NormalKind);
182        const manifoldMesh: IManifoldMesh = this._manifold.getMesh(localOptions.rebuildNormals && normalComponent ? [3, 4, 5] : undefined);
183
184        vertexData.indices = manifoldMesh.triVerts.length > 65535 ? new Uint32Array(manifoldMesh.triVerts) : new Uint16Array(manifoldMesh.triVerts);
185
192        const vertexCount = manifoldMesh.vertProperties.length / manifoldMesh.numProp;
193
194        // Attributes
195        let offset = 0;
196        for (let componentIndex = 0; componentIndex < this._vertexStructure.length; componentIndex++) {
197            const component = this._vertexStructure[componentIndex];
198
199            const data = new Float32Array(vertexCount * component.stride);
200            for (let i = 0; i < vertexCount; i++) {
201                for (let strideIndex = 0; strideIndex < component.stride; strideIndex++) {
202                    data[i * component.stride + strideIndex] = manifoldMesh.vertProperties[i * manifoldMesh.numProp + offset + strideIndex];
203                }
204            }
205            vertexData.set(data, component.kind);
206            offset += component.stride;
207        }
208
209        // Rebuild mesh from vertex data
210        return vertexData;
338        }
339
340        const tempVector3 = new Vector3();
341        let numProp = 3;
342        const structure: IManifoldVertexComponent[] = [{ stride: 3, kind: VertexBuffer.PositionKind }];
343
344        if (!worldMatrix) {
345            structure[0].data = data.positions!;
354
355        // Normals
356        const sourceNormals = data.normals!;
357        if (sourceNormals) {
358            numProp += 3;
359            structure.push({ stride: 3, kind: VertexBuffer.NormalKind });
360            if (!worldMatrix) {
361                structure[1].data = sourceNormals;
362            } else {
BabylonJS/Babylon.js
explain how rebuildNormals in CSG2.toVertexData works.
Codemap
CSG2.toVertexData rebuildNormals Flow

This codemap traces the rebuildNormals functionality in CSG2.toVertexData(), showing how the option triggers normal recalculation in the Manifold library when conditions are met. Key flow includes option processing , normal component detection , and the critical Manifold library call that receives the normal indices [3,4,5] for rebuilding.

AI generated guide

Motivation

When performing boolean operations (union, subtraction, intersection) on 3D meshes using the Manifold library, the resulting geometry often has incorrect or missing surface normals. Normals are crucial for proper lighting and shading. The rebuildNormals option provides a way to automatically recalculate these normals after operations, ensuring the final mesh renders correctly with proper lighting.

Details

The toVertexData() method accepts an optional rebuildNormals parameter that defaults to false . Before triggering the rebuild, the system first checks if the source geometry actually contains normals by searching for a normal component in the vertex structure . If both conditions are met (rebuildNormals is true AND normals exist), the method passes the array [3, 4, 5] to the Manifold library's getMesh() method . These indices specify that normals should be stored at positions 3, 4, and 5 in each vertex's property array (following the 3 position values at indices 0, 1, 2). The Manifold library then performs the actual normal recalculation using its WebAssembly-based geometry processing engine.

Process rebuildNormals option
Call Manifold library
BabylonJS/Babylon.js
explain how normals are recalculated when rebuildNormals = true
Codemap
CSG2 Normal Recalculation Flow

This codemap traces the complete flow of normal recalculation in CSG2 when rebuildNormals = true, from option processing through Manifold WebAssembly processing to final vertex data extraction. Key locations include the critical Manifold library call , the data extraction loop , and comparison with traditional Babylon.js normal computation .

AI generated guide

Motivation

When performing boolean operations (union, subtraction, intersection) on 3D meshes using the Manifold library, the resulting geometry often has incorrect or missing surface normals. Normals are crucial for proper lighting and shading - without them, meshes appear flat or have distorted lighting. The rebuildNormals option provides a way to automatically recalculate these normals after operations, ensuring the final mesh renders correctly with proper lighting.

Details

The toVertexData() method accepts an optional rebuildNormals parameter that defaults to false . Before triggering the rebuild, the system first checks if the source geometry actually contains normals by searching for a normal component in the vertex structure . This prevents unnecessary processing when normals don't exist.

If both conditions are met (rebuildNormals is true AND normals exist), the method passes the array [3, 4, 5] to the Manifold library's getMesh() method . These indices specify that normals should be stored at positions 3, 4, and 5 in each vertex's property array (following the 3 position values at indices 0, 1, 2).

The Manifold library is loaded as a WebAssembly module from an external CDN , providing high-performance geometry processing. This external library performs the actual normal recalculation using sophisticated algorithms that are more robust than Babylon.js's built-in normal computation, especially for complex geometries resulting from boolean operations.

toVertexData() method entry
Library Initialization
Load WebAssembly module
Setup Manifold instance
AI generated guide

Motivation

When you perform boolean operations (union, subtraction, intersection) on 3D meshes, the resulting geometry often has incorrect or missing surface normals. Normals are crucial for proper lighting and shading - without correct normals, your mesh will look dark, shiny in wrong places, or have completely broken lighting. The CSG2 system solves this by automatically recalculating normals using the sophisticated Manifold WebAssembly library when you set rebuildNormals = true.

Details

The extraction process starts by calculating how many vertices exist from Manifold's internal vertex property array . Then it systematically extracts each type of vertex data (positions, normals, UVs, etc.) from Manifold's flat property array and organizes them into separate Babylon.js vertex buffers .

For normals specifically, the system knows they occupy 3 slots (x,y,z) in the vertex structure and extracts the recalculated normal values accordingly. The extraction loop creates properly sized arrays for each vertex component, copies the data from Manifold's format into Babylon.js format, and sets the data on the VertexData object . Finally, the complete VertexData object containing positions, recalculated normals, and other attributes is returned for use in creating meshes .

This approach leverages Manifold's advanced geometry processing algorithms which are specifically designed to handle the complex topology changes that occur during boolean operations, producing much more reliable normals than traditional face-based computation methods.

Extract data from Manifold
Loop through vertex components
Create data arrays for each component
Set data in vertexData object
AI generated guide

Motivation

When 3D meshes undergo complex geometric operations like boolean unions or subtractions, their surface normals often become incorrect or inconsistent. Normals are crucial for proper lighting and shading - incorrect normals make meshes appear dark, flat, or lit from wrong angles. Babylon.js provides a traditional normal computation method that works well for simple meshes but can produce artifacts on complex geometries resulting from boolean operations.

Details

Babylon.js computes surface normals using a classic geometric approach . The process systematically processes each triangle face in the mesh:

  1. Edge Vector Calculation: For each triangle, two edge vectors are computed by subtracting vertex positions . These vectors define the plane orientation of the face.

  2. Face Normal Computation: The cross product of these edge vectors yields a perpendicular vector - the face normal . This vector is then normalized to unit length.

  3. Normal Accumulation: Each face normal is accumulated to its three constituent vertices . This averaging process creates smooth transitions across adjacent faces.

  4. Final Normalization: All accumulated vertex normals are normalized to ensure consistent lighting behavior .

While this algorithm is mathematically sound and efficient for simple geometries, it struggles with the complex topology changes that occur during boolean operations. This is why CSG2 delegates normal recalculation to the specialized Manifold library when rebuildNormals = true, which uses more sophisticated algorithms better suited for post-boolean geometry.

Reset normals array to zeros
For each triangle face
p1p2 = v1 - v2
p3p2 = v3 - v2
Normalize face normal
Add to vertex 1 normal
Add to vertex 2 normal
Add to vertex 3 normal
For each vertex
Calculate magnitude
Divide by magnitude
Return normalized normals
(cache)Search | DeepWiki