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;
|