# 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

    1×
    1×

    1×
    62×

    62×

    145×
    145×

    145×
    145×

    145×

    1×
    1×
    1×

    1×
    1×
    1×

    1×
    1×
    1×
    1×
    1×
    1×
    1×
    1×
    1×

    1×
    1×
    1×
    1×
    1×

    1×
    1×
    1×

    1×

     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;