API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/examples/js/models/testModel.js

/**
 A **TestModel** is a procedurally-generated test {{#crossLink "Model"}}{{/crossLink}} containing {{#crossLink "Mesh"}}Meshes{{/crossLink}} that represent city buildings.

 <a href="../../examples/#models_generation_TestModel"><img src="http://i.giphy.com/l0HlPJO1AN01Lz27e.gif"></img></a>

 ## Overview

 * Procedurally generates simple content for development and testing.
 * Allows you to develop some basic capabilities of your app without needing to load any models.

 It inherits these capabilities from its {{#crossLink "Model"}}{{/crossLink}} base class:

 * Allows you to access and manipulate the components within it.
 * Can be transformed within World-space by attaching it to a {{#crossLink "Transform"}}{{/crossLink}}.
 * Provides its dynamic World-space axis-aligned boundary.

 ## Examples

 * TODO

 ## Usage

 ````javascript
 var model = new xeogl.TestModel({
     id: "myModel",
     size: 5000, // Width of each axis
     density: 4 // How many buildings on each axis
 });
 ````

 @class TestModel
 @module xeogl
 @submodule models
 @constructor
 @param [scene] {Scene} Parent {{#crossLink "Scene"}}Scene{{/crossLink}} - creates this TestModel in the default
 {{#crossLink "Scene"}}Scene{{/crossLink}} when omitted.
 @param [cfg] {*} Configs
 @param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}},
 generated automatically when omitted.
 @param [cfg.entityType] {String} Optional entity classification when using within a semantic data model. See the {{#crossLink "Object"}}{{/crossLink}} documentation for usage.
 @param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this TestModel.
 @param [cfg.size] {Number} World-space width of each axis.
 @param [cfg.density] {Number} Number of buildings on each axis.
 @param [cfg.position=[0,0,0]] {Float32Array} The TestModel's local 3D position.
 @param [cfg.scale=[1,1,1]] {Float32Array} The TestModel's local scale.
 @param [cfg.rotation=[0,0,0]] {Float32Array} The TestModel's local rotation, as Euler angles given in degrees.
 @param [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] {Float32Array} The TestModel's local transform matrix. Overrides the position, scale and rotation parameters.
 @extends Model
 */
xeogl.TestModel = class xeoglTestModel extends xeogl.BuildableModel {

    init(cfg) {
        super.init(cfg);
        this._generate(cfg);
    }

    _generate(options) {

        this.destroyAll();

        options = options || {};

        // Create some geometry and material assets

        this.createAsset("box", {
            type: "xeogl.BoxGeometry",
            xSize: 1,
            ySize: 1,
            zSize: 1
        });

        this.createAsset("asphalt", {
            type: "xeogl.LambertMaterial",
            diffuse: [0.2, 0.2, 0.2],
            ambient: [0.2, 0.2, 0.2],
            specular: [0.0, 0.0, 0.0]
        });

        this.createAsset("lightConcrete", {
            type: "xeogl.LambertMaterial",
            diffuse: [0.6, 0.6, 0.6],
            ambient: [0.2, 0.2, 0.2]
        });

        this.createAsset("grass", {
            type: "xeogl.LambertMaterial",
            diffuse: [0, 0.5, 0.2],
            ambient: [0.1, 0.1, 0.1]
        });

        // Select a couple of assets and generate the asphalt ground

        this.setGeometry("box");
        this.setMaterial("asphalt");
        this.setPosition(20, -.5, 20);
        this.setScale(140, 0.1, 140);
        this.createMesh();

        // Generate the buildings

        var size = options.size || 1000;
        var halfSize = size * 0.5;
        var density = options.density || 10;
        var spacing = size / density;

        for (var x = -halfSize; x <= halfSize; x += spacing) {
            for (var z = -halfSize; z <= halfSize; z += spacing) {
                this._generateBuilding(x + 2, z + 2, x + spacing - 2, z + spacing - 2, options);
            }
        }
    }

    _generateBuilding(xmin, zmin, xmax, zmax, options) {

        var xpos = (xmin + xmax) * 0.5;
        var ypos = 0;
        var zpos = (zmin + zmax) * 0.5;

        // Each building gets a green lawn under it

        this.setGeometry("box");
        this.setMaterial("grass");
        this.setPosition(xpos, ypos, zpos);
        this.setScale((xmax - xmin) / 2.5, 0.5, (zmax - zmin) / 2.5);
        this.setColorize(0.3 + Math.random() * 0.5, 0.3 + Math.random() * 0.5, 0.3 + Math.random() * 0.5, 1.0);
        this.createMesh();

        // Now generate the building as a bunch of boxes

        var yMaxSize = (Math.random() * 30) + 15;
        var ySize = yMaxSize + 10;
        var width;
        var axis;
        var sign;

        var xminBox;
        var zminBox;
        var xmaxBox;
        var zmaxBox;

        while (ySize > 5) {

            width = (Math.random() * 5) + 2;
            axis = Math.round(Math.random());
            sign = Math.round(Math.random());

            switch (axis) {

                case 0:

                    if (sign == 0) {

                        xminBox = xmin;
                        zminBox = zpos - width;

                        xmaxBox = xpos + width;
                        zmaxBox = zpos + width;

                    } else {

                        xminBox = xpos - width;
                        zminBox = zpos - width;

                        xmaxBox = xmax;
                        zmaxBox = zpos + width;
                    }

                    break;

                case 1:

                    if (sign == 0) {

                        xminBox = xpos - width;
                        zminBox = zmin;

                        xmaxBox = xpos + width;
                        zmaxBox = zpos + width;

                    } else {

                        xminBox = xpos - width;
                        zminBox = zpos - width;

                        xmaxBox = xpos + width;
                        zmaxBox = zmax;
                    }

                    break;
            }

            this.setGeometry("box");
            this.setMaterial("lightConcrete");
            this.setPosition(xpos, ypos + ySize, zpos);
            this.setScale((xmaxBox - xminBox) * 0.5, ySize, (zmaxBox - zminBox) * 0.5);
            this.createMesh();

            // Decrease current vertical box size
            ySize -= (Math.random() * 5) + 2;
        }
    }
};