API Docs for: 0.5.5
Show:

File: kick/math/Frustum.js

define(["kick/core/Constants", "./Vec3", "./Aabb"], function (constants, vec3, aabb) {
    "use strict";
    var OUTSIDE = 0,
        INSIDE = 1,
        INTERSECTING = 2;

    /**
     * Frustum represented as 6 line equations (a*x+b*y+c*z+d=0 , where [a,b,c] is the normal of the plane).
     * Note the normals of the frustum points inwards. The order of the planes are left, right, top, bottom, near, far
     * The implementation is based on
     * "Fast Extraction of Viewing Frustum Planes from the WorldView-Projection Matrix" by Gil Grib and Klaus Hartmann
     * http://www.cs.otago.ac.nz/postgrads/alexis/planeExtraction.pdf
     * @class Frustum
     * @namespace kick.math
     */
    return {
        /**
         * Create a array of 24. 6 line equations (a*x+b*y+c*z+d=0 , where [a,b,c] is the normal of the plane).
         * @method create
         * @static
         */
        create : function () {
            return new Float32Array(24);
        },

        /**
         * @method extractPlanes
         * @param {Array_24} out
         * @param {kick.math.Mat4} modelViewMatrix
         * @param {Boolean} normalize normalize plane normal
         * @return {Array_24} out
         * @static
         */
        extractPlanes: function (out, modelViewMatrix, normalize) {
            var _11 = modelViewMatrix[0], _21 = modelViewMatrix[1], _31 = modelViewMatrix[2], _41 = modelViewMatrix[3],
                _12 = modelViewMatrix[4], _22 = modelViewMatrix[5], _32 = modelViewMatrix[6], _42 = modelViewMatrix[7],
                _13 = modelViewMatrix[8], _23 = modelViewMatrix[9], _33 = modelViewMatrix[10], _43 = modelViewMatrix[11],
                _14 = modelViewMatrix[12], _24 = modelViewMatrix[13], _34 = modelViewMatrix[14], _44 = modelViewMatrix[15],
                i,
                x,
                y,
                z,
                length,
                lengthRecip;
            // Left clipping plane
            out[0] = _41 + _11;
            out[1] = _42 + _12;
            out[2] = _43 + _13;
            out[3] = _44 + _14;
            // Right clipping plane
            out[4] = _41 - _11;
            out[4 + 1] = _42 - _12;
            out[4 + 2] = _43 - _13;
            out[4 + 3] = _44 - _14;
            // Top clipping plane
            out[2 * 4] = _41 - _21;
            out[2 * 4 + 1] = _42 - _22;
            out[2 * 4 + 2] = _43 - _23;
            out[2 * 4 + 3] = _44 - _24;
            // Bottom clipping plane
            out[3 * 4] = _41 + _21;
            out[3 * 4 + 1] = _42 + _22;
            out[3 * 4 + 2] = _43 + _23;
            out[3 * 4 + 3] = _44 + _24;
            // Near clipping plane
            out[4 * 4] = _41 + _31;
            out[4 * 4 + 1] = _42 + _32;
            out[4 * 4 + 2] = _43 + _33;
            out[4 * 4 + 3] = _44 + _34;
            // Far clipping plane
            out[5 * 4] = _41 - _31;
            out[5 * 4 + 1] = _42 - _32;
            out[5 * 4 + 2] = _43 - _33;
            out[5 * 4 + 3] = _44 - _34;
            if (normalize) {
                for (i = 0; i < 6; i++) {
                    x = out[i * 4];
                    y = out[i * 4 + 1];
                    z = out[i * 4 + 2];
                    length = Math.sqrt(x * x + y * y + z * z);
                    lengthRecip = 1 / length;
                    out[i * 4] *= lengthRecip;
                    out[i * 4 + 1] *= lengthRecip;
                    out[i * 4 + 2] *= lengthRecip;
                    out[i * 4 + 3] *= lengthRecip;
                }
            }
            return out;
        },

        /**
         * Value = 0
         * @property OUTSIDE
         * @type Number
         * @static
         */
        OUTSIDE: OUTSIDE,

        /**
         * Value = 1
         * @property INSIDE
         * @type Number
         * @static
         */
        INSIDE: INSIDE,

        /**
         * Value = 2
         * @property INTERSECTING
         * @type Number
         * @static
         */
        INTERSECTING: INTERSECTING,

        /**
         * Based on [Akenine-Moller's Real-Time Rendering 3rd Ed] chapter 16.14.3
         * @method intersectAabb
         * @param {kick.math.Frustum} frustumPlanes
         * @param {kick.math.Aabb} aabbIn
         * @return {Number} frustum.OUTSIDE = outside(0), frustum.INSIDE = inside(1), frustum.INTERSECTING = intersecting(2)
         * @static
         */
        intersectAabb: (function () {
            var center = vec3.create(),
                halfVector = vec3.create();
            return function (frustumPlanes, aabbIn) {
                var result = INSIDE, i,
                    testResult,
                    centerX, centerY, centerZ,
                    halfVectorX, halfVectorY, halfVectorZ,
                    // based on [Akenine-Moller's Real-Time Rendering 3rd Ed] chapter 16.10.1
                    planeAabbIntersect = function (planeIndex) {
                        var offset = planeIndex * 4,
                            nx = frustumPlanes[offset],
                            ny = frustumPlanes[offset + 1],
                            nz = frustumPlanes[offset + 2],
                            d = frustumPlanes[offset + 3],
                            e = halfVectorX * Math.abs(nx) + halfVectorY * Math.abs(ny) + halfVectorZ * Math.abs(nz),
                            s = centerX * nx + centerY * ny + centerZ * nz + d;
                        // Note that the following is reverse than in [Akenine-Moller's Real-Time Rendering 3rd Ed],
                        // since we define outside as the negative halfspace
                        if (s - e > 0) { return INSIDE; }
                        if (s + e < 0) { return OUTSIDE; }
                        return INTERSECTING;
                    };
                aabb.center(center, aabbIn);
                aabb.halfVec3(halfVector, aabbIn);
                centerX = center[0];
                centerY = center[1];
                centerZ = center[2];
                halfVectorX = halfVector[0];
                halfVectorY = halfVector[1];
                halfVectorZ = halfVector[2];
                for (i = 0; i < 6; i++) {
                    testResult = planeAabbIntersect(i);
                    if (testResult === OUTSIDE) {
                        return testResult;
                    } else if (testResult === INTERSECTING) {
                        result = INTERSECTING;
                    }
                }
                return result;
            };
        }())
    };
});