API Docs for:

File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/geometry/aabbGeometry.js

/**
 An **AABBGeometry** is a {{#crossLink "Geometry"}}{{/crossLink}} that shows the extents of a World-space axis-aligned bounding box (AABB).

 <a href="../../examples/#geometry_primitives_AABBGeometry"><img src="http://i.giphy.com/3o6ZsSVy0NKXZ1vDSo.gif"></img></a>

 ## Overview

 * A World-space AABB is an axis-aligned box given as a six-element array containing the min/max extents of an axis-aligned volume, ie. ````[xmin,ymin,zmin,xmax,ymax,zmax]````.
 * Set a AABBGeometry's {{#crossLink "AABBGeometry/targetAABB:property"}}{{/crossLink}} property to an AABB to fix the AABBGeometry to those extents, or
 * set a AABBGeometry's {{#crossLink "AABBGeometry/target:property"}}{{/crossLink}} property to any target {{#crossLink "Component"}}{{/crossLink}}
 subtype that has an AABB, to make it dynamically fit itself to changes in the target AABB.

 ## Examples

 * [Rendering an AABBGeometry](../../examples/#geometry_primitives_AABBGeometry)

 ## Usage

 ````javascript
 // First Mesh with a TorusGeometry
 var mesh = new xeogl.Mesh({
     geometry: new xeogl.TorusGeometry()
 });

 // Second Mesh with an AABBGeometry that shows a wireframe box
 // for the World-space axis-aligned boundary of the first Mesh
 var boundaryHelper = new xeogl.Mesh({

     geometry: new xeogl.AABBGeometry({
         targetAABB: mesh.aabb
     }),

     material: new xeogl.PhongMaterial({
         diffuse: [0.5, 1.0, 0.5],
         emissive: [0.5, 1.0, 0.5],
         lineWidth:2
     })
 });
 ````

 Now whenever our mesh {{#crossLink "Mesh"}}{{/crossLink}} changes shape or position, our AABBGeometry will automatically
 update to stay fitted to it.

 We could also directly configure the AABBGeometry with the {{#crossLink "Mesh"}}{{/crossLink}}'s {{#crossLink "Mesh/aabb:property"}}AABB{{/crossLink}}:

 ````javascript
 var boundaryHelper2 = new xeogl.Mesh({

     geometry: new xeogl.AABBGeometry({
         targetAABB: mesh.aabb
     }),

     material: new xeogl.PhongMaterial({
         diffuse: [0.5, 1.0, 0.5],
         emissive: [0.5, 1.0, 0.5],
         lineWidth:2
     })
 });
 ````

 @class AABBGeometry
 @module xeogl
 @submodule geometry
 @constructor
 @param [owner] {Component} Owner component. When destroyed, the owner will destroy this component as well. Creates this component within the default {{#crossLink "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.meta] {String:Object} Optional map of user-defined metadata to attach to this AABBGeometry.
 @param [cfg.target] {Component} ID or instance of a {{#crossLink "Component"}}{{/crossLink}} subtype whose AABB we'll show.
 @param [cfg.targetAABB] {Float32Array} An axis-aligned box (AABB) in a six-element Float32Array
 containing the min/max extents of the axis-aligned volume, ie. ````(xmin,ymin,zmin,xmax,ymax,zmax)````.
 @extends Component
 */

import {utils} from '../utils.js';
import {tasks} from '../tasks.js';
import {Geometry} from './geometry.js';
import {componentClasses} from "./../componentClasses.js";

const type = "xeogl.AABBGeometry";

class AABBGeometry extends Geometry {

    /**
     JavaScript class name for this Component.

     For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.

     @property type
     @type String
     @final
     */
    get type() {
        return type;
    }

    init(cfg) {

        super.init(utils.apply(cfg, {
            combined: true,
            quantized: true, // Quantized geometry is immutable
            primitive: cfg.primitive || "lines",
            indices: [
                0, 1, 1, 2, 2, 3, 3, 0, 4,
                5, 5, 6, 6, 7, 7, 4, 0, 4,
                1, 5, 2, 6, 3, 7
            ],
            positions: cfg.positions || [
                1.0, 1.0, 1.0,
                1.0, -1.0, 1.0,
                -1.0, -1.0, 1.0,
                -1.0, 1.0, 1.0,
                1.0, 1.0, -1.0,
                1.0, -1.0, -1.0,
                -1.0, -1.0, -1.0,
                -1.0, 1.0, -1.0
            ]
        }));

        if (cfg.target) {
            this.target = cfg.target;

        } else if (cfg.targetAABB) {
            this.targetAABB = cfg.targetAABB;
        }
    }


    /**
     A component whose AABB we'll dynamically fit this AABBGeometry to.

     This property effectively replaces the {{#crossLink "AABBGeometry/targetAABB:property"}}{{/crossLink}} property.

     @property target
     @type Component
     */
    set target(target) {
        let geometryDirty = false;
        const self = this;
        this._attach({
            name: "target",
            type: "xeogl.Component",
            component: target,
            sceneDefault: false,
            on: {
                boundary: function () {
                    if (geometryDirty) {
                        return;
                    }
                    geometryDirty = true;
                    tasks.scheduleTask(function () {
                        self._setPositionsFromAABB(self._attached.target.aabb);
                        geometryDirty = false;
                    });
                }
            },
            onAttached: function () {
                self._setPositionsFromAABB(self._attached.target.aabb);
            }
        });
    }

    get target() {
        return this._attached.target;
    }

    /**
     Sets this AABBGeometry to an axis-aligned box (AABB), given as a six-element Float32Array
     containing the min/max extents of the
     axis-aligned volume, ie. ````[xmin,ymin,zmin,xmax,ymax,zmax]````.

     This property overrides the {{#crossLink "AABBGeometry/target:property"}}{{/crossLink}} property, causing it to become null.

     @property targetAABB
     @type Float32Array
     */
    set targetAABB(aabb) {
        if (!aabb) {
            return;
        }
        if (this._attached.target) {
            this.target = null;
        }
        this._setPositionsFromAABB(aabb);
    }

    _setPositionsFromAABB(aabb) {
        this.positions = [
            aabb[3], aabb[4], aabb[5],
            aabb[3], aabb[1], aabb[5],
            aabb[0], aabb[1], aabb[5],
            aabb[0], aabb[4], aabb[5],
            aabb[3], aabb[4], aabb[2],
            aabb[3], aabb[1], aabb[2],
            aabb[0], aabb[1], aabb[2],
            aabb[0], aabb[4], aabb[2]
        ];
    }
}

componentClasses[type] = AABBGeometry;

export{AABBGeometry};