Skip to content

⬅️ Back to Table of Contents

📄 BoxGeometry.js

📊 Analysis Summary

Metric Count
🔧 Functions 3
🧱 Classes 1
📦 Imports 3
📊 Variables & Constants 23

📚 Table of Contents

🛠️ File Location:

📂 src/geometries/BoxGeometry.js

📦 Imports

Name Source
BufferGeometry ../core/BufferGeometry.js
Float32BufferAttribute ../core/BufferAttribute.js
Vector3 ../math/Vector3.js

Variables & Constants

Name Type Kind Value Exported
scope this let/var this
indices any[] let/var []
vertices any[] let/var []
normals any[] let/var []
uvs any[] let/var []
numberOfVertices number let/var 0
groupStart number let/var 0
segmentWidth number let/var width / gridX
segmentHeight number let/var height / gridY
widthHalf number let/var width / 2
heightHalf number let/var height / 2
depthHalf number let/var depth / 2
gridX1 any let/var gridX + 1
gridY1 any let/var gridY + 1
vertexCounter number let/var 0
groupCount number let/var 0
vector Vector3 let/var new Vector3()
y number let/var iy * segmentHeight - heightHalf
x number let/var ix * segmentWidth - widthHalf
a number let/var numberOfVertices + ix + gridX1 * iy
b number let/var numberOfVertices + ix + gridX1 * ( iy + 1 )
c number let/var numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 )
d number let/var numberOfVertices + ( ix + 1 ) + gridX1 * iy

Functions

BoxGeometry.copy(source: any): this

Parameters:

  • source any

Returns: this

Calls:

  • super.copy
  • Object.assign
Code
copy( source ) {

        super.copy( source );

        this.parameters = Object.assign( {}, source.parameters );

        return this;

    }

BoxGeometry.fromJSON(data: any): BoxGeometry

JSDoc:

/**
     * Factory method for creating an instance of this class from the given
     * JSON object.
     *
     * @param {Object} data - A JSON object representing the serialized geometry.
     * @return {BoxGeometry} A new instance.
     */

Parameters:

  • data any

Returns: BoxGeometry

Code
static fromJSON( data ) {

        return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );

    }

buildPlane(u: any, v: any, w: any, udir: any, vdir: any, width: any, height: any, depth: any, gridX: any, gridY: any, materialIndex: any): void

Parameters:

  • u any
  • v any
  • w any
  • udir any
  • vdir any
  • width any
  • height any
  • depth any
  • gridX any
  • gridY any
  • materialIndex any

Returns: void

Calls:

  • vertices.push
  • normals.push
  • uvs.push
  • indices.push
  • scope.addGroup

Internal Comments:

// generate vertices, normals and uvs
// set values to correct vector component (x8)
// now apply vector to vertex buffer (x4)
// now apply vector to normal buffer (x4)
// uvs (x4)
// counters (x3)
// indices
// 1. you need three indices to draw a single face
// 2. a single segment consists of two faces
// 3. so we need to generate six (2*3) indices per segment
// faces (x4)
// increase counter (x3)
// add a group to the geometry. this will ensure multi material support (x4)
// calculate new start value for groups (x3)
// update total number of vertices (x3)

Code
function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {

            const segmentWidth = width / gridX;
            const segmentHeight = height / gridY;

            const widthHalf = width / 2;
            const heightHalf = height / 2;
            const depthHalf = depth / 2;

            const gridX1 = gridX + 1;
            const gridY1 = gridY + 1;

            let vertexCounter = 0;
            let groupCount = 0;

            const vector = new Vector3();

            // generate vertices, normals and uvs

            for ( let iy = 0; iy < gridY1; iy ++ ) {

                const y = iy * segmentHeight - heightHalf;

                for ( let ix = 0; ix < gridX1; ix ++ ) {

                    const x = ix * segmentWidth - widthHalf;

                    // set values to correct vector component

                    vector[ u ] = x * udir;
                    vector[ v ] = y * vdir;
                    vector[ w ] = depthHalf;

                    // now apply vector to vertex buffer

                    vertices.push( vector.x, vector.y, vector.z );

                    // set values to correct vector component

                    vector[ u ] = 0;
                    vector[ v ] = 0;
                    vector[ w ] = depth > 0 ? 1 : - 1;

                    // now apply vector to normal buffer

                    normals.push( vector.x, vector.y, vector.z );

                    // uvs

                    uvs.push( ix / gridX );
                    uvs.push( 1 - ( iy / gridY ) );

                    // counters

                    vertexCounter += 1;

                }

            }

            // indices

            // 1. you need three indices to draw a single face
            // 2. a single segment consists of two faces
            // 3. so we need to generate six (2*3) indices per segment

            for ( let iy = 0; iy < gridY; iy ++ ) {

                for ( let ix = 0; ix < gridX; ix ++ ) {

                    const a = numberOfVertices + ix + gridX1 * iy;
                    const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
                    const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
                    const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;

                    // faces

                    indices.push( a, b, d );
                    indices.push( b, c, d );

                    // increase counter

                    groupCount += 6;

                }

            }

            // add a group to the geometry. this will ensure multi material support

            scope.addGroup( groupStart, groupCount, materialIndex );

            // calculate new start value for groups

            groupStart += groupCount;

            // update total number of vertices

            numberOfVertices += vertexCounter;

        }

