Source

Geometry.js

import ContextResource from './ContextResource';
import { VertexFormat, VertexElement } from './VertexFormat';

/**
 * A geometry
 *
 * @category Geometry
 * @extends {ContextResource}
 */
class Geometry extends ContextResource {
    /**
     * Constructor
     */
    constructor() {
        super();

        /**
         * Colors
         *
         * @type {Float32Array}
         * @private
         */
        this.colors = null;

        /**
         * Indices
         *
         * @type {Uint16Array}
         * @private
         */
        this.indices = null;

        /**
         * Normals
         *
         * @type {Float32Array}
         * @private
         */
        this.normals = null;

        /**
         * Positions
         *
         * @type {Float32Array}
         * @private
         */
        this.positions = null;

        /**
         * Uvs
         *
         * @type {Float32Array}
         * @private
         */
        this.uvs = null;

        /**
         * Format
         *
         * @type {VertexFormat}
         * @private
         */
        this.vertexFormat = null;
    }

    /**
     * Set vertices colors
     *
     * @param {Float32Array} colors An array of float values representing colors (r, g, b, a, r, g, b, a, …)
     * @return {Geometry} A reference to the instance
     */
    setColors(colors) {
        this.colors = new Float32Array(colors);

        // Indicates that an attribute of the geometry need an update.
        if (this.vertexFormat) {
            this.vertexFormat.setStreamAsWaitingUpdate(VertexElement.Usage.Color, true);
        }

        return this;
    }

    /**
     * Set indices
     *
     * @param {Uint16Array} indices An array of unsigned integer values representing indices order
     * @return {Geometry} A reference to the instance
     */
    setIndices(indices) {
        this.indices = new Uint16Array(indices);

        // Indicates that indices need an update.
        if (this.vertexFormat) {
            this.vertexFormat.setIndicesAsWaitingUpdate(true);
        }

        return this;
    }

    /**
     * Set vertices normals
     *
     * @param {Float32Array} normals An array of float values representing normals (x, y, z, x, y, z, …)
     * @return {Geometry} A reference to the instance
     */
    setNormals(normals) {
        this.normals = new Float32Array(normals);

        // Indicates that an attribut of the geometry need an update.
        if (this.vertexFormat) {
            this.vertexFormat.setStreamAsWaitingUpdate(VertexElement.Usage.Normal, true);
        }

        return this;
    }

    /**
     * Set vertices positions
     *
     * @param {Float32Array} positions An array of float values representing positions (x, y, z, x, y, z, …)
     * @return {Geometry} A reference to the instance
     */
    setPositions(positions) {
        this.positions = new Float32Array(positions);

        // Indicates that an attribute of the geometry need an update.
        if (this.vertexFormat) {
            this.vertexFormat.setStreamAsWaitingUpdate(VertexElement.Usage.Position, true);
        }

        return this;
    }

    /**
     * Set texture coordinates (uvs) for each vertex
     *
     * @param {Float32Array} uvs An array of float values representing texture coordinates (u, v, u, v, …)
     * @return {Geometry} A reference to the instance
     */
    setTextureUVs(uvs) {
        this.uvs = new Float32Array(uvs);

        // Indicates that an attribute of the geometry need an update
        if (this.vertexFormat) {
            this.vertexFormat.setStreamAsWaitingUpdate(VertexElement.Usage.UVS, true);
        }

        return this;
    }

    /**
     * Set geometry's format
     *
     * @param {VertexFormat} vertexFormat A VertexFormat instance
     * @return {Geometry} A reference to the instance
     */
    setVertexFormat(vertexFormat) {
        this.vertexFormat = vertexFormat;

        return this;
    }

    /**
     * Get format
     *
     * @return {VertexFormat} A VertexFormat instance
     */
    getVertexFormat() {
        return this.vertexFormat;
    }

    /**
     * Return index count
     *
     * @return {number} Indices array's length
     */
    getIndexCount() {
        return this.indices.length;
    }

    /**
     * Return the indices
     *
     * @return {Uint16Array} Indices array
     */
    getIndices() {
        return this.indices;
    }

    /**
     * Return an array with the color for each vertex
     *
     * @return {Float32Array} An array with the format [r, g, b, a, r, g, b, a, …]
     */
    getVerticesColors() {
        return this.colors;
    }

    /**
     * Return an array with the position for each vertex
     *
     * @return {Float32Array} An array with the format [x, y, z, x, y, z, …]
     */
    getVerticesPositions() {
        return this.positions;
    }

    /**
     * Return an array with the normal for each vertex
     *
     * @return {Float32Array} An array with the format [x, y, z, x, y, z, …]
     */
    getVerticesNormals() {
        return this.normals;
    }

    /**
     * Return an array with the texture coordinates for each vertex
     *
     * @return {Float32Array} An array with the format [u, v, u, v, …]
     */
    getVerticesUVs() {
        return this.uvs;
    }

