1 /*
  2 SpiderGL Computer Graphics Library
  3 Copyright (c) 2010, Marco Di Benedetto - Visual Computing Lab, ISTI - CNR
  4 All rights reserved.
  5 
  6 Redistribution and use in source and binary forms, with or without
  7 modification, are permitted provided that the following conditions are met:
  8     * Redistributions of source code must retain the above copyright
  9       notice, this list of conditions and the following disclaimer.
 10     * Redistributions in binary form must reproduce the above copyright
 11       notice, this list of conditions and the following disclaimer in the
 12       documentation and/or other materials provided with the distribution.
 13     * Neither the name of SpiderGL nor the
 14       names of its contributors may be used to endorse or promote products
 15       derived from this software without specific prior written permission.
 16 
 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 20 DISCLAIMED. IN NO EVENT SHALL PAUL BRUNT BE LIABLE FOR ANY
 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 27 */
 28 
 29 /**
 30  * @fileOverview Space
 31  */
 32 
 33 /**
 34  * The SpiderGL.Space namespace.
 35  *
 36  * @namespace The SpiderGL.Space namespace.
 37  */
 38 SpiderGL.Space = { };
 39 
 40 /**
 41  * Creates a SpiderGL.Space.MatrixStack.
 42  *
 43  * SpiderGL.Space.MatrixStack is a stack for 4x4 matrices. Initially, the stack depth is one and contains an identity matrix.
 44  * Every method or getter to access the top matrix (or a derivation like inverse or transpose) returns a copy of the internal matrix.
 45  * For performance reasons, variants of the above accessors (having the same identifier with the postfix "$" appended) that return a reference to the internal matrix are also present.
 46  * The transpose, inverse, and inverse-transpose of the top matrix are calculated and cached when they are accessed.
 47  *
 48  * @class The SpiderGL.Space.MatrixStack is a stack for 4x4 matrices.
 49  *
 50  * @augments SpiderGL.Core.ObjectBase
 51  *
 52  * @param {function(this)} [onChange] A callback function called whenever the stack is modified.
 53  *
 54  * @example
 55  * var s = new SpiderGL.Space.MatrixStack();
 56  * s.loadIdentity();
 57  * s.scale([2, 0.5, 2]);
 58  * for (var i=0; i<n; ++i) {
 59  * 	s.push();
 60  * 		s.translate(positions[i]);
 61  * 		matrices[i] = {
 62  * 			m  : s.matrix,
 63  * 			i  : s.inverse,
 64  * 			t  : s.transpose,
 65  * 			it : s.inverseTranspose
 66  * 		};
 67  * 	s.pop();
 68  * }
 69  *
 70  * @see reset
 71  * @see SpiderGL.Space.TransformationStack
 72  */
 73 SpiderGL.Space.MatrixStack = function (onChange) {
 74 	SpiderGL.Core.ObjectBase.call(this);
 75 
 76 	this._onChange = null;
 77 	this.reset();
 78 	this._onChange = onChange;
 79 }
 80 
 81 SpiderGL.Space.MatrixStack.prototype = {
 82 	_invalidate : function () {
 83 		this._i  = null;
 84 		this._t  = null;
 85 		this._it = null;
 86 		if (this._onChange) {
 87 			this._onChange(this);
 88 		}
 89 	},
 90 
 91 	/**
 92 	 * Resets the stack.
 93 	 * The stack is reset to its initial state, that is, a stack with depth one containing the identity matrix.
 94 	 *
 95 	 * @see SpiderGL.Math.Mat4.identity
 96 	 */
 97 	reset : function () {
 98 		var m = SpiderGL.Math.Mat4.identity();
 99 		this._s  = [ m ];
100 		this._l  = 1;
101 		this._m  = m;
102 		this._i  = m;
103 		this._t  = m;
104 		this._it = m;
105 		if (this._onChange) {
106 			this._onChange(this);
107 		}
108 	},
109 
110 	/**
111 	 * Gets/Sets the callback invoked whenever the top matrix changes.
112 	 * Initially, no callback is defined.
113 	 *
114 	 * @event
115 	 */
116 	get onChange() {
117 		return this._onChange;
118 	},
119 
120 	set onChange(f) {
121 		this._onChange = f;
122 	},
123 
124 	/**
125 	 * Gets the stack depth.
126 	 * Initially, the stack contains an identity matrix, so its depth is one.
127 	 *
128 	 * @type number
129 	 *
130 	 * @readonly
131 	 */
132 	get size() {
133 		return this._l;
134 	},
135 
136 	/**
137 	 * Gets a reference to the matrix at the top of the stack.
138 	 * The returned array MUST NOT be changed.
139 	 * Initially, the stack has depth one and contains an identity matrix.
140 	 *
141 	 * @type array
142 	 *
143 	 * @readonly
144 	 *
145 	 * @see #matrix
146 	 */
147 	get matrix$() {
148 		return this._m;
149 	},
150 
151 	/**
152 	 * Gets a copy of the matrix at the top of the stack.
153 	 * Initially, the stack has depth one and contains an identity matrix.
154 	 *
155 	 * @type array
156 	 *
157 	 * @readonly
158 	 *
159 	 * @see #matrix$
160 	 */
161 	get matrix() {
162 		return SpiderGL.Math.Mat4.dup(this.matrix$);
163 	},
164 
165 	/**
166 	 * Alias for #matrix$.
167 	 *
168 	 * @type array
169 	 *
170 	 * @readonly
171 	 *
172 	 * @see #top
173 	 * @see #matrix$
174 	 */
175 	get top$() {
176 		return this.matrix$;
177 	},
178 
179 	/**
180 	 * Alias for #matrix.
181 	 *
182 	 * @type array
183 	 *
184 	 * @readonly
185 	 *
186 	 * @see #top$
187 	 * @see #matrix
188 	 */
189 	get top() {
190 		return this.matrix;
191 	},
192 
193 	/**
194 	 * Gets a reference to the inverse of the matrix at the top of the stack.
195 	 * The returned array MUST NOT be changed.
196 	 *
197 	 * @type array
198 	 *
199 	 * @readonly
200 	 *
201 	 * @see #inverse
202 	 */
203 	get inverse$() {
204 		return (this._i || (this._i = SpiderGL.Math.Mat4.inverse(this._m)));
205 	},
206 
207 	/**
208 	 * Gets a copy of the inverse of the matrix at the top of the stack.
209 	 *
210 	 * @type array
211 	 *
212 	 * @readonly
213 	 *
214 	 * @see #inverse$
215 	 */
216 	get inverse() {
217 		return SpiderGL.Math.Mat4.dup(this.inverse$);
218 	},
219 
220 	/**
221 	 * Gets a reference to the transpose of the matrix at the top of the stack.
222 	 * The returned array MUST NOT be changed.
223 	 *
224 	 * @type array
225 	 *
226 	 * @readonly
227 	 *
228 	 * @see #transpose
229 	 */
230 	get transpose$() {
231 		return (this._t || (this._t = SpiderGL.Math.Mat4.transpose(this._m)));
232 	},
233 
234 	/**
235 	 * Gets a copy of the transpose of the matrix at the top of the stack.
236 	 *
237 	 * @type array
238 	 *
239 	 * @readonly
240 	 *
241 	 * @see #transpose$
242 	 */
243 	get transpose() {
244 		return SpiderGL.Math.Mat4.dup(this.transpose$);
245 	},
246 
247 	/**
248 	 * Gets a reference to the transpose of the inverse of the matrix at the top of the stack.
249 	 * The returned array MUST NOT be changed.
250 	 *
251 	 * @type array
252 	 *
253 	 * @readonly
254 	 *
255 	 * @see #inverseTranspose
256 	 */
257 	get inverseTranspose$() {
258 		return (this._it || (this._it = SpiderGL.Math.Mat4.transpose(this.inverse$)));
259 	},
260 
261 	/**
262 	 * Gets a copy of the transpose of the inverse of the matrix at the top of the stack.
263 	 *
264 	 * @type array
265 	 *
266 	 * @readonly
267 	 *
268 	 * @see #inverseTranspose$
269 	 */
270 	get inverseTranspose() {
271 		return SpiderGL.Math.Mat4.dup(this.inverseTranspose$);
272 	},
273 
274 	/**
275 	 * Pushes into the stack the matrix at its top.
276 	 * After a push operation, the stack depth is incremented by one and the two matrices at its top are identical.
277 	 * There is no limit on the depth the stack can reach.
278 	 *
279 	 * @see #pop
280 	 */
281 	push : function () {
282 		var m = SpiderGL.Math.Mat4.dup(this._m);
283 		this._s.push(m);
284 		this._l++;
285 		this._m = m;
286 	},
287 
288 	/**
289 	 * Pops the stack.
290 	 * After a pop operation, the stack depth is decremented by one.
291 	 * Nothing is done if the stack has only one element.
292 	 *
293 	 * @see #push
294 	 */
295 	pop : function () {
296 		if (this._l <= 1) return;
297 		this._s.pop();
298 		this._l--;
299 		this._m = this._s[this._l - 1];
300 		this._invalidate();
301 	},
302 
303 	/**
304 	 * Replaces the matrix at the top with a clone of the passed matrix.
305 	 *
306 	 * @param {array} m The matrix whose clone will be set as the top of the stack.
307 	 *
308 	 * @see #loadIdentity
309 	 * @see #multiply
310 	 * @see SpiderGL.Math.Mat4.dup
311 	 */
312 	load : function (m) {
313 		m = SpiderGL.Math.Mat4.dup(m);
314 		this._s[this._l - 1] = m;
315 		this._m = m;
316 		this._invalidate();
317 	},
318 
319 	/**
320 	 * Replaces the matrix at the top with an identity matrix.
321 	 *
322 	 * @see #load
323 	 * @see #multiply
324 	 * @see SpiderGL.Math.Mat4.identity
325 	 * @see SpiderGL.Math.Mat4.identity$
326 	 */
327 	loadIdentity : function () {
328 		var m = SpiderGL.Math.Mat4.identity$(this._m);
329 		this._i  = m;
330 		this._t  = m;
331 		this._it = m;
332 	},
333 
334 	/**
335 	 * Post-multiplies the matrix at the top with the passed matrix
336 	 * The matrix a at the top will be replaced by a * m.
337 	 *
338 	 * @param {array} m The matrix to post-multiply.
339 	 *
340 	 * @see #load
341 	 * @see SpiderGL.Math.Mat4.mul
342 	 * @see SpiderGL.Math.Mat4.mul$
343 	 */
344 	multiply : function (m) {
345 		SpiderGL.Math.Mat4.mul$(this._m, m);
346 		this._invalidate();
347 	},
348 
349 	/**
350 	 * Post-multiplies the matrix at the top with an ortographic projection matrix.
351 	 *
352 	 * @param {array} min The minimum coordinates of the parallel viewing volume.
353 	 * @param {array} max The maximum coordinates of the parallel viewing volume.
354 	 *
355 	 * @see #frustum
356 	 * @see #perspective
357 	 * @see SpiderGL.Math.Mat4.ortho
358 	 * @see SpiderGL.Math.Mat4.mul$
359 	 */
360 	ortho : function (min, max) {
361 		SpiderGL.Math.Mat4.mul$(this._m, SpiderGL.Math.Mat4.ortho(min, max));
362 		this._invalidate();
363 	},
364 
365 	/**
366 	 * Post-multiplies the matrix at the top with a frustum matrix.
367 	 *
368 	 * @param {array} min A 3-component array with the minimum coordinates of the frustum volume.
369 	 * @param {array} max A 3-component array with the maximum coordinates of the frustum volume.
370 	 *
371 	 * @see #perspective
372 	 * @see #ortho
373 	 * @see SpiderGL.Math.Mat4.frustum
374 	 * @see SpiderGL.Math.Mat4.mul$
375 	 */
376 	frustum : function (min, max) {
377 		SpiderGL.Math.Mat4.mul$(this._m, SpiderGL.Math.Mat4.frustum(min, max));
378 		this._invalidate();
379 	},
380 
381 	/**
382 	 * Post-multiplies the matrix at the top with a perspective projection matrix.
383 	 *
384 	 * @param {number} fovY The vertical field-of-view angle, in radians.
385 	 * @param {number} aspectRatio The projection plane aspect ratio.
386 	 * @param {number} zNear The distance of the near clipping plane.
387 	 * @param {number} zFar The distance of the far clipping plane.
388 	 *
389 	 * @see #frustum
390 	 * @see #ortho
391 	 * @see SpiderGL.Math.Mat4.perspective
392 	 * @see SpiderGL.Math.Mat4.mul$
393 	 */
394 	perspective : function (fovY, aspectRatio, zNear, zFar) {
395 		SpiderGL.Math.Mat4.mul$(this._m, SpiderGL.Math.Mat4.perspective(fovY, aspectRatio, zNear, zFar));
396 		this._invalidate();
397 	},
398 
399 	/**
400 	 * Post-multiplies the matrix at the top with a look-at matrix.
401 	 *
402 	 * @param {array} position The viewer's position as a 3-dimensional vector.
403 	 * @param {array} target The viewer's look-at point as a 3-dimensional vector.
404 	 * @param {array} position The viewer's up vector as a 3-dimensional vector.
405 	 *
406 	 * @see SpiderGL.Math.Mat4.lookAt
407 	 * @see SpiderGL.Math.Mat4.mul$
408 	 */
409 	lookAt : function (position, target, up) {
410 		SpiderGL.Math.Mat4.mul$(this._m, SpiderGL.Math.Mat4.lookAt(position, target, up));
411 		this._invalidate();
412 	},
413 
414 	/**
415 	 * Post-multiplies the matrix at the top with a translation matrix.
416 	 *
417 	 * @param {array} v A 3-dimensional vector with translation offsets.
418 	 *
419 	 * @see #rotate
420 	 * @see #scale
421 	 * @see SpiderGL.Math.Mat4.translation
422 	 * @see SpiderGL.Math.Mat4.translate$
423 	 */
424 	translate : function (v) {
425 		SpiderGL.Math.Mat4.translate$(this._m, v);
426 		this._invalidate();
427 	},
428 
429 	/**
430 	 * Post-multiplies the matrix at the top with a rotation matrix.
431 	 *
432 	 * @param {number} angle The counter-clockwise rotation angle, in radians.
433 	 * @param {array} axis A 3-dimensional vector representing the rotation axis.
434 	 *
435 	 * @see #translate
436 	 * @see #scale
437 	 * @see SpiderGL.Math.Mat4.rotationAngleAxis
438 	 * @see SpiderGL.Math.Mat4.rotateAngleAxis$
439 	 */
440 	rotate : function (angle, axis) {
441 		SpiderGL.Math.Mat4.rotateAngleAxis$(this._m, angle, axis);
442 		this._invalidate();
443 	},
444 
445 	/**
446 	 * Post-multiplies the matrix at the top with a scaling matrix.
447 	 *
448 	 * @param {array} v The scaling amount as a 3-dimensional array.
449 	 *
450 	 * @see #translate
451 	 * @see #rotate
452 	 * @see SpiderGL.Math.Mat4.scaling
453 	 * @see SpiderGL.Math.Mat4.scale$
454 	 */
455 	scale : function (v) {
456 		SpiderGL.Math.Mat4.scale$(this._m, v);
457 		this._invalidate();
458 	}
459 };
460 
461 SpiderGL.Type.extend(SpiderGL.Space.MatrixStack, SpiderGL.Core.ObjectBase);
462 
463 /**
464  * Creates a SpiderGL.Space.ViewportStack.
465  *
466  * SpiderGL.Space.ViewportStack is a stack for viewport rectangles, specified with lower and left coordinates, width and height.
467  * Initially, the stack depth is one and contains a rectangle with lower-eft coordinates equal to zero and width and height equal to one, that is, the array [0, 0, 1, 1].
468  * Every method or getter to access the top rectangle returns a copy of the internal rectangle.
469  * For performance reasons, variants of the above accessors (having the same identifier with the postfix "$" appended) that return a reference to the internal rectangle are also present.
470  *
471  * @class The SpiderGL.Space.ViewportStack is a stack for viewport rectangles.
472  *
473  * @augments SpiderGL.Core.ObjectBase
474  *
475  * @param {function(this)} [onChange] A callback function called whenever the stack is modified.
476  *
477  * @example
478  * var s  = new SpiderGL.Space.ViewportStack();
479  * var dw = width  / nx;
480  * var dh = height / ny;
481  * s.load(x, y, width, height);
482  * for (var x=0; x<nx; ++x) {
483  * 	for (var y=0; y<ny; ++y) {
484  * 	s.push();
485 		s.inner([x*dw, y*dh, dw, dh]);
486 		viewports.push(s.rect);
487  * 	s.pop();
488  * }
489  *
490  * @see reset
491  * @see SpiderGL.Space.TransformationStack
492  */
493 SpiderGL.Space.ViewportStack = function (onChange) {
494 	SpiderGL.Core.ObjectBase.call(this);
495 
496 	this._onChange = null;
497 	this.reset();
498 	this._onChange = onChange;
499 }
500 
501 SpiderGL.Space.ViewportStack.prototype = {
502 	_invalidate : function () {
503 		if (this._onChange) {
504 			this._onChange(this);
505 		}
506 	},
507 
508 	/**
509 	 * Resets the stack.
510 	 * The stack is reset to its initial state, that is, a stack with depth one containing the identity rectangle, that is, [0, 0, 1, 1].
511 	 *
512 	 * @see #loadIdentity
513 	 */
514 	reset : function () {
515 		var r = [0, 0, 1, 1];
516 		this._s  = [ r ];
517 		this._l  = 1;
518 		this._r  = r;
519 		if (this._onChange) {
520 			this._onChange(this);
521 		}
522 	},
523 
524 	/**
525 	 * Gets/Sets the callback invoked whenever the top rectangle changes.
526 	 * Initially, no callback is defined.
527 	 *
528 	 * @event
529 	 */
530 	get onChange() {
531 		return this._onChange;
532 	},
533 
534 	set onChange(f) {
535 		this._onChange = f;
536 	},
537 
538 	/**
539 	 * Gets the stack depth.
540 	 * Initially, the stack contains the identity rectangle, that is, [0, 0, 1, 1].
541 	 *
542 	 * @type number
543 	 *
544 	 * @readonly
545 	 */
546 	get size() {
547 		return this._l;
548 	},
549 
550 	/**
551 	 * Gets a reference to the rectangle at the top of the stack.
552 	 * The returned array MUST NOT be changed.
553 	 * Initially, the stack has depth one and contains the identity rectangle, that is, [0, 0, 1, 1].
554 	 *
555 	 * @type array
556 	 *
557 	 * @readonly
558 	 *
559 	 * @see #rect
560 	 */
561 	get rect$() {
562 		return this._r;
563 	},
564 
565 	/**
566 	 * Gets a copy of the matrix at the top of the stack.
567 	 * Initially, the stack has depth one and contains the identity rectangle, that is, [0, 0, 1, 1].
568 	 *
569 	 * @type array
570 	 *
571 	 * @readonly
572 	 *
573 	 * @see #rect$
574 	 */
575 	get rect() {
576 		return this.rect$.slice(0, 4);
577 	},
578 
579 	/**
580 	 * Alias for #rect$.
581 	 *
582 	 * @type array
583 	 *
584 	 * @readonly
585 	 *
586 	 * @see #top
587 	 * @see #rect$
588 	 */
589 	get top$() {
590 		return this.rect$;
591 	},
592 
593 	/**
594 	 * Alias for #rect.
595 	 *
596 	 * @type array
597 	 *
598 	 * @readonly
599 	 *
600 	 * @see #top$
601 	 * @see #rect
602 	 */
603 	get top() {
604 		return this.rect;
605 	},
606 
607 	/**
608 	 * Pushes into the stack the rectangle at its top.
609 	 * After a push operation, the stack depth is incremented by one and the two rectangle at its top are identical.
610 	 * There is no limit on the depth the stack can reach.
611 	 *
612 	 * @see #pop
613 	 */
614 	push : function () {
615 		var r = this._r.slice(0, 4);
616 		this._s.push(r);
617 		this._l++;
618 		this._r = r;
619 	},
620 
621 	/**
622 	 * Pops the stack.
623 	 * After a pop operation, the stack depth is decremented by one.
624 	 * Nothing is done if the stack has only one element.
625 	 *
626 	 * @see #push
627 	 */
628 	pop : function () {
629 		if (this._l <= 1) return;
630 		this._s.pop();
631 		this._l--;
632 		this._r = this._s[this._l - 1];
633 		this._invalidate();
634 	},
635 
636 	/**
637 	 * Replaces the rectangle at the top with a clone of the passed rectangle.
638 	 *
639 	 * @param {array} m The rectangle whose clone will be set as the top of the stack.
640 	 *
641 	 * @see #loadIdentity
642 	 * @see #inner
643 	 */
644 	load : function (r) {
645 		r = r.slice(0, 4);
646 		this._s[this._l - 1] = r;
647 		this._r = r;
648 		this._invalidate();
649 	},
650 
651 	/**
652 	 * Replaces the rectangle at the top with the identity rectangle, that is, [0, 0, 1, 1].
653 	 *
654 	 * @see #load
655 	 * @see #inner
656 	 */
657 	loadIdentity : function () {
658 		var r = [0, 0, 1, 1];
659 		this._r  = r;
660 	},
661 
662 	/**
663 	 * Replace the rectangle r at the top of the stack with Post-multiplies the matrix at the top with the passed matrix
664 	 * The matrix a at the top will be replaced by a * m.
665 	 *
666 	 * @param {array} m The matrix to post-multiply.
667 	 *
668 	 * @see #load
669 	 */
670 	inner : function (r) {
671 		this._r[0] += r[0];
672 		this._r[1] += r[1];
673 		this._r[2]  = r[2];
674 		this._r[3]  = r[3];
675 		this._invalidate();
676 	}
677 };
678 
679 SpiderGL.Type.extend(SpiderGL.Space.ViewportStack, SpiderGL.Core.ObjectBase);
680 
681 /**
682  * Creates a SpiderGL.Space.ViewportStack.
683  *
684  * SpiderGL.Space.ViewportStack is a stack for viewport rectangles, specified with lower and left coordinates, width and height.
685  * Initially, the stack depth is one and contains a rectangle with lower-eft coordinates equal to zero and width and height equal to one, that is, the array [0, 0, 1, 1].
686  * Every method or getter to access the top rectangle returns a copy of the internal rectangle.
687  * For performance reasons, variants of the above accessors (having the same identifier with the postfix "$" appended) that return a reference to the internal rectangle are also present.
688  *
689  * @class The SpiderGL.Space.ViewportStack is a stack for viewport rectangles.
690  *
691  * @augments SpiderGL.Core.ObjectBase
692  *
693  * @param {function(this)} [onChange] A callback function called whenever the stack is modified.
694  *
695  * @example
696  * var s  = new SpiderGL.Space.ViewportStack();
697  * var dw = width  / nx;
698  * var dh = height / ny;
699  * s.load(x, y, width, height);
700  * for (var x=0; x<nx; ++x) {
701  * 	for (var y=0; y<ny; ++y) {
702  * 	s.push();
703 		s.inner([0, 0, dw, dh]);
704 		viewports.push(s.rect);
705  * 	s.pop();
706  * }
707  *
708  * @see reset
709  * @see SpiderGL.Space.TransformationStack
710  */
711 SpiderGL.Space.DepthRangeStack = function (onChange) {
712 	SpiderGL.Core.ObjectBase.call(this);
713 
714 	this._onChange = null;
715 	this.reset();
716 	this._onChange = onChange;
717 }
718 
719 SpiderGL.Space.DepthRangeStack.prototype = {
720 	_invalidate : function () {
721 		if (this._onChange) {
722 			this._onChange(this);
723 		}
724 	},
725 
726 	/**
727 	 * Resets the stack.
728 	 * The stack is reset to its initial state, that is, a stack with depth one containing the identity rectangle, that is, [0, 0, 1, 1].
729 	 *
730 	 * @see #loadIdentity
731 	 */
732 	reset : function () {
733 		var r = [0, 1];
734 		this._s  = [ r ];
735 		this._l  = 1;
736 		this._r  = r;
737 		if (this._onChange) {
738 			this._onChange(this);
739 		}
740 	},
741 
742 	/**
743 	 * Gets/Sets the callback invoked whenever the top rectangle changes.
744 	 * Initially, no callback is defined.
745 	 *
746 	 * @event
747 	 */
748 	get onChange() {
749 		return this._onChange;
750 	},
751 
752 	set onChange(f) {
753 		this._onChange = f;
754 	},
755 
756 	/**
757 	 * Gets the stack depth
758 	 * Initially, the stack contains an identity matrix, so its depth is one.
759 	 *
760 	 * @type number
761 	 *
762 	 * @readonly
763 	 */
764 	get size() {
765 		return this._l;
766 	},
767 
768 	/**
769 	 * Gets a reference to the matrix at the top of the stack.
770 	 * The returned array MUST NOT be changed.
771 	 * Initially, the stack has depth one and contains an identity matrix.
772 	 *
773 	 * @type array
774 	 *
775 	 * @readonly
776 	 *
777 	 * @see #matrix
778 	 */
779 	get range$() {
780 		return this._r;
781 	},
782 
783 	/**
784 	 * Gets a copy of the matrix at the top of the stack.
785 	 * Initially, the stack has depth one and contains an identity matrix.
786 	 *
787 	 * @type array
788 	 *
789 	 * @readonly
790 	 *
791 	 * @see #matrix$
792 	 */
793 	get range() {
794 		return this.range$.slice(0, 2);
795 	},
796 
797 	/**
798 	 * Alias for #rect$.
799 	 *
800 	 * @type array
801 	 *
802 	 * @readonly
803 	 *
804 	 * @see #top
805 	 * @see #rect$
806 	 */
807 	get top$() {
808 		return this.range$;
809 	},
810 
811 	/**
812 	 * Alias for #rect.
813 	 *
814 	 * @type array
815 	 *
816 	 * @readonly
817 	 *
818 	 * @see #top$
819 	 * @see #rect
820 	 */
821 	get top() {
822 		return this.range;
823 	},
824 
825 	/**
826 	 * Pushes into the stack the range at its top.
827 	 * After a push operation, the stack depth is incremented by one and the two rectangle at its top are identical.
828 	 * There is no limit on the depth the stack can reach.
829 	 *
830 	 * @see #pop
831 	 */
832 	push : function () {
833 		var r = this._r.slice(0, 2);
834 		this._s.push(r);
835 		this._l++;
836 		this._r = r;
837 	},
838 
839 	/**
840 	 * Pops the stack.
841 	 * After a pop operation, the stack depth is decremented by one.
842 	 * Nothing is done if the stack has only one element.
843 	 *
844 	 * @see #push
845 	 */
846 	pop : function () {
847 		if (this._l <= 1) return;
848 		this._s.pop();
849 		this._l--;
850 		this._r = this._s[this._l - 1];
851 		this._invalidate();
852 	},
853 
854 	/**
855 	 * Replaces the matrix at the top with a clone of the passed matrix.
856 	 *
857 	 * @param {array} m The matrix to push on the stack. The matrix actually pushed is a clone of m.
858 	 *
859 	 * @see #loadIdentity
860 	 * @see #multiply
861 	 * @see SpiderGL.Math.Mat4.dup
862 	 */
863 	load : function (r) {
864 		r = r.slice(0, 2);
865 		this._s[this._l - 1] = r;
866 		this._r = r;
867 		this._invalidate();
868 	},
869 
870 	/**
871 	 * Replaces the matrix at the top with an identity matrix.
872 	 *
873 	 * @see #load
874 	 * @see #multiply
875 	 * @see SpiderGL.Math.Mat4.identity
876 	 * @see SpiderGL.Math.Mat4.identity$
877 	 */
878 	loadIdentity : function () {
879 		var r = [0, 1];
880 		this._r  = r;
881 	},
882 
883 	/**
884 	 * Post-multiplies the matrix at the top with the passed matrix
885 	 * The matrix a at the top will be replaced by a * m.
886 	 *
887 	 * @param {array} m The matrix to post-multiply.
888 	 *
889 	 * @see #load
890 	 */
891 	inner : function (r) {
892 		this._r[0] += r[0];
893 		this._r[1]  = r[1];
894 		this._invalidate();
895 	}
896 };
897 
898 SpiderGL.Type.extend(SpiderGL.Space.DepthRangeStack, SpiderGL.Core.ObjectBase);
899 
900 /**
901  * Creates a SpiderGL.Space.TransformationStack.
902  *
903  * The purpose of SpiderGL.Space.TransformationStack is to provide transformation stack similar to the one in the fixed-pipeline versions of OpenGL.
904  * Differently from OpenGL, which has two stacks, namely MODELVIEW and PRIJECTION, the SpiderGL.Space.TransformationStack is composed of three SpiderGL.Space.MatrixStack stacks: model, view and projection.
905  * All three stacks can be directly accessed, as well as utility getters to obtain compositions of matrices, e.g. model-view-projection, model-view-inverse etc.
906  * To avoid recalculation of several sub-products, matrix compositions and variations are cached and updated when stack operations occur.
907  *
908  * @class The SpiderGL.Space.TransformationStack holds the model, view and projection matrix stacks and calculates their matrix compositions.
909  *
910  * @augments SpiderGL.Core.ObjectBase
911  *
912  * @example
913  * var xform = new SpiderGL.Space.TransformationStack();
914  *
915  * var uniforms = {
916  * 	uModelViewprojection : null,
917  * 	uNormalMatrix        : null,
918  * 	uColor               : null
919  * };
920  *
921  * program.bind();
922  *
923  * xform.projection.loadIdentity();
924  * xform.projection.perspective(SpiderGL.Math.degToRad(60.0), width/height, 0.1, 100.0);
925  *
926  * xform.view.loadIdentity();
927  * xform.view.lookAt([0, 0, 10], [0, 0, 0], [0, 1, 0]);
928  *
929  * xform.model.loadIdentity();
930  * xform.model.scale([0.1, 0.1, 0.1]);
931  *
932  * for (var i=0; i<n; ++i) {
933  * 	s.push();
934  * 		s.translate(models[i].positions);
935  * 		uniforms.uModelViewProjection = xform.modelViewProjectionMatrix;
936  * 		uniforms.uNormalMatrix        = xform.modelSpaceNormalMatrix;
937  * 		uniforms.uColor               = models[i].color;
938  * 		program.setUniforms(uniforms);
939  * 		drawModel(models[i]);
940  * 	s.pop();
941  * }
942  *
943  * @see reset
944  * @see SpiderGL.Space.MatrixStack
945  */
946 SpiderGL.Space.TransformationStack = function () {
947 	SpiderGL.Core.ObjectBase.call(this);
948 
949 	var that = this;
950 
951 	this._mv  = { };
952 	this._vp  = { };
953 	this._mvp = { };
954 	this._n   = { };
955 	this._c   = { };
956 
957 	this._m = new SpiderGL.Space.MatrixStack(function(){
958 		that._mv  = { };
959 		that._mvp = { };
960 		that._n   = { };
961 		that._c   = { };
962 	});
963 
964 	this._v = new SpiderGL.Space.MatrixStack(function(){
965 		that._mv  = { };
966 		that._vp  = { };
967 		that._mvp = { };
968 		that._n   = { };
969 		that._c   = { };
970 	});
971 
972 	this._p = new SpiderGL.Space.MatrixStack(function(){
973 		that._vp  = { };
974 		that._mvp = { };
975 	});
976 
977 	this._viewport = new SpiderGL.Space.ViewportStack(function(){
978 	});
979 
980 	this._depth = new SpiderGL.Space.DepthRangeStack(function(){
981 	});
982 }
983 
984 SpiderGL.Space.TransformationStack.prototype = {
985 	/**
986 	 * Resets the three stacks.
987 	 *
988 	 * @see SpiderGL.Space.MatrixStack.reset
989 	 */
990 	reset : function () {
991 		this._m.reset();
992 		this._v.reset();
993 		this._p.reset();
994 	},
995 
996 	/**
997 	 * Gets the viewport stack.
998 	 *
999 	 * @type SpiderGL.Space.ViewportStack
1000 	 *
1001 	 * @see depthRange
1002 	 */
1003 	get viewport() {
1004 		return this._viewport;
1005 	},
1006 
1007 	get viewportRect$() {
1008 		return this._viewport.rect$;
1009 	},
1010 
1011 	get viewportRect() {
1012 		return this._viewport.rect;
1013 	},
1014 
1015 	/**
1016 	 * Gets the depth range stack.
1017 	 *
1018 	 * @type SpiderGL.Space.DepthRangeStack
1019 	 *
1020 	 * @see viewport
1021 	 */
1022 	get depth() {
1023 		return this._depth;
1024 	},
1025 
1026 	get depthRange$() {
1027 		return this._depth.range$;
1028 	},
1029 
1030 	get depthRange() {
1031 		return this._depth.range;
1032 	},
1033 
1034 	/**
1035 	 * Gets the model stack.
1036 	 *
1037 	 * @type SpiderGL.Space.MatrixStack
1038 	 *
1039 	 * @see view
1040 	 * @see projection
1041 	 */
1042 	get model() {
1043 		return this._m;
1044 	},
1045 
1046 	/**
1047 	 * Gets a reference to the top matrix of the model stack.
1048 	 * The returned array MUST NOT be changed.
1049 	 *
1050 	 * @see modelMatrix
1051 	 * @see SpiderGL.Space.MatrixStack.matrix$
1052 	 */
1053 	get modelMatrix$() {
1054 		return this._m.matrix$;
1055 	},
1056 
1057 	/**
1058 	 * Gets a copy of the top matrix of the model stack.
1059 	 *
1060 	 * @type array
1061 	 *
1062 	 * @see modelMatrix$
1063 	 * @see SpiderGL.Space.MatrixStack.matrix
1064 	 */
1065 	get modelMatrix() {
1066 		return this._m.matrix;
1067 	},
1068 
1069 	/**
1070 	 * Gets a reference to the inverse of the top matrix of the model stack.
1071 	 * The returned array MUST NOT be changed.
1072 	 *
1073 	 * @type array
1074 	 *
1075 	 * @see modelMatrixInverse
1076 	 * @see SpiderGL.Space.MatrixStack.inverse$
1077 	 */
1078 	get modelMatrixInverse$() {
1079 		return this._m.inverse$;
1080 	},
1081 
1082 	/**
1083 	 * Gets a copy of the inverse of the top matrix of the model stack.
1084 	 *
1085 	 * @type array
1086 	 *
1087 	 * @see modelMatrixInverse$
1088 	 * @see SpiderGL.Space.MatrixStack.inverse
1089 	 */
1090 	get modelMatrixInverse() {
1091 		return this._m.inverse;
1092 	},
1093 
1094 	/**
1095 	 * Gets a reference to the transpose of the top matrix of the model stack.
1096 	 * The returned array MUST NOT be changed.
1097 	 *
1098 	 * @type array
1099 	 *
1100 	 * @see modelMatrixTranspose
1101 	 * @see SpiderGL.Space.MatrixStack.transpose$
1102 	 */
1103 	get modelMatrixTranspose$() {
1104 		return this._m.transpose$;
1105 	},
1106 
1107 	/**
1108 	 * Gets a copy of the transpose of the top matrix of the model stack.
1109 	 *
1110 	 * @type array
1111 	 *
1112 	 * @see modelMatrixTranspose$
1113 	 * @see SpiderGL.Space.MatrixStack.transpose
1114 	 */
1115 	get modelMatrixTranspose() {
1116 		return this._m.transpose;
1117 	},
1118 
1119 	/**
1120 	 * Gets a reference to the transpose of the inverse of the top matrix of the model stack.
1121 	 * The returned array MUST NOT be changed.
1122 	 *
1123 	 * @type array
1124 	 *
1125 	 * @see modelMatrixInverseTranspose
1126 	 * @see SpiderGL.Space.MatrixStack.inverseTranspose$
1127 	 */
1128 	get modelMatrixInverseTranspose$() {
1129 		return this._m.inverseTranspose$;
1130 	},
1131 
1132 	/**
1133 	 * Gets a copy of the transpose of the inverse of the top matrix of the model stack.
1134 	 *
1135 	 * @type array
1136 	 *
1137 	 * @see modelMatrixInverseTranspose$
1138 	 * @see SpiderGL.Space.MatrixStack.inverseTranspose
1139 	 */
1140 	get modelMatrixInverseTranspose() {
1141 		return this._m.inverseTranspose;
1142 	},
1143 
1144 	/**
1145 	 * Gets the view stack.
1146 	 *
1147 	 * @type SpiderGL.Space.MatrixStack
1148 	 *
1149 	 * @see model
1150 	 * @see projection
1151 	 */
1152 	get view() {
1153 		return this._v;
1154 	},
1155 
1156 	/**
1157 	 * Gets a reference to the top matrix of the view stack.
1158 	 * The returned array MUST NOT be changed.
1159 	 *
1160 	 * @type array
1161 	 *
1162 	 * @see viewMatrix
1163 	 * @see SpiderGL.Space.MatrixStack.matrix$
1164 	 */
1165 	get viewMatrix$() {
1166 		return this._v.matrix$;
1167 	},
1168 
1169 	/**
1170 	 * Gets a copy of the top matrix of the view stack.
1171 	 *
1172 	 * @type array
1173 	 *
1174 	 * @see viewMatrix$
1175 	 * @see SpiderGL.Space.MatrixStack.matrix
1176 	 */
1177 	get viewMatrix() {
1178 		return this._v.matrix;
1179 	},
1180 
1181 	/**
1182 	 * Gets a reference to the inverse of the top matrix of the view stack.
1183 	 * The returned array MUST NOT be changed.
1184 	 *
1185 	 * @type array
1186 	 *
1187 	 * @see viewMatrixInverse
1188 	 * @see SpiderGL.Space.MatrixStack.inverse$
1189 	 */
1190 	get viewMatrixInverse$() {
1191 		return this._v.inverse$;
1192 	},
1193 
1194 	/**
1195 	 * Gets a copy of the inverse of the top matrix of the view stack.
1196 	 *
1197 	 * @type array
1198 	 *
1199 	 * @see viewMatrixInverse$
1200 	 * @see SpiderGL.Space.MatrixStack.inverse
1201 	 */
1202 	get viewMatrixInverse() {
1203 		return this._v.inverse;
1204 	},
1205 
1206 	/**
1207 	 * Gets a reference to the transpose of the top matrix of the view stack.
1208 	 * The returned array MUST NOT be changed.
1209 	 *
1210 	 * @type array
1211 	 *
1212 	 * @see viewMatrixTranspose
1213 	 * @see SpiderGL.Space.MatrixStack.transpose$
1214 	 */
1215 	get viewMatrixTranspose$() {
1216 		return this._v.transpose$;
1217 	},
1218 
1219 	/**
1220 	 * Gets a copy of the transpose of the top matrix of the view stack.
1221 	 *
1222 	 * @type array
1223 	 *
1224 	 * @see viewMatrixTranspose$
1225 	 * @see SpiderGL.Space.MatrixStack.transpose
1226 	 */
1227 	get viewMatrixTranspose() {
1228 		return this._v.transpose;
1229 	},
1230 
1231 	/**
1232 	 * Gets a reference to the transpose of the inverse of the top matrix of the view stack.
1233 	 * The returned array MUST NOT be changed.
1234 	 *
1235 	 * @type array
1236 	 *
1237 	 * @see viewMatrixInverseTranspose
1238 	 * @see SpiderGL.Space.MatrixStack.inverseTranspose$
1239 	 */
1240 	get viewMatrixInverseTranspose$() {
1241 		return this._v.inverseTranspose$;
1242 	},
1243 
1244 	/**
1245 	 * Gets a copy of the transpose of the inverse of the top matrix of the view stack.
1246 	 *
1247 	 * @type array
1248 	 *
1249 	 * @see viewMatrixInverseTranspose$
1250 	 * @see SpiderGL.Space.MatrixStack.inverseTranspose
1251 	 */
1252 	get viewMatrixInverseTranspose() {
1253 		return this._v.inverseTranspose;
1254 	},
1255 
1256 	/**
1257 	 * Gets the projection stack.
1258 	 *
1259 	 * @type SpiderGL.Space.MatrixStack
1260 	 *
1261 	 * @see model
1262 	 * @see view
1263 	 */
1264 	get projection() {
1265 		return this._p;
1266 	},
1267 
1268 	/**
1269 	 * Gets a reference to the top matrix of the projection stack.
1270 	 * The returned array MUST NOT be changed.
1271 	 *
1272 	 * @type array
1273 	 *
1274 	 * @see projectionMatrix
1275 	 * @see SpiderGL.Space.MatrixStack.matrix$
1276 	 */
1277 	get projectionMatrix$() {
1278 		return this._p.matrix$;
1279 	},
1280 
1281 	/**
1282 	 * Gets a copy of the top matrix of the projection stack.
1283 	 *
1284 	 * @type array
1285 	 *
1286 	 * @see projectionMatrix$
1287 	 * @see SpiderGL.Space.MatrixStack.matrix
1288 	 */
1289 	get projectionMatrix() {
1290 		return this._p.matrix;
1291 	},
1292 
1293 	/**
1294 	 * Gets a reference to the inverse of the top matrix of the projection stack.
1295 	 * The returned array MUST NOT be changed.
1296 	 *
1297 	 * @type array
1298 	 *
1299 	 * @see projectionMatrixInverse
1300 	 * @see SpiderGL.Space.MatrixStack.inverse$
1301 	 */
1302 	get projectionMatrixInverse$() {
1303 		return this._p.inverse$;
1304 	},
1305 
1306 	/**
1307 	 * Gets a copy of the inverse of the top matrix of the projection stack.
1308 	 *
1309 	 * @type array
1310 	 *
1311 	 * @see projectionMatrixInverse$
1312 	 * @see SpiderGL.Space.MatrixStack.inverse
1313 	 */
1314 	get projectionMatrixInverse() {
1315 		return this._p.inverse;
1316 	},
1317 
1318 	/**
1319 	 * Gets a reference to the transpose of the top matrix of the projection stack.
1320 	 * The returned array MUST NOT be changed.
1321 	 *
1322 	 * @type array
1323 	 *
1324 	 * @see projectionMatrixTranspose
1325 	 * @see SpiderGL.Space.MatrixStack.transpose$
1326 	 */
1327 	get projectionMatrixTranspose$() {
1328 		return this._p.transpose$;
1329 	},
1330 
1331 	/**
1332 	 * Gets a copy of the transpose of the top matrix of the projection stack.
1333 	 *
1334 	 * @type array
1335 	 *
1336 	 * @see projectionMatrixTranspose$
1337 	 * @see SpiderGL.Space.MatrixStack.transpose
1338 	 */
1339 	get projectionMatrixTranspose() {
1340 		return this._p.transpose;
1341 	},
1342 
1343 	/**
1344 	 * Gets a reference to the transpose of the inverse of the top matrix of the projection stack.
1345 	 * The returned array MUST NOT be changed.
1346 	 *
1347 	 * @type array
1348 	 *
1349 	 * @see projectionMatrixInverseTranspose
1350 	 * @see SpiderGL.Space.MatrixStack.inverseTranspose$
1351 	 */
1352 	get projectionMatrixInverseTranspose$() {
1353 		return this._p.inverseTranspose$;
1354 	},
1355 
1356 	/**
1357 	 * Gets a copy of the transpose of the inverse of the top matrix of the projection stack.
1358 	 *
1359 	 * @type array
1360 	 *
1361 	 * @see projectionMatrixInverseTranspose$
1362 	 * @see SpiderGL.Space.MatrixStack.inverseTranspose
1363 	 */
1364 	get projectionMatrixInverseTranspose() {
1365 		return this._p.inverseTranspose;
1366 	},
1367 
1368 	/**
1369 	 * Gets a reference to the matrix T = V * M, where V is the view matrix and M the model matrix.
1370 	 * The returned array MUST NOT be changed.
1371 	 *
1372 	 * @type array
1373 	 *
1374 	 * @see modelViewMatrix
1375 	 */
1376 	get modelViewMatrix$() {
1377 		return (this._mv.m || (this._mv.m = SpiderGL.Math.Mat4.mul(this.viewMatrix$, this.modelMatrix$)));
1378 	},
1379 
1380 	/**
1381 	 * Gets a copy of the matrix T = V * M, where V is the view matrix and M the model matrix.
1382 	 *
1383 	 * @type array
1384 	 *
1385 	 * @see modelViewMatrix$
1386 	 */
1387 	get modelViewMatrix() {
1388 		return SpiderGL.Math.Mat4.dup(this.modelViewMatrix$);
1389 	},
1390 
1391 	/**
1392 	 * Gets a reference to the inverse of the matrix T = V * M, where V is the view matrix and M the model matrix.
1393 	 * The returned array MUST NOT be changed.
1394 	 *
1395 	 * @type array
1396 	 *
1397 	 * @see modelViewMatrixInverse
1398 	 */
1399 	get modelViewMatrixInverse$() {
1400 		return (this._mv.i || (this._mv.i = SpiderGL.Math.Mat4.mul(this.modelMatrixInverse$, this.viewMatrixInverse$)));
1401 	},
1402 
1403 	/**
1404 	 * Gets a copy of the inverse of the matrix T = V * M, where V is the view matrix and M the model matrix.
1405 	 *
1406 	 * @type array
1407 	 *
1408 	 * @see modelViewMatrixInverse$
1409 	 */
1410 	get modelViewMatrixInverse() {
1411 		return SpiderGL.Math.Mat4.dup(this.modelViewMatrixInverse$);
1412 	},
1413 
1414 	/**
1415 	 * Gets a reference to the transpose of the matrix T = V * M, where V is the view matrix and M the model matrix.
1416 	 * The returned array MUST NOT be changed.
1417 	 *
1418 	 * @type array
1419 	 *
1420 	 * @see modelViewMatrixTranspose
1421 	 */
1422 	get modelViewMatrixTranspose$() {
1423 		return (this._mv.t || (this._mv.t = SpiderGL.Math.Mat4.transpose(this.modelViewMatrix$)));
1424 	},
1425 
1426 	/**
1427 	 * Gets a copy of the transpose of the matrix T = V * M, where V is the view matrix and M the model matrix.
1428 	 *
1429 	 * @type array
1430 	 *
1431 	 * @see modelViewMatrixTranspose$
1432 	 */
1433 	get modelViewMatrixTranspose() {
1434 		return SpiderGL.Math.Mat4.dup(this.modelViewMatrixTranspose$);
1435 	},
1436 
1437 	/**
1438 	 * Gets a reference to the transpose of the inverse of the matrix T = V * M, where V is the view matrix and M the model matrix.
1439 	 * The returned array MUST NOT be changed.
1440 	 *
1441 	 * @type array
1442 	 *
1443 	 * @see modelViewMatrixInverseTranspose
1444 	 */
1445 	get modelViewMatrixInverseTranspose$() {
1446 		return (this._mv.it || (this._mv.it = SpiderGL.Math.Mat4.transpose(this.modelViewMatrixInverse$)));
1447 	},
1448 
1449 	/**
1450 	 * Gets a copy of the transpose of the inverse of the matrix T = V * M, where V is the view matrix and M the model matrix.
1451 	 *
1452 	 * @type array
1453 	 *
1454 	 * @see modelViewMatrixInverseTranspose$
1455 	 */
1456 	get modelViewMatrixInverseTranspose() {
1457 		return SpiderGL.Math.Mat4.dup(this.modelViewMatrixInverseTranspose$);
1458 	},
1459 
1460 	/**
1461 	 * Gets a reference to the matrix T = P * V, where P is the projection matrix and V the view matrix.
1462 	 * The returned array MUST NOT be changed.
1463 	 *
1464 	 * @type array
1465 	 *
1466 	 * @see viewProjectionMatrix
1467 	 */
1468 	get viewProjectionMatrix$() {
1469 		return (this._vp.m || (this._vp.m = SpiderGL.Math.Mat4.mul(this.projectionMatrix$, this.viewMatrix$)));
1470 	},
1471 
1472 	/**
1473 	 * Gets a copy of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1474 	 *
1475 	 * @type array
1476 	 *
1477 	 * @see viewProjectionMatrix$
1478 	 */
1479 	get viewProjectionMatrix() {
1480 		return SpiderGL.Math.Mat4.dup(this.viewProjectionMatrix$);
1481 	},
1482 
1483 	/**
1484 	 * Gets a reference to the inverse of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1485 	 * The returned array MUST NOT be changed.
1486 	 *
1487 	 * @type array
1488 	 *
1489 	 * @see viewProjectionMatrixInverse
1490 	 */
1491 	get viewProjectionMatrixInverse$() {
1492 		return (this._vp.i || (this._vp.i = SpiderGL.Math.Mat4.mul(this.viewMatrixInverse$, this.projectionMatrixInverse$)));
1493 	},
1494 
1495 	/**
1496 	 * Gets a copy of the inverse of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1497 	 *
1498 	 * @type array
1499 	 *
1500 	 * @see viewProjectionMatrixInverse$
1501 	 */
1502 	get viewProjectionMatrixInverse() {
1503 		return SpiderGL.Math.Mat4.dup(this.viewProjectionMatrixInverse$);
1504 	},
1505 
1506 	/**
1507 	 * Gets a reference to the transpose of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1508 	 * The returned array MUST NOT be changed.
1509 	 *
1510 	 * @type array
1511 	 *
1512 	 * @see viewProjectionMatrixTranspose
1513 	 */
1514 	get viewProjectionMatrixTranspose$() {
1515 		return (this._vp.t || (this._vp.t = SpiderGL.Math.Mat4.transpose(this.viewProjectionMatrix$)));
1516 	},
1517 
1518 	/**
1519 	 * Gets a copy of the transpose of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1520 	 *
1521 	 * @type array
1522 	 *
1523 	 * @see viewProjectionMatrixTranspose$
1524 	 */
1525 	get viewProjectionMatrixTranspose() {
1526 		return SpiderGL.Math.Mat4.dup(this.viewProjectionMatrixTranspose$);
1527 	},
1528 
1529 	/**
1530 	 * Gets a reference to the transpose of the inverse of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1531 	 * The returned array MUST NOT be changed.
1532 	 *
1533 	 * @type array
1534 	 *
1535 	 * @see viewProjectionMatrixInverseTranspose
1536 	 */
1537 	get viewProjectionMatrixInverseTranspose$() {
1538 		return (this._vp.it || (this._vp.it = SpiderGL.Math.Mat4.transpose(this.viewProjectionMatrixInverse$)));
1539 	},
1540 
1541 	/**
1542 	 * Gets a copy of the transpose of the inverse of the matrix T = P * V, where P is the projection matrix and V the view matrix.
1543 	 *
1544 	 * @type array
1545 	 *
1546 	 * @see viewProjectionMatrixInverseTranspose$
1547 	 */
1548 	get viewProjectionMatrixInverseTranspose() {
1549 		return SpiderGL.Math.Mat4.dup(this.viewProjectionMatrixInverseTranspose$);
1550 	},
1551 
1552 	/**
1553 	 * Gets a reference to the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1554 	 * The returned array MUST NOT be changed.
1555 	 *
1556 	 * @type array
1557 	 *
1558 	 * @see modelViewProjectionMatrix
1559 	 */
1560 	get modelViewProjectionMatrix$() {
1561 		return (this._mvp.m || (this._mvp.m = SpiderGL.Math.Mat4.mul(this.viewProjectionMatrix$, this.modelMatrix$)));
1562 	},
1563 
1564 	/**
1565 	 * Gets a copy of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1566 	 *
1567 	 * @type array
1568 	 *
1569 	 * @see modelViewProjectionMatrix$
1570 	 */
1571 	get modelViewProjectionMatrix() {
1572 		return SpiderGL.Math.Mat4.dup(this.modelViewProjectionMatrix$);
1573 	},
1574 
1575 	/**
1576 	 * Gets a reference to the inverse of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1577 	 * The returned array MUST NOT be changed.
1578 	 *
1579 	 * @type array
1580 	 *
1581 	 * @see modelViewProjectionMatrix
1582 	 */
1583 	get modelViewProjectionMatrixInverse$() {
1584 		return (this._mvp.i || (this._mvp.i = SpiderGL.Math.Mat4.inverse(this.modelViewProjectionMatrix$)));
1585 	},
1586 
1587 	/**
1588 	 * Gets a copy of the inverse of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1589 	 *
1590 	 * @type array
1591 	 *
1592 	 * @see modelViewProjectionMatrix$
1593 	 */
1594 	get modelViewProjectionMatrixInverse() {
1595 		return SpiderGL.Math.Mat4.dup(this.modelViewProjectionMatrixInverse$);
1596 	},
1597 
1598 	/**
1599 	 * Gets a reference to the transpose of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1600 	 * The returned array MUST NOT be changed.
1601 	 *
1602 	 * @type array
1603 	 *
1604 	 * @see modelViewProjectionMatrixTranspose
1605 	 */
1606 	get modelViewProjectionMatrixTranspose$() {
1607 		return (this._mvp.t || (this._mvp.t = SpiderGL.Math.Mat4.transpose(this.modelViewProjectionMatrix$)));
1608 	},
1609 
1610 	/**
1611 	 * Gets a copy of the transpose of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1612 	 *
1613 	 * @type array
1614 	 *
1615 	 * @see modelViewProjectionMatrixTranspose$
1616 	 */
1617 	get modelViewProjectionMatrixTranspose() {
1618 		return SpiderGL.Math.Mat4.dup(this.modelViewProjectionMatrixTranspose$);
1619 	},
1620 
1621 	/**
1622 	 * Gets a reference to the transpose of the inverse of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1623 	 * The returned array MUST NOT be changed.
1624 	 *
1625 	 * @type array
1626 	 *
1627 	 * @see modelViewProjectionMatrixInverseTranspose
1628 	 */
1629 	get modelViewProjectionMatrixInverseTranspose$() {
1630 		return (this._mvp.it || (this._mvp.it = SpiderGL.Math.Mat4.transpose(this.modelViewProjectionMatrixInverse$)));
1631 	},
1632 
1633 	/**
1634 	 * Gets a copy of the transpose of the inverse of the matrix T = P * V * M, where P is the projection matrix, V the view matrix and M the model matrix.
1635 	 *
1636 	 * @type array
1637 	 *
1638 	 * @see modelViewProjectionMatrixInverseTranspose$
1639 	 */
1640 	get modelViewProjectionMatrixInverseTranspose() {
1641 		return SpiderGL.Math.Mat4.dup(this.modelViewProjectionMatrixInverseTranspose$);
1642 	},
1643 
1644 	/**
1645 	 * Gets a reference to the transpose of the inverse of the upper-left 3x3 matrix of the model matrix.
1646 	 * The returned array MUST NOT be changed.
1647 	 *
1648 	 * @type array
1649 	 *
1650 	 * @see worldSpaceNormalMatrix
1651 	 * @see viewSpaceNormalMatrix$
1652 	 */
1653 	get worldSpaceNormalMatrix$() {
1654 		return (this._n.m || (this._n.m = SpiderGL.Math.Mat4.inverseTranspose33(this.modelMatrix$)));
1655 	},
1656 
1657 	/**
1658 	 * Gets a copy of the transpose of the inverse of the upper-left 3x3 matrix of the model matrix.
1659 	 *
1660 	 * @type array
1661 	 *
1662 	 * @see worldSpaceNormalMatrix$
1663 	 * @see viewSpaceNormalMatrix
1664 	 */
1665 	get worldSpaceNormalMatrix() {
1666 		return SpiderGL.Math.Mat4.dup(this.worldSpaceNormalMatrix$);
1667 	},
1668 
1669 	/**
1670 	 * Gets a reference to the transpose of the inverse of the upper-left 3x3 matrix of the model-view matrix.
1671 	 * The returned array MUST NOT be changed.
1672 	 *
1673 	 * @type array
1674 	 *
1675 	 * @see viewSpaceNormalMatrix
1676 	 * @see worldSpaceNormalMatrix$
1677 	 */
1678 	get viewSpaceNormalMatrix$() {
1679 		return (this._n.v || (this._n.v = SpiderGL.Math.Mat4.inverseTranspose33(this.modelViewMatrix$)));
1680 	},
1681 
1682 	/**
1683 	 * Gets a copy of the transpose of the inverse of the upper-left 3x3 matrix of the model matrix.
1684 	 *
1685 	 * @type array
1686 	 *
1687 	 * @see viewSpaceNormalMatrix$
1688 	 * @see worldSpaceNormalMatrix
1689 	 */
1690 	get viewSpaceNormalMatrix() {
1691 		return SpiderGL.Math.Mat4.dup(this.viewSpaceNormalMatrix$);
1692 	},
1693 
1694 	/**
1695 	 * Gets a reference to the 3-dimensional vector representing the 4th column of the inverse of the model-view matrix.
1696 	 * The returned array MUST NOT be changed.
1697 	 *
1698 	 * @type array
1699 	 *
1700 	 * @see modelSpaceViewerPosition
1701 	 * @see modelSpaceViewDirection$
1702 	 * @see worldSpaceViewerPosition$
1703 	 */
1704 	get modelSpaceViewerPosition$() {
1705 		return (this._c.mp || (this._c.mp = SpiderGL.Math.Vec4.to3(SpiderGL.Math.Mat4.col(this.modelViewMatrixInverse$, 3))));
1706 	},
1707 
1708 	/**
1709 	 * Gets a copy of the 3-dimensional vector representing the 4th column of the inverse of the model-view matrix.
1710 	 *
1711 	 * @type array
1712 	 *
1713 	 * @see modelSpaceViewerPosition$
1714 	 * @see modelSpaceViewDirection$
1715 	 * @see worldSpaceViewerPosition
1716 	 */
1717 	get modelSpaceViewerPosition() {
1718 		return SpiderGL.Math.Vec3.dup(this.modelSpaceViewerPosition$);
1719 	},
1720 
1721 	/**
1722 	 * Gets a reference to the 3-dimensional vector representing the 4th column of the inverse of the view matrix.
1723 	 * The returned array MUST NOT be changed.
1724 	 *
1725 	 * @type array
1726 	 *
1727 	 * @see worldSpaceViewerPosition
1728 	 * @see worldSpaceViewDirection$
1729 	 * @see modelSpaceViewerPosition$
1730 	 */
1731 	get worldSpaceViewerPosition$() {
1732 		return (this._c.wp || (this._c.wp = SpiderGL.Math.Vec4.to3(SpiderGL.Math.Mat4.col(this.viewMatrixInverse$, 3))));
1733 	},
1734 
1735 	/**
1736 	 * Gets a copy of the 3-dimensional vector representing the 4th column of the inverse of the model-view matrix.
1737 	 *
1738 	 * @type array
1739 	 *
1740 	 * @see worldSpaceViewerPosition$
1741 	 * @see worldSpaceViewDirection
1742 	 * @see modelSpaceViewerPosition
1743 	 */
1744 	get worldSpaceViewerPosition() {
1745 		return SpiderGL.Math.Vec3.dup(this.worldSpaceViewerPosition$);
1746 	},
1747 
1748 	/**
1749 	 * Gets a reference to the 3-dimensional vector representing the negated 3rd row of the inverse of the model-view matrix.
1750 	 * The returned array MUST NOT be changed.
1751 	 *
1752 	 * @type array
1753 	 *
1754 	 * @see modelSpaceViewDirection
1755 	 * @see modelSpaceViewerPosition$
1756 	 * @see worldSpaceViewDirection$
1757 	 */
1758 	get modelSpaceViewDirection$() {
1759 		return (this._c.md || (this._c.md = SpiderGL.Math.Vec3.normalize$(SpiderGL.Math.Vec3.neg$(SpiderGL.Math.Vec4.to3(SpiderGL.Math.Mat4.row(this.modelViewMatrixInverse$, 2))))));
1760 	},
1761 
1762 	/**
1763 	 * Gets a copy of the 3-dimensional vector representing the negated 3rd row of the inverse of the model-view matrix.
1764 	 *
1765 	 * @type array
1766 	 *
1767 	 * @see modelSpaceViewDirection$
1768 	 * @see modelSpaceViewerPosition
1769 	 * @see worldSpaceViewDirection
1770 	 */
1771 	get modelSpaceViewDirection() {
1772 		return SpiderGL.Math.Vec3.dup(this.modelSpaceViewDirection$);
1773 	},
1774 
1775 	/**
1776 	 * Gets a reference to the 3-dimensional vector representing the negated 3rd row of the inverse of the view matrix.
1777 	 * The returned array MUST NOT be changed.
1778 	 *
1779 	 * @type array
1780 	 *
1781 	 * @see worldSpaceViewDirection
1782 	 * @see worldSpaceViewerPosition$
1783 	 * @see modelSpaceViewDirection$
1784 	 */
1785 	get worldSpaceViewDirection$() {
1786 		return (this._c.wd || (this._c.wd = SpiderGL.Math.Vec3.normalize$(SpiderGL.Math.Vec3.neg$(SpiderGL.Math.Vec4.to3(SpiderGL.Math.Mat4.row(this.viewMatrixInverse$, 2))))));
1787 	},
1788 
1789 	/**
1790 	 * Gets a reference to the 3-dimensional vector representing the negated 3rd row of the inverse of the model-view matrix.
1791 	 *
1792 	 * @type array
1793 	 *
1794 	 * @see worldSpaceViewDirection$
1795 	 * @see worldSpaceViewerPosition
1796 	 * @see modelSpaceViewDirection
1797 	 */
1798 	get worldSpaceViewDirection() {
1799 		return SpiderGL.Math.Vec3.dup(this.worldSpaceViewDirection$);
1800 	},
1801 
1802 	project : function(xyzw) {
1803 		return SpiderGL.Math.project(xyzw, this.modelViewProjectionMatrix$, this.viewportRect$, this.depthRange$);
1804 	},
1805 
1806 	unproject : function(xyz) {
1807 		return SpiderGL.Math.unproject(xyz, this.modelViewProjectionMatrixInverse$, this.viewportRect$, this.depthRange$);
1808 	}
1809 };
1810 
1811 SpiderGL.Type.extend(SpiderGL.Space.TransformationStack, SpiderGL.Core.ObjectBase);
1812 
1813