Classes

BoxGeometry

Class Code
class BoxGeometry extends BufferGeometry {

    /**
     * Constructs a new box geometry.
     *
     * @param {number} [width=1] - The width. That is, the length of the edges parallel to the X axis.
     * @param {number} [height=1] - The height. That is, the length of the edges parallel to the Y axis.
     * @param {number} [depth=1] - The depth. That is, the length of the edges parallel to the Z axis.
     * @param {number} [widthSegments=1] - Number of segmented rectangular faces along the width of the sides.
     * @param {number} [heightSegments=1] - Number of segmented rectangular faces along the height of the sides.
     * @param {number} [depthSegments=1] - Number of segmented rectangular faces along the depth of the sides.
     */
    constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {

        super();

        this.type = 'BoxGeometry';

        /**
         * Holds the constructor parameters that have been
         * used to generate the geometry. Any modification
         * after instantiation does not change the geometry.
         *
         * @type {Object}
         */
        this.parameters = {
            width: width,
            height: height,
            depth: depth,
            widthSegments: widthSegments,
            heightSegments: heightSegments,
            depthSegments: depthSegments
        };

        const scope = this;

        // segments

        widthSegments = Math.floor( widthSegments );
        heightSegments = Math.floor( heightSegments );
        depthSegments = Math.floor( depthSegments );

        // buffers

        const indices = [];
        const vertices = [];
        const normals = [];
        const uvs = [];

        // helper variables

        let numberOfVertices = 0;
        let groupStart = 0;

        // build each side of the box geometry

        buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px
        buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx
        buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py
        buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny
        buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz
        buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz

        // build geometry

        this.setIndex( indices );
        this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
        this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
        this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );

        function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {

            const segmentWidth = width / gridX;
            const segmentHeight = height / gridY;

            const widthHalf = width / 2;
            const heightHalf = height / 2;
            const depthHalf = depth / 2;

            const gridX1 = gridX + 1;
            const gridY1 = gridY + 1;

            let vertexCounter = 0;
            let groupCount = 0;

            const vector = new Vector3();

            // generate vertices, normals and uvs

            for ( let iy = 0; iy < gridY1; iy ++ ) {

                const y = iy * segmentHeight - heightHalf;

                for ( let ix = 0; ix < gridX1; ix ++ ) {

                    const x = ix * segmentWidth - widthHalf;

                    // set values to correct vector component

                    vector[ u ] = x * udir;
                    vector[ v ] = y * vdir;
                    vector[ w ] = depthHalf;

                    // now apply vector to vertex buffer

                    vertices.push( vector.x, vector.y, vector.z );

                    // set values to correct vector component

                    vector[ u ] = 0;
                    vector[ v ] = 0;
                    vector[ w ] = depth > 0 ? 1 : - 1;

                    // now apply vector to normal buffer

                    normals.push( vector.x, vector.y, vector.z );

                    // uvs

                    uvs.push( ix / gridX );
                    uvs.push( 1 - ( iy / gridY ) );

                    // counters

                    vertexCounter += 1;

                }

            }

            // indices

            // 1. you need three indices to draw a single face
            // 2. a single segment consists of two faces
            // 3. so we need to generate six (2*3) indices per segment

            for ( let iy = 0; iy < gridY; iy ++ ) {

                for ( let ix = 0; ix < gridX; ix ++ ) {

                    const a = numberOfVertices + ix + gridX1 * iy;
                    const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
                    const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
                    const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;

                    // faces

                    indices.push( a, b, d );
                    indices.push( b, c, d );

                    // increase counter

                    groupCount += 6;

                }

            }

            // add a group to the geometry. this will ensure multi material support

            scope.addGroup( groupStart, groupCount, materialIndex );

            // calculate new start value for groups

            groupStart += groupCount;

            // update total number of vertices

            numberOfVertices += vertexCounter;

        }

    }

    copy( source ) {

        super.copy( source );

        this.parameters = Object.assign( {}, source.parameters );

        return this;

    }

    /**
     * Factory method for creating an instance of this class from the given
     * JSON object.
     *
     * @param {Object} data - A JSON object representing the serialized geometry.
     * @return {BoxGeometry} A new instance.
     */
    static fromJSON( data ) {

        return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );

    }

}

Methods

copy(source: any): this
Code
copy( source ) {

        super.copy( source );

        this.parameters = Object.assign( {}, source.parameters );

        return this;

    }
fromJSON(data: any): BoxGeometry
Code
static fromJSON( data ) {

        return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );

    }