3
|
1 /*
|
|
2 * Copyright (C) 2009 Apple Inc. All Rights Reserved.
|
|
3 *
|
|
4 * Redistribution and use in source and binary forms, with or without
|
|
5 * modification, are permitted provided that the following conditions
|
|
6 * are met:
|
|
7 * 1. Redistributions of source code must retain the above copyright
|
|
8 * notice, this list of conditions and the following disclaimer.
|
|
9 * 2. Redistributions in binary form must reproduce the above copyright
|
|
10 * notice, this list of conditions and the following disclaimer in the
|
|
11 * documentation and/or other materials provided with the distribution.
|
|
12 *
|
|
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
24 */
|
|
25 /*
|
|
26 CanvasMatrix4 class
|
|
27
|
|
28 This class implements a 4x4 matrix. It has functions which
|
|
29 duplicate the functionality of the OpenGL matrix stack and
|
|
30 glut functions.
|
|
31
|
|
32 IDL:
|
|
33
|
|
34 [
|
|
35 Constructor(in CanvasMatrix4 matrix), // copy passed matrix into new CanvasMatrix4
|
|
36 Constructor(in sequence<float> array) // create new CanvasMatrix4 with 16 floats (row major)
|
|
37 Constructor() // create new CanvasMatrix4 with identity matrix
|
|
38 ]
|
|
39 interface CanvasMatrix4 {
|
|
40 attribute float m11;
|
|
41 attribute float m12;
|
|
42 attribute float m13;
|
|
43 attribute float m14;
|
|
44 attribute float m21;
|
|
45 attribute float m22;
|
|
46 attribute float m23;
|
|
47 attribute float m24;
|
|
48 attribute float m31;
|
|
49 attribute float m32;
|
|
50 attribute float m33;
|
|
51 attribute float m34;
|
|
52 attribute float m41;
|
|
53 attribute float m42;
|
|
54 attribute float m43;
|
|
55 attribute float m44;
|
|
56
|
|
57 void load(in CanvasMatrix4 matrix); // copy the values from the passed matrix
|
|
58 void load(in sequence<float> array); // copy 16 floats into the matrix
|
|
59 sequence<float> getAsArray(); // return the matrix as an array of 16 floats
|
|
60 WebGLFloatArray getAsCanvasFloatArray(); // return the matrix as a WebGLFloatArray with 16 values
|
|
61 void makeIdentity(); // replace the matrix with identity
|
|
62 void transpose(); // replace the matrix with its transpose
|
|
63 void invert(); // replace the matrix with its inverse
|
|
64
|
|
65 void translate(in float x, in float y, in float z); // multiply the matrix by passed translation values on the right
|
|
66 void scale(in float x, in float y, in float z); // multiply the matrix by passed scale values on the right
|
|
67 void rotate(in float angle, // multiply the matrix by passed rotation values on the right
|
|
68 in float x, in float y, in float z); // (angle is in degrees)
|
|
69 void multRight(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the right
|
|
70 void multLeft(in CanvasMatrix matrix); // multiply the matrix by the passed matrix on the left
|
|
71 void ortho(in float left, in float right, // multiply the matrix by the passed ortho values on the right
|
|
72 in float bottom, in float top,
|
|
73 in float near, in float far);
|
|
74 void frustum(in float left, in float right, // multiply the matrix by the passed frustum values on the right
|
|
75 in float bottom, in float top,
|
|
76 in float near, in float far);
|
|
77 void perspective(in float fovy, in float aspect, // multiply the matrix by the passed perspective values on the right
|
|
78 in float zNear, in float zFar);
|
|
79 void lookat(in float eyex, in float eyey, in float eyez, // multiply the matrix by the passed lookat
|
|
80 in float ctrx, in float ctry, in float ctrz, // values on the right
|
|
81 in float upx, in float upy, in float upz);
|
|
82 }
|
|
83 */
|
|
84
|
|
85 CanvasMatrix4 = function(m)
|
|
86 {
|
|
87 if (typeof m == 'object') {
|
|
88 if ("length" in m && m.length >= 16) {
|
|
89 this.load(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
|
|
90 return;
|
|
91 }
|
|
92 else if (m instanceof CanvasMatrix4) {
|
|
93 this.load(m);
|
|
94 return;
|
|
95 }
|
|
96 }
|
|
97 this.makeIdentity();
|
|
98 }
|
|
99
|
|
100 CanvasMatrix4.prototype.load = function()
|
|
101 {
|
|
102 if (arguments.length == 1 && typeof arguments[0] == 'object') {
|
|
103 var matrix = arguments[0];
|
|
104
|
|
105 if ("length" in matrix && matrix.length == 16) {
|
|
106 this.m11 = matrix[0];
|
|
107 this.m12 = matrix[1];
|
|
108 this.m13 = matrix[2];
|
|
109 this.m14 = matrix[3];
|
|
110
|
|
111 this.m21 = matrix[4];
|
|
112 this.m22 = matrix[5];
|
|
113 this.m23 = matrix[6];
|
|
114 this.m24 = matrix[7];
|
|
115
|
|
116 this.m31 = matrix[8];
|
|
117 this.m32 = matrix[9];
|
|
118 this.m33 = matrix[10];
|
|
119 this.m34 = matrix[11];
|
|
120
|
|
121 this.m41 = matrix[12];
|
|
122 this.m42 = matrix[13];
|
|
123 this.m43 = matrix[14];
|
|
124 this.m44 = matrix[15];
|
|
125 return;
|
|
126 }
|
|
127
|
|
128 if (arguments[0] instanceof CanvasMatrix4) {
|
|
129
|
|
130 this.m11 = matrix.m11;
|
|
131 this.m12 = matrix.m12;
|
|
132 this.m13 = matrix.m13;
|
|
133 this.m14 = matrix.m14;
|
|
134
|
|
135 this.m21 = matrix.m21;
|
|
136 this.m22 = matrix.m22;
|
|
137 this.m23 = matrix.m23;
|
|
138 this.m24 = matrix.m24;
|
|
139
|
|
140 this.m31 = matrix.m31;
|
|
141 this.m32 = matrix.m32;
|
|
142 this.m33 = matrix.m33;
|
|
143 this.m34 = matrix.m34;
|
|
144
|
|
145 this.m41 = matrix.m41;
|
|
146 this.m42 = matrix.m42;
|
|
147 this.m43 = matrix.m43;
|
|
148 this.m44 = matrix.m44;
|
|
149 return;
|
|
150 }
|
|
151 }
|
|
152
|
|
153 this.makeIdentity();
|
|
154 }
|
|
155
|
|
156 CanvasMatrix4.prototype.getAsArray = function()
|
|
157 {
|
|
158 return [
|
|
159 this.m11, this.m12, this.m13, this.m14,
|
|
160 this.m21, this.m22, this.m23, this.m24,
|
|
161 this.m31, this.m32, this.m33, this.m34,
|
|
162 this.m41, this.m42, this.m43, this.m44
|
|
163 ];
|
|
164 }
|
|
165
|
|
166 CanvasMatrix4.prototype.getAsWebGLFloatArray = function()
|
|
167 {
|
|
168 return new WebGLFloatArray(this.getAsArray());
|
|
169 }
|
|
170
|
|
171 CanvasMatrix4.prototype.makeIdentity = function()
|
|
172 {
|
|
173 this.m11 = 1;
|
|
174 this.m12 = 0;
|
|
175 this.m13 = 0;
|
|
176 this.m14 = 0;
|
|
177
|
|
178 this.m21 = 0;
|
|
179 this.m22 = 1;
|
|
180 this.m23 = 0;
|
|
181 this.m24 = 0;
|
|
182
|
|
183 this.m31 = 0;
|
|
184 this.m32 = 0;
|
|
185 this.m33 = 1;
|
|
186 this.m34 = 0;
|
|
187
|
|
188 this.m41 = 0;
|
|
189 this.m42 = 0;
|
|
190 this.m43 = 0;
|
|
191 this.m44 = 1;
|
|
192 }
|
|
193
|
|
194 CanvasMatrix4.prototype.transpose = function()
|
|
195 {
|
|
196 var tmp = this.m12;
|
|
197 this.m12 = this.m21;
|
|
198 this.m21 = tmp;
|
|
199
|
|
200 tmp = this.m13;
|
|
201 this.m13 = this.m31;
|
|
202 this.m31 = tmp;
|
|
203
|
|
204 tmp = this.m14;
|
|
205 this.m14 = this.m41;
|
|
206 this.m41 = tmp;
|
|
207
|
|
208 tmp = this.m23;
|
|
209 this.m23 = this.m32;
|
|
210 this.m32 = tmp;
|
|
211
|
|
212 tmp = this.m24;
|
|
213 this.m24 = this.m42;
|
|
214 this.m42 = tmp;
|
|
215
|
|
216 tmp = this.m34;
|
|
217 this.m34 = this.m43;
|
|
218 this.m43 = tmp;
|
|
219 }
|
|
220
|
|
221 CanvasMatrix4.prototype.invert = function()
|
|
222 {
|
|
223 // Calculate the 4x4 determinant
|
|
224 // If the determinant is zero,
|
|
225 // then the inverse matrix is not unique.
|
|
226 var det = this._determinant4x4();
|
|
227
|
|
228 if (Math.abs(det) < 1e-8)
|
|
229 return null;
|
|
230
|
|
231 this._makeAdjoint();
|
|
232
|
|
233 // Scale the adjoint matrix to get the inverse
|
|
234 this.m11 /= det;
|
|
235 this.m12 /= det;
|
|
236 this.m13 /= det;
|
|
237 this.m14 /= det;
|
|
238
|
|
239 this.m21 /= det;
|
|
240 this.m22 /= det;
|
|
241 this.m23 /= det;
|
|
242 this.m24 /= det;
|
|
243
|
|
244 this.m31 /= det;
|
|
245 this.m32 /= det;
|
|
246 this.m33 /= det;
|
|
247 this.m34 /= det;
|
|
248
|
|
249 this.m41 /= det;
|
|
250 this.m42 /= det;
|
|
251 this.m43 /= det;
|
|
252 this.m44 /= det;
|
|
253 }
|
|
254
|
|
255 CanvasMatrix4.prototype.translate = function(x,y,z)
|
|
256 {
|
|
257 if (x == undefined)
|
|
258 x = 0;
|
|
259 if (y == undefined)
|
|
260 y = 0;
|
|
261 if (z == undefined)
|
|
262 z = 0;
|
|
263
|
|
264 var matrix = new CanvasMatrix4();
|
|
265 matrix.m41 = x;
|
|
266 matrix.m42 = y;
|
|
267 matrix.m43 = z;
|
|
268
|
|
269 this.multRight(matrix);
|
|
270 }
|
|
271
|
|
272 CanvasMatrix4.prototype.scale = function(x,y,z)
|
|
273 {
|
|
274 if (x == undefined)
|
|
275 x = 1;
|
|
276 if (z == undefined) {
|
|
277 if (y == undefined) {
|
|
278 y = x;
|
|
279 z = x;
|
|
280 }
|
|
281 else
|
|
282 z = 1;
|
|
283 }
|
|
284 else if (y == undefined)
|
|
285 y = x;
|
|
286
|
|
287 var matrix = new CanvasMatrix4();
|
|
288 matrix.m11 = x;
|
|
289 matrix.m22 = y;
|
|
290 matrix.m33 = z;
|
|
291
|
|
292 this.multRight(matrix);
|
|
293 }
|
|
294
|
|
295 CanvasMatrix4.prototype.rotate = function(angle,x,y,z)
|
|
296 {
|
|
297 // angles are in degrees. Switch to radians
|
|
298 angle = angle / 180 * Math.PI;
|
|
299
|
|
300 angle /= 2;
|
|
301 var sinA = Math.sin(angle);
|
|
302 var cosA = Math.cos(angle);
|
|
303 var sinA2 = sinA * sinA;
|
|
304
|
|
305 // normalize
|
|
306 var length = Math.sqrt(x * x + y * y + z * z);
|
|
307 if (length == 0) {
|
|
308 // bad vector, just use something reasonable
|
|
309 x = 0;
|
|
310 y = 0;
|
|
311 z = 1;
|
|
312 } else if (length != 1) {
|
|
313 x /= length;
|
|
314 y /= length;
|
|
315 z /= length;
|
|
316 }
|
|
317
|
|
318 var mat = new CanvasMatrix4();
|
|
319
|
|
320 // optimize case where axis is along major axis
|
|
321 if (x == 1 && y == 0 && z == 0) {
|
|
322 mat.m11 = 1;
|
|
323 mat.m12 = 0;
|
|
324 mat.m13 = 0;
|
|
325 mat.m21 = 0;
|
|
326 mat.m22 = 1 - 2 * sinA2;
|
|
327 mat.m23 = 2 * sinA * cosA;
|
|
328 mat.m31 = 0;
|
|
329 mat.m32 = -2 * sinA * cosA;
|
|
330 mat.m33 = 1 - 2 * sinA2;
|
|
331 mat.m14 = mat.m24 = mat.m34 = 0;
|
|
332 mat.m41 = mat.m42 = mat.m43 = 0;
|
|
333 mat.m44 = 1;
|
|
334 } else if (x == 0 && y == 1 && z == 0) {
|
|
335 mat.m11 = 1 - 2 * sinA2;
|
|
336 mat.m12 = 0;
|
|
337 mat.m13 = -2 * sinA * cosA;
|
|
338 mat.m21 = 0;
|
|
339 mat.m22 = 1;
|
|
340 mat.m23 = 0;
|
|
341 mat.m31 = 2 * sinA * cosA;
|
|
342 mat.m32 = 0;
|
|
343 mat.m33 = 1 - 2 * sinA2;
|
|
344 mat.m14 = mat.m24 = mat.m34 = 0;
|
|
345 mat.m41 = mat.m42 = mat.m43 = 0;
|
|
346 mat.m44 = 1;
|
|
347 } else if (x == 0 && y == 0 && z == 1) {
|
|
348 mat.m11 = 1 - 2 * sinA2;
|
|
349 mat.m12 = 2 * sinA * cosA;
|
|
350 mat.m13 = 0;
|
|
351 mat.m21 = -2 * sinA * cosA;
|
|
352 mat.m22 = 1 - 2 * sinA2;
|
|
353 mat.m23 = 0;
|
|
354 mat.m31 = 0;
|
|
355 mat.m32 = 0;
|
|
356 mat.m33 = 1;
|
|
357 mat.m14 = mat.m24 = mat.m34 = 0;
|
|
358 mat.m41 = mat.m42 = mat.m43 = 0;
|
|
359 mat.m44 = 1;
|
|
360 } else {
|
|
361 var x2 = x*x;
|
|
362 var y2 = y*y;
|
|
363 var z2 = z*z;
|
|
364
|
|
365 mat.m11 = 1 - 2 * (y2 + z2) * sinA2;
|
|
366 mat.m12 = 2 * (x * y * sinA2 + z * sinA * cosA);
|
|
367 mat.m13 = 2 * (x * z * sinA2 - y * sinA * cosA);
|
|
368 mat.m21 = 2 * (y * x * sinA2 - z * sinA * cosA);
|
|
369 mat.m22 = 1 - 2 * (z2 + x2) * sinA2;
|
|
370 mat.m23 = 2 * (y * z * sinA2 + x * sinA * cosA);
|
|
371 mat.m31 = 2 * (z * x * sinA2 + y * sinA * cosA);
|
|
372 mat.m32 = 2 * (z * y * sinA2 - x * sinA * cosA);
|
|
373 mat.m33 = 1 - 2 * (x2 + y2) * sinA2;
|
|
374 mat.m14 = mat.m24 = mat.m34 = 0;
|
|
375 mat.m41 = mat.m42 = mat.m43 = 0;
|
|
376 mat.m44 = 1;
|
|
377 }
|
|
378 this.multRight(mat);
|
|
379 }
|
|
380
|
|
381 CanvasMatrix4.prototype.multRight = function(mat)
|
|
382 {
|
|
383 var m11 = (this.m11 * mat.m11 + this.m12 * mat.m21
|
|
384 + this.m13 * mat.m31 + this.m14 * mat.m41);
|
|
385 var m12 = (this.m11 * mat.m12 + this.m12 * mat.m22
|
|
386 + this.m13 * mat.m32 + this.m14 * mat.m42);
|
|
387 var m13 = (this.m11 * mat.m13 + this.m12 * mat.m23
|
|
388 + this.m13 * mat.m33 + this.m14 * mat.m43);
|
|
389 var m14 = (this.m11 * mat.m14 + this.m12 * mat.m24
|
|
390 + this.m13 * mat.m34 + this.m14 * mat.m44);
|
|
391
|
|
392 var m21 = (this.m21 * mat.m11 + this.m22 * mat.m21
|
|
393 + this.m23 * mat.m31 + this.m24 * mat.m41);
|
|
394 var m22 = (this.m21 * mat.m12 + this.m22 * mat.m22
|
|
395 + this.m23 * mat.m32 + this.m24 * mat.m42);
|
|
396 var m23 = (this.m21 * mat.m13 + this.m22 * mat.m23
|
|
397 + this.m23 * mat.m33 + this.m24 * mat.m43);
|
|
398 var m24 = (this.m21 * mat.m14 + this.m22 * mat.m24
|
|
399 + this.m23 * mat.m34 + this.m24 * mat.m44);
|
|
400
|
|
401 var m31 = (this.m31 * mat.m11 + this.m32 * mat.m21
|
|
402 + this.m33 * mat.m31 + this.m34 * mat.m41);
|
|
403 var m32 = (this.m31 * mat.m12 + this.m32 * mat.m22
|
|
404 + this.m33 * mat.m32 + this.m34 * mat.m42);
|
|
405 var m33 = (this.m31 * mat.m13 + this.m32 * mat.m23
|
|
406 + this.m33 * mat.m33 + this.m34 * mat.m43);
|
|
407 var m34 = (this.m31 * mat.m14 + this.m32 * mat.m24
|
|
408 + this.m33 * mat.m34 + this.m34 * mat.m44);
|
|
409
|
|
410 var m41 = (this.m41 * mat.m11 + this.m42 * mat.m21
|
|
411 + this.m43 * mat.m31 + this.m44 * mat.m41);
|
|
412 var m42 = (this.m41 * mat.m12 + this.m42 * mat.m22
|
|
413 + this.m43 * mat.m32 + this.m44 * mat.m42);
|
|
414 var m43 = (this.m41 * mat.m13 + this.m42 * mat.m23
|
|
415 + this.m43 * mat.m33 + this.m44 * mat.m43);
|
|
416 var m44 = (this.m41 * mat.m14 + this.m42 * mat.m24
|
|
417 + this.m43 * mat.m34 + this.m44 * mat.m44);
|
|
418
|
|
419 this.m11 = m11;
|
|
420 this.m12 = m12;
|
|
421 this.m13 = m13;
|
|
422 this.m14 = m14;
|
|
423
|
|
424 this.m21 = m21;
|
|
425 this.m22 = m22;
|
|
426 this.m23 = m23;
|
|
427 this.m24 = m24;
|
|
428
|
|
429 this.m31 = m31;
|
|
430 this.m32 = m32;
|
|
431 this.m33 = m33;
|
|
432 this.m34 = m34;
|
|
433
|
|
434 this.m41 = m41;
|
|
435 this.m42 = m42;
|
|
436 this.m43 = m43;
|
|
437 this.m44 = m44;
|
|
438 }
|
|
439
|
|
440 CanvasMatrix4.prototype.multLeft = function(mat)
|
|
441 {
|
|
442 var m11 = (mat.m11 * this.m11 + mat.m12 * this.m21
|
|
443 + mat.m13 * this.m31 + mat.m14 * this.m41);
|
|
444 var m12 = (mat.m11 * this.m12 + mat.m12 * this.m22
|
|
445 + mat.m13 * this.m32 + mat.m14 * this.m42);
|
|
446 var m13 = (mat.m11 * this.m13 + mat.m12 * this.m23
|
|
447 + mat.m13 * this.m33 + mat.m14 * this.m43);
|
|
448 var m14 = (mat.m11 * this.m14 + mat.m12 * this.m24
|
|
449 + mat.m13 * this.m34 + mat.m14 * this.m44);
|
|
450
|
|
451 var m21 = (mat.m21 * this.m11 + mat.m22 * this.m21
|
|
452 + mat.m23 * this.m31 + mat.m24 * this.m41);
|
|
453 var m22 = (mat.m21 * this.m12 + mat.m22 * this.m22
|
|
454 + mat.m23 * this.m32 + mat.m24 * this.m42);
|
|
455 var m23 = (mat.m21 * this.m13 + mat.m22 * this.m23
|
|
456 + mat.m23 * this.m33 + mat.m24 * this.m43);
|
|
457 var m24 = (mat.m21 * this.m14 + mat.m22 * this.m24
|
|
458 + mat.m23 * this.m34 + mat.m24 * this.m44);
|
|
459
|
|
460 var m31 = (mat.m31 * this.m11 + mat.m32 * this.m21
|
|
461 + mat.m33 * this.m31 + mat.m34 * this.m41);
|
|
462 var m32 = (mat.m31 * this.m12 + mat.m32 * this.m22
|
|
463 + mat.m33 * this.m32 + mat.m34 * this.m42);
|
|
464 var m33 = (mat.m31 * this.m13 + mat.m32 * this.m23
|
|
465 + mat.m33 * this.m33 + mat.m34 * this.m43);
|
|
466 var m34 = (mat.m31 * this.m14 + mat.m32 * this.m24
|
|
467 + mat.m33 * this.m34 + mat.m34 * this.m44);
|
|
468
|
|
469 var m41 = (mat.m41 * this.m11 + mat.m42 * this.m21
|
|
470 + mat.m43 * this.m31 + mat.m44 * this.m41);
|
|
471 var m42 = (mat.m41 * this.m12 + mat.m42 * this.m22
|
|
472 + mat.m43 * this.m32 + mat.m44 * this.m42);
|
|
473 var m43 = (mat.m41 * this.m13 + mat.m42 * this.m23
|
|
474 + mat.m43 * this.m33 + mat.m44 * this.m43);
|
|
475 var m44 = (mat.m41 * this.m14 + mat.m42 * this.m24
|
|
476 + mat.m43 * this.m34 + mat.m44 * this.m44);
|
|
477
|
|
478 this.m11 = m11;
|
|
479 this.m12 = m12;
|
|
480 this.m13 = m13;
|
|
481 this.m14 = m14;
|
|
482
|
|
483 this.m21 = m21;
|
|
484 this.m22 = m22;
|
|
485 this.m23 = m23;
|
|
486 this.m24 = m24;
|
|
487
|
|
488 this.m31 = m31;
|
|
489 this.m32 = m32;
|
|
490 this.m33 = m33;
|
|
491 this.m34 = m34;
|
|
492
|
|
493 this.m41 = m41;
|
|
494 this.m42 = m42;
|
|
495 this.m43 = m43;
|
|
496 this.m44 = m44;
|
|
497 }
|
|
498
|
|
499 CanvasMatrix4.prototype.ortho = function(left, right, bottom, top, near, far)
|
|
500 {
|
|
501 var tx = (left + right) / (left - right);
|
|
502 var ty = (top + bottom) / (top - bottom);
|
|
503 var tz = (far + near) / (far - near);
|
|
504
|
|
505 var matrix = new CanvasMatrix4();
|
|
506 matrix.m11 = 2 / (left - right);
|
|
507 matrix.m12 = 0;
|
|
508 matrix.m13 = 0;
|
|
509 matrix.m14 = 0;
|
|
510 matrix.m21 = 0;
|
|
511 matrix.m22 = 2 / (top - bottom);
|
|
512 matrix.m23 = 0;
|
|
513 matrix.m24 = 0;
|
|
514 matrix.m31 = 0;
|
|
515 matrix.m32 = 0;
|
|
516 matrix.m33 = -2 / (far - near);
|
|
517 matrix.m34 = 0;
|
|
518 matrix.m41 = tx;
|
|
519 matrix.m42 = ty;
|
|
520 matrix.m43 = tz;
|
|
521 matrix.m44 = 1;
|
|
522
|
|
523 this.multRight(matrix);
|
|
524 }
|
|
525
|
|
526 CanvasMatrix4.prototype.frustum = function(left, right, bottom, top, near, far)
|
|
527 {
|
|
528 var matrix = new CanvasMatrix4();
|
|
529 var A = (right + left) / (right - left);
|
|
530 var B = (top + bottom) / (top - bottom);
|
|
531 var C = -(far + near) / (far - near);
|
|
532 var D = -(2 * far * near) / (far - near);
|
|
533
|
|
534 matrix.m11 = (2 * near) / (right - left);
|
|
535 matrix.m12 = 0;
|
|
536 matrix.m13 = 0;
|
|
537 matrix.m14 = 0;
|
|
538
|
|
539 matrix.m21 = 0;
|
|
540 matrix.m22 = 2 * near / (top - bottom);
|
|
541 matrix.m23 = 0;
|
|
542 matrix.m24 = 0;
|
|
543
|
|
544 matrix.m31 = A;
|
|
545 matrix.m32 = B;
|
|
546 matrix.m33 = C;
|
|
547 matrix.m34 = -1;
|
|
548
|
|
549 matrix.m41 = 0;
|
|
550 matrix.m42 = 0;
|
|
551 matrix.m43 = D;
|
|
552 matrix.m44 = 0;
|
|
553
|
|
554 this.multRight(matrix);
|
|
555 }
|
|
556
|
|
557 CanvasMatrix4.prototype.perspective = function(fovy, aspect, zNear, zFar)
|
|
558 {
|
|
559 var top = Math.tan(fovy * Math.PI / 360) * zNear;
|
|
560 var bottom = -top;
|
|
561 var left = aspect * bottom;
|
|
562 var right = aspect * top;
|
|
563 this.frustum(left, right, bottom, top, zNear, zFar);
|
|
564 }
|
|
565
|
|
566 CanvasMatrix4.prototype.lookat = function(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)
|
|
567 {
|
|
568 var matrix = new CanvasMatrix4();
|
|
569
|
|
570 // Make rotation matrix
|
|
571
|
|
572 // Z vector
|
|
573 var zx = eyex - centerx;
|
|
574 var zy = eyey - centery;
|
|
575 var zz = eyez - centerz;
|
|
576 var mag = Math.sqrt(zx * zx + zy * zy + zz * zz);
|
|
577 if (mag) {
|
|
578 zx /= mag;
|
|
579 zy /= mag;
|
|
580 zz /= mag;
|
|
581 }
|
|
582
|
|
583 // Y vector
|
|
584 var yx = upx;
|
|
585 var yy = upy;
|
|
586 var yz = upz;
|
|
587
|
|
588 // X vector = Y cross Z
|
|
589 xx = yy * zz - yz * zy;
|
|
590 xy = -yx * zz + yz * zx;
|
|
591 xz = yx * zy - yy * zx;
|
|
592
|
|
593 // Recompute Y = Z cross X
|
|
594 yx = zy * xz - zz * xy;
|
|
595 yy = -zx * xz + zz * xx;
|
|
596 yx = zx * xy - zy * xx;
|
|
597
|
|
598 // cross product gives area of parallelogram, which is < 1.0 for
|
|
599 // non-perpendicular unit-length vectors; so normalize x, y here
|
|
600
|
|
601 mag = Math.sqrt(xx * xx + xy * xy + xz * xz);
|
|
602 if (mag) {
|
|
603 xx /= mag;
|
|
604 xy /= mag;
|
|
605 xz /= mag;
|
|
606 }
|
|
607
|
|
608 mag = Math.sqrt(yx * yx + yy * yy + yz * yz);
|
|
609 if (mag) {
|
|
610 yx /= mag;
|
|
611 yy /= mag;
|
|
612 yz /= mag;
|
|
613 }
|
|
614
|
|
615 matrix.m11 = xx;
|
|
616 matrix.m12 = xy;
|
|
617 matrix.m13 = xz;
|
|
618 matrix.m14 = 0;
|
|
619
|
|
620 matrix.m21 = yx;
|
|
621 matrix.m22 = yy;
|
|
622 matrix.m23 = yz;
|
|
623 matrix.m24 = 0;
|
|
624
|
|
625 matrix.m31 = zx;
|
|
626 matrix.m32 = zy;
|
|
627 matrix.m33 = zz;
|
|
628 matrix.m34 = 0;
|
|
629
|
|
630 matrix.m41 = 0;
|
|
631 matrix.m42 = 0;
|
|
632 matrix.m43 = 0;
|
|
633 matrix.m44 = 1;
|
|
634 matrix.translate(-eyex, -eyey, -eyez);
|
|
635
|
|
636 this.multRight(matrix);
|
|
637 }
|
|
638
|
|
639 // Support functions
|
|
640 CanvasMatrix4.prototype._determinant2x2 = function(a, b, c, d)
|
|
641 {
|
|
642 return a * d - b * c;
|
|
643 }
|
|
644
|
|
645 CanvasMatrix4.prototype._determinant3x3 = function(a1, a2, a3, b1, b2, b3, c1, c2, c3)
|
|
646 {
|
|
647 return a1 * this._determinant2x2(b2, b3, c2, c3)
|
|
648 - b1 * this._determinant2x2(a2, a3, c2, c3)
|
|
649 + c1 * this._determinant2x2(a2, a3, b2, b3);
|
|
650 }
|
|
651
|
|
652 CanvasMatrix4.prototype._determinant4x4 = function()
|
|
653 {
|
|
654 var a1 = this.m11;
|
|
655 var b1 = this.m12;
|
|
656 var c1 = this.m13;
|
|
657 var d1 = this.m14;
|
|
658
|
|
659 var a2 = this.m21;
|
|
660 var b2 = this.m22;
|
|
661 var c2 = this.m23;
|
|
662 var d2 = this.m24;
|
|
663
|
|
664 var a3 = this.m31;
|
|
665 var b3 = this.m32;
|
|
666 var c3 = this.m33;
|
|
667 var d3 = this.m34;
|
|
668
|
|
669 var a4 = this.m41;
|
|
670 var b4 = this.m42;
|
|
671 var c4 = this.m43;
|
|
672 var d4 = this.m44;
|
|
673
|
|
674 return a1 * this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)
|
|
675 - b1 * this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)
|
|
676 + c1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)
|
|
677 - d1 * this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
|
678 }
|
|
679
|
|
680 CanvasMatrix4.prototype._makeAdjoint = function()
|
|
681 {
|
|
682 var a1 = this.m11;
|
|
683 var b1 = this.m12;
|
|
684 var c1 = this.m13;
|
|
685 var d1 = this.m14;
|
|
686
|
|
687 var a2 = this.m21;
|
|
688 var b2 = this.m22;
|
|
689 var c2 = this.m23;
|
|
690 var d2 = this.m24;
|
|
691
|
|
692 var a3 = this.m31;
|
|
693 var b3 = this.m32;
|
|
694 var c3 = this.m33;
|
|
695 var d3 = this.m34;
|
|
696
|
|
697 var a4 = this.m41;
|
|
698 var b4 = this.m42;
|
|
699 var c4 = this.m43;
|
|
700 var d4 = this.m44;
|
|
701
|
|
702 // Row column labeling reversed since we transpose rows & columns
|
|
703 this.m11 = this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
|
|
704 this.m21 = - this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
|
|
705 this.m31 = this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
|
|
706 this.m41 = - this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
|
|
707
|
|
708 this.m12 = - this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
|
|
709 this.m22 = this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
|
|
710 this.m32 = - this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
|
|
711 this.m42 = this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
|
|
712
|
|
713 this.m13 = this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
|
|
714 this.m23 = - this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
|
|
715 this.m33 = this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
|
|
716 this.m43 = - this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
|
|
717
|
|
718 this.m14 = - this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
|
|
719 this.m24 = this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
|
|
720 this.m34 = - this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
|
|
721 this.m44 = this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
|
|
722 } |