Mercurial > hg > Members > e085711
comparison webGL/dandy/resources/CanvasMatrix.js @ 3:10344afb38a6
upload dandy
author | NOBUYASU Oshiro |
---|---|
date | Mon, 07 Jun 2010 17:58:31 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:be36da713ffd | 3:10344afb38a6 |
---|---|
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 } |