all files / src/ Camera.js

100% Statements 34/34
50% Branches 1/2
100% Functions 9/9
100% Lines 34/34
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125                      62×                                                   62×           145× 145×   145× 145×   145×                                                                                                
import Node from './Node';
import Matrix4 from './math/Matrix4';
import Frustum from './math/Frustum';
import Ray from './math/Ray';
 
import glMatrix from './dep/glmatrix';
var vec3 = glMatrix.vec3;
var vec4 = glMatrix.vec4;
 
/**
 * @constructor clay.Camera
 * @extends clay.Node
 */
var Camera = Node.extend(function () {
    return /** @lends clay.Camera# */ {
        /**
         * Camera projection matrix
         * @type {clay.Matrix4}
         */
        projectionMatrix: new Matrix4(),
 
        /**
         * Inverse of camera projection matrix
         * @type {clay.Matrix4}
         */
        invProjectionMatrix: new Matrix4(),
 
        /**
         * View matrix, equal to inverse of camera's world matrix
         * @type {clay.Matrix4}
         */
        viewMatrix: new Matrix4(),
 
        /**
         * Camera frustum in view space
         * @type {clay.Frustum}
         */
        frustum: new Frustum()
    };
}, function () {
    this.update(true);
},
/** @lends clay.Camera.prototype */
{
 
    update: function (force) {
        Node.prototype.update.call(this, force);
        Matrix4.invert(this.viewMatrix, this.worldTransform);
 
        this.updateProjectionMatrix();
        Matrix4.invert(this.invProjectionMatrix, this.projectionMatrix);
 
        this.frustum.setFromProjection(this.projectionMatrix);
    },
 
    /**
     * Set camera view matrix
     */
    setViewMatrix: function (viewMatrix) {
        Matrix4.copy(this.viewMatrix, viewMatrix);
        Matrix4.invert(this.worldTransform, viewMatrix);
        this.decomposeWorldTransform();
    },
 
    /**
     * Decompose camera projection matrix
     */
    decomposeProjectionMatrix: function () {},
 
    /**
     * Set camera projection matrix
     * @param {clay.Matrix4} projectionMatrix
     */
    setProjectionMatrix: function (projectionMatrix) {
        Matrix4.copy(this.projectionMatrix, projectionMatrix);
        Matrix4.invert(this.invProjectionMatrix, projectionMatrix);
        this.decomposeProjectionMatrix();
    },
    /**
     * Update projection matrix, called after update
     */
    updateProjectionMatrix: function () {},
 
    /**
     * Cast a picking ray from camera near plane to far plane
     * @function
     * @param {clay.Vector2} ndc
     * @param {clay.Ray} [out]
     * @return {clay.Ray}
     */
    castRay: (function () {
        var v4 = vec4.create();
        return function (ndc, out) {
            var ray = out !== undefined ? out : new Ray();
            var x = ndc.array[0];
            var y = ndc.array[1];
            vec4.set(v4, x, y, -1, 1);
            vec4.transformMat4(v4, v4, this.invProjectionMatrix.array);
            vec4.transformMat4(v4, v4, this.worldTransform.array);
            vec3.scale(ray.origin.array, v4, 1 / v4[3]);
 
            vec4.set(v4, x, y, 1, 1);
            vec4.transformMat4(v4, v4, this.invProjectionMatrix.array);
            vec4.transformMat4(v4, v4, this.worldTransform.array);
            vec3.scale(v4, v4, 1 / v4[3]);
            vec3.sub(ray.direction.array, v4, ray.origin.array);
 
            vec3.normalize(ray.direction.array, ray.direction.array);
            ray.direction._dirty = true;
            ray.origin._dirty = true;
 
            return ray;
        };
    })(),
 
    /**
     * @function
     * @name clone
     * @return {clay.Camera}
     * @memberOf clay.Camera.prototype
     */
});
 
export default Camera;