    /**
     * Create a cube
     *
     * @param {number} [width] Width
     * @param {number} [height] Height
     * @param {number} [depth] Depth
     * @return {Geometry} A Geometry instance
     */
    static createCube(width = 1, height = 1, depth = 1) {
        const geometry = new Geometry();

        // Set format
        const format = new VertexFormat();
        format.add(new VertexElement(VertexElement.Usage.Position, 0, VertexElement.Type.Float, 3, false));
        format.add(new VertexElement(VertexElement.Usage.Color, 2, VertexElement.Type.Float, 4, false));
        format.add(new VertexElement(VertexElement.Usage.UVS, 1, VertexElement.Type.Float, 2, false));
        format.add(new VertexElement(VertexElement.Usage.Normal, 3, VertexElement.Type.Float, 3, false));
        geometry.setVertexFormat(format);

        // Set positions
        const positions = new Float32Array([
            -width, -height, depth,
            width, -height, depth,
            width, height, depth,
            -width, height, depth,

            -width, -height, -depth,
            -width, height, -depth,
            width, height, -depth,
            width, -height, -depth,

            -width, height, -depth,
            -width, height, depth,
            width, height, depth,
            width, height, -depth,

            -width, -height, -depth,
            width, -height, -depth,
            width, -height, depth,
            -width, -height, depth,

            width, -height, -depth,
            width, height, -depth,
            width, height, depth,
            width, -height, depth,

            -width, -height, -depth,
            -width, -height, depth,
            -width, height, depth,
            -width, height, -depth,
        ]);
        geometry.setPositions(positions);

        // Set colors
        const colors = new Float32Array([
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,

            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,

            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,

            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,

            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,

            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
        ]);
        geometry.setColors(colors);

        // Texture uvs
        const uvs = new Float32Array([
            0, 0,
            1, 0,
            1, 1,
            0, 1,

            0, 0,
            1, 0,
            1, 1,
            0, 1,

            0, 0,
            1, 0,
            1, 1,
            0, 1,

            0, 0,
            1, 0,
            1, 1,
            0, 1,

            0, 0,
            1, 0,
            1, 1,
            0, 1,

            0, 0,
            1, 0,
            1, 1,
            0, 1,
        ]);
        geometry.setTextureUVs(uvs);

        // Normals
        const normals = new Float32Array([
            0.0, 0.0, 1.0,
            0.0, 0.0, 1.0,
            0.0, 0.0, 1.0,
            0.0, 0.0, 1.0,

            0.0, 0.0, -1.0,
            0.0, 0.0, -1.0,
            0.0, 0.0, -1.0,
            0.0, 0.0, -1.0,

            0.0, 1.0, 0.0,
            0.0, 1.0, 0.0,
            0.0, 1.0, 0.0,
            0.0, 1.0, 0.0,

            0.0, -1.0, 0.0,
            0.0, -1.0, 0.0,
            0.0, -1.0, 0.0,
            0.0, -1.0, 0.0,

            1.0, 0.0, 0.0,
            1.0, 0.0, 0.0,
            1.0, 0.0, 0.0,
            1.0, 0.0, 0.0,

            -1.0, 0.0, 0.0,
            -1.0, 0.0, 0.0,
            -1.0, 0.0, 0.0,
            -1.0, 0.0, 0.0,
        ]);
        geometry.setNormals(normals);

        // Indices.
        const indices = new Uint16Array([0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7,
            8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
            16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23,
        ]);
        geometry.setIndices(indices);

        return geometry;
    }

    /**
     * Create a rectangle
     *
     * @param {number} width Width
     * @param {number} height Height
     * @return {Geometry} A Geometry instance
     */
    static createRectangle(width, height) {
        const geometry = new Geometry();

        // Set format
        const format = new VertexFormat();
        format.add(new VertexElement(VertexElement.Usage.Position, 0, VertexElement.Type.Float, 3, false));
        format.add(new VertexElement(VertexElement.Usage.Color, 1, VertexElement.Type.Float, 4, false));
        format.add(new VertexElement(VertexElement.Usage.UVS, 2, VertexElement.Type.Float, 2, false));
        format.add(new VertexElement(VertexElement.Usage.Normal, 3, VertexElement.Type.Float, 3, false));
        geometry.setVertexFormat(format);

        // Set positions
        const positions = new Float32Array([
            -width, -height, 0,
            -width, height, 0,
            width, -height, 0,
            width, height, 0,
        ]);
        geometry.setPositions(positions);

        // Set colors
        const colors = new Float32Array([
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
            1, 1, 1, 1,
        ]);
        geometry.setColors(colors);

        // Texture uvs
        const uvs = new Float32Array([
            0, 1,
            0, 0,
            1, 1,
            1, 0,
        ]);
        geometry.setTextureUVs(uvs);

        // Normals
        const normals = new Float32Array([
            0.0, 0.0, 1.0,
            0.0, 0.0, 1.0,
            0.0, 0.0, 1.0,
            0.0, 0.0, 1.0,
        ]);
        geometry.setNormals(normals);

        // Indices
        geometry.setIndices(new Uint16Array([0, 2, 1, 3]));

        return geometry;
    }
}

export default Geometry;