root/trunk/helix/linalgebra.d

Revision 5, 102.7 kB (checked in by nail, 6 years ago)

Initial import

Line 
1 /*
2 Redistribution and use in source and binary forms, with or without
3 modification, are permitted provided that the following conditions
4 are met:
5
6     Redistributions of source code must retain the above copyright
7     notice, this list of conditions and the following disclaimer.
8
9     Redistributions in binary form must reproduce the above
10     copyright notice, this list of conditions and the following
11     disclaimer in the documentation and/or other materials provided
12     with the distribution.
13
14     Neither name of Victor Nakoryakov nor the names of
15     its contributors may be used to endorse or promote products
16     derived from this software without specific prior written
17     permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 Copyright (C) 2006. Victor Nakoryakov.
33 */
34 /**
35 Module consists of basic mathematical objects oriented to working with 3D
36 graphics.
37
38 Those are 2,3,4-D vectors, quaternion, 3x3 and 4x4 matrices. In case of
39 specialization for 3D graphics there are always some features and deviation
40 from classical math. Here I summarize such features of helix'es linear algebra:
41 $(UL
42     $(LI In helix paradigm of column-vector is taken. So multiplication of matrix
43          by vector makes sense but multiplication of vector by matrix makes not.
44          This approach conforms to rules accepted in classical math and coincides
45          with OpenGL rules. However this is opposite to Direct3D paradigm where
46          vector is a row. So, in helix, to combine sequence of transforms specified with
47          matrices A, B, C in order A then B then C, you have to multiply them in
48          back-to-front order order: M=C*B*A. )
49
50     $(LI When an issue deal with euler angles following definitions are accepted.
51          Yaw is rotation around Y, Pitch is rotaion around X, Roll is rotation around Z
52          Rotations are always applied in order: Roll then Pitch then Yaw. )
53
54     $(LI Helix matrices use column-major memory layout. I.e. matrix
55         $(MAT33
56             $(MAT33_ROW a, b, c)
57             $(MAT33_ROW d, e, f)
58             $(MAT33_ROW g, h, i)
59         )
60         in memory will looks like: a, d, g, b, e, h, c, f, i. This order is the same as
61         in OpenGL API, but opposite to Direct3D API. However as mentioned above, Direct3D
62         uses vector-row paradigm that is opposite to classical math, so D3D requires
63         transposed matrix as compared to classical math to get desired transformation. As a
64         result you haven't to transpose helix matrix while transmission to API even in Direct3D
65         case. Normaly you haven't to remember about memory layout, just use it as in classical
66         math, this feature is significant only in routines that operate with data pointers
67         and plain array representation. There are reminders in such methods' documentation. )
68 )
69
70 Authors:
71     Victor Nakoryakov, nail-mail[at]mail.ru
72     
73 Macros:
74     MAT33     = <table style="border-left: double 3px #666666; border-right: double 3px #666666;
75                  margin-left: 3em;">$0</table>
76     MAT33_ROW = <tr><td>$1</td><td>$2</td><td>$3</td></tr>
77 */
78 module helix.linalgebra;
79
80 private import helix.basic,
81                helix.config;
82
83 /** Defines ort names that are usualy used as indices. */
84 enum Ort
85 {
86     X, ///
87     Y, /// ditto
88     Z, /// ditto
89     W  /// ditto
90 }
91
92 /**
93 Wrapper template to provide possibility to use different float types
94 in implemented structs and routines.
95 */
96 private template LinearAlgebra(float_t)
97 {
98     private alias helix.basic.equal          equal;
99    
100     alias .LinearAlgebra!(float).Vector2     Vector2f;
101     alias .LinearAlgebra!(float).Vector3     Vector3f;
102     alias .LinearAlgebra!(float).Vector4     Vector4f;
103     alias .LinearAlgebra!(float).Quaternion  Quaternionf;
104     alias .LinearAlgebra!(float).Matrix33    Matrix33f;
105     alias .LinearAlgebra!(float).Matrix44    Matrix44f;
106    
107     alias .LinearAlgebra!(double).Vector2    Vector2d;
108     alias .LinearAlgebra!(double).Vector3    Vector3d;
109     alias .LinearAlgebra!(double).Vector4    Vector4d;
110     alias .LinearAlgebra!(double).Quaternion Quaterniond;
111     alias .LinearAlgebra!(double).Matrix33   Matrix33d;
112     alias .LinearAlgebra!(double).Matrix44   Matrix44d;
113    
114     alias .LinearAlgebra!(real).Vector2      Vector2r;
115     alias .LinearAlgebra!(real).Vector3      Vector3r;
116     alias .LinearAlgebra!(real).Vector4      Vector4r;
117     alias .LinearAlgebra!(real).Quaternion   Quaternionr;
118     alias .LinearAlgebra!(real).Matrix33     Matrix33r;
119     alias .LinearAlgebra!(real).Matrix44     Matrix44r;
120
121     /************************************************************************************
122     Two dimensional vector.
123
124     For formal definition of vector, meaning of possible operations and related
125     information see $(LINK http://en.wikipedia.org/wiki/Vector_(spatial)).
126     *************************************************************************************/
127     struct Vector2
128     {
129         align(1)
130         {
131             float_t x; /// Components of vector.
132             float_t y; /// ditto
133         }
134        
135         static Vector2 nan = { float_t.nan, float_t.nan }; /// Vector with both components seted to NaN.
136         static Vector2 unitX = { 1, 0 };                   /// Unit vector codirectional with corresponding axis.
137         static Vector2 unitY = { 0, 1 };                   /// ditto
138        
139         /**
140         Method to construct vector in C-like syntax.
141
142         Examples:
143         ------------
144         Vector2 myVector = Vector2(1, 2);
145         ------------
146         */
147         static Vector2 opCall(float_t x, float_t y)
148         {
149             Vector2 v;
150             v.set(x, y);
151             return v;
152         }
153        
154         /** Sets values of components to passed values. */
155         void set(float_t x, float_t y)
156         {
157             this.x = x;
158             this.y = y;
159         }
160        
161         /** Returns: Norm (also known as length, magnitude) of vector. */
162         real norm()
163         {
164             return hypot(x, y);
165         }
166    
167         /**
168         Returns: Square of vector's norm.
169         
170         Since this method doesn't need calculation of square root it is better
171         to use it instead of norm() when you can. For example, if you want just
172         to know which of 2 vectors is longer it's better to compare their norm
173         squares instead of their norm.
174         */
175         real normSquare()
176         {
177             return x*x + y*y;
178         }
179    
180         /** Normalizes this vector. */
181         void normalize()
182         {
183             *this /= norm;
184         }
185    
186         /** Returns: Normalized copy of this vector. */
187         Vector2 normalized()
188         {
189             real n = norm;
190             return Vector2(x / n, y / n);
191         }
192    
193         /**
194         Returns: Whether this vector is unit.
195         Params:
196             relprec, absprec = Parameters passed to equal function while comparison of
197                                norm square and 1. Have the same meaning as in equal function.
198         */
199         bool isUnit(int relprec = defrelprec, int absprec = defabsprec)
200         {
201             return equal( normSquare(), 1, relprec, absprec );
202         }
203    
204         /** Returns: Axis for which projection of this vector on it will be longest. */
205         Ort dominatingAxis()
206         {
207             return (x > y) ? Ort.X : Ort.Y;
208         }
209    
210         /** Returns: Whether all components are normalized numbers. */
211         bool isnormal()
212         {
213             return std.math.isnormal(x) && std.math.isnormal(y);
214         }
215    
216         /** Returns: float_t pointer to x component of this vector. It's like a _ptr method for arrays. */
217         float_t* ptr()
218         {
219             return cast(float_t*)this;
220         }
221    
222         /** Returns: Component corresponded to passed index. */
223         float_t opIndex(Ort ort)
224         in { assert(ort <= Ort.Y); }
225         body
226         {
227             return ptr[cast(int)ort];
228         }
229    
230         /** Assigns new _value to component corresponded to passed index. */
231         void opIndexAssign(float_t value, Ort ort)
232         in { assert(ort <= Ort.Y); }
233         body
234         {
235             ptr[cast(int)ort] = value;
236         }
237    
238         /**
239         Standard operators that have intuitive meaning, same as in classical math.
240         
241         Note that division operators do no cheks of value of k, so in case of division
242         by 0 result vector will have infinity components. You can check this with isnormal()
243         method.
244         */
245         bool opEquals(Vector2 v)
246         {
247             return x == v.x && y == v.y;
248         }
249    
250         /** ditto */
251         Vector2 opNeg()
252         {
253             return Vector2(-x, -y);
254         }
255    
256         /** ditto */
257         Vector2 opAdd(Vector2 v)
258         {
259             return Vector2(x + v.x, y + v.y);
260         }
261    
262         /** ditto */
263         void opAddAssign(Vector2 v)
264         {
265             x += v.x;
266             y += v.y;
267         }
268    
269         /** ditto */
270         Vector2 opSub(Vector2 v)
271         {
272             return Vector2(x - v.x, y - v.y);
273         }
274    
275         /** ditto */
276         void opSubAssign(Vector2 v)
277         {
278             x -= v.x;
279             y -= v.y;
280         }
281    
282         /** ditto */
283         Vector2 opMul(real k)
284         {
285             return Vector2(x * k, y * k);
286         }
287    
288         /** ditto */
289         void opMulAssign(real k)
290         {
291             x *= k;
292             y *= k;
293         }
294    
295         /** ditto */
296         Vector2 opMul_r(real k)
297         {
298             return Vector2(x * k, y * k);
299         }
300    
301         /** ditto */
302         Vector2 opDiv(real k)
303         {
304             return Vector2(x / k, y / k);
305         }
306    
307         /** ditto */
308         void opDivAssign(real k)
309         {
310             x /= k;
311             y /= k;
312         }
313    
314         /** Returns: Copy of this vector with float type components */
315         Vector2f toVector2f()
316         {
317             return Vector2f(cast(float)x, cast(float)y);
318         }
319        
320         /** Returns: Copy of this vector with double type components */
321         Vector2d toVector2d()
322         {
323             return Vector2d(cast(double)x, cast(double)y);
324         }
325        
326         /** Returns: Copy of this vector with real type components */
327         Vector2r toVector2r()
328         {
329             return Vector2r(cast(real)x, cast(real)y);
330         }
331    
332         /**
333         Routines known as swizzling.
334         Returns:
335             New vector constructed from this one and having component values
336             that correspond to method name.
337         */
338         Vector3 xy0()    { return Vector3(x, y, 0); }
339         Vector3 x0y()    { return Vector3(x, 0, y); } /// ditto
340     }
341    
342     /** Returns: Dot product between passed vectors. */
343     real dp(Vector2 a, Vector2 b)
344     {
345         return a.x * b.x + a.y * b.y;
346     }
347        
348     alias EqualityByNorm!(Vector2).equal equal; /// Introduces approximate equality function for Vector2.
349     alias Lerp!(Vector2).lerp lerp;             /// Introduces linear interpolaton function for Vector2.
350    
351    
352     /************************************************************************************
353     Three dimensional vector.
354
355     For formal definition of vector, meaning of possible operations and related
356     information see $(LINK http://en.wikipedia.org/wiki/Vector_(spatial)).
357     *************************************************************************************/
358     struct Vector3
359     {
360         align(1)
361         {
362             float_t x; /// Components of vector.
363             float_t y; /// ditto
364             float_t z; /// ditto
365         }
366        
367         static Vector3 nan = { float_t.nan, float_t.nan, float_t.nan }; /// Vector with all components seted to NaN.
368         static Vector3 unitX = { 1, 0, 0 };  /// Unit vector codirectional with corresponding axis.
369         static Vector3 unitY = { 0, 1, 0 };  /// ditto
370         static Vector3 unitZ = { 0, 0, 1 };  /// ditto
371        
372         /**
373         Method to construct vector in C-like syntax.
374
375         Examples:
376         ------------
377         Vector3 myVector = Vector3(1, 2, 3);
378         ------------
379         */
380         static Vector3 opCall(float_t x, float_t y, float_t z)
381         {
382             Vector3 v;
383             v.set(x, y, z);
384             return v;
385         }
386        
387         /** Sets values of components to passed values. */
388         void set(float_t x, float_t y, float_t z)
389         {
390             this.x = x;
391             this.y = y;
392             this.z = z;
393         }
394    
395         /** Returns: Norm (also known as length, magnitude) of vector. */
396         real norm()
397         {
398             return sqrt(x*x + y*y + z*z);
399         }
400    
401         /**
402         Returns: Square of vector's norm.
403         
404         Since this method doesn't need calculation of square root it is better
405         to use it instead of norm() when you can. For example, if you want just
406         to know which of 2 vectors is longer it's better to compare their norm
407         squares instead of their norm.
408         */
409         real normSquare()
410         {
411             return x*x + y*y + z*z;
412         }
413    
414         /** Normalizes this vector. */
415         void normalize()
416         {
417             *this /= norm;
418         }
419    
420         /** Returns: Normalized copy of this vector. */
421         Vector3 normalized()
422         {
423             real n = norm;
424             return Vector3(x / n, y / n, z / n);
425         }
426    
427         /**
428         Returns: Whether this vector is unit.
429         Params:
430             relprec, absprec = Parameters passed to equal function while comparison of
431                                norm square and 1. Have the same meaning as in equal function.
432         */
433         bool isUnit(int relprec = defrelprec, int absprec = defabsprec)
434         {
435             return equal( normSquare(), 1, relprec, absprec );
436         }
437    
438         /** Returns: Axis for which projection of this vector on it will be longest. */
439         Ort dominatingAxis()
440         {
441             if (x > y)
442                 return (x > z) ? Ort.X : Ort.Z;
443             else
444                 return (y > z) ? Ort.Y : Ort.Z;
445         }
446    
447         /** Returns: Whether all components are normalized numbers. */
448         bool isnormal()
449         {
450             return std.math.isnormal(x) && std.math.isnormal(y) && std.math.isnormal(z);
451         }
452    
453         /** Returns: float_t pointer to x component of this vector. It's like a _ptr method for arrays. */
454         float_t* ptr()
455         {
456             return cast(float_t*)this;
457         }
458    
459         /** Returns: Component corresponded to passed index. */
460         float_t opIndex(Ort ort)
461         in { assert(ort <= Ort.Z); }
462         body
463         {
464             return ptr[cast(int)ort];
465         }
466    
467         /** Assigns new _value to component corresponded to passed index. */
468         void opIndexAssign(float_t value, Ort ort)
469         in { assert(ort <= Ort.Z); }
470         body
471         {
472             ptr[cast(int)ort] = value;
473         }
474    
475         /**
476         Standard operators that have intuitive meaning, same as in classical math.
477         
478         Note that division operators do no cheks of value of k, so in case of division
479         by 0 result vector will have infinity components. You can check this with isnormal()
480         method.
481         */
482         bool opEquals(Vector3 v)
483         {
484             return x == v.x && y == v.y && z == v.z;
485         }
486    
487         /** ditto */
488         Vector3 opNeg()
489         {
490             return Vector3(-x, -y, -z);
491         }
492    
493         /** ditto */
494         Vector3 opAdd(Vector3 v)
495         {
496             return Vector3(x + v.x, y + v.y, z + v.z);
497         }
498    
499         /** ditto */
500         void opAddAssign(Vector3 v)
501         {
502             x += v.x;
503             y += v.y;
504             z += v.z;
505         }
506    
507         /** ditto */
508         Vector3 opSub(Vector3 v)
509         {
510             return Vector3(x - v.x, y - v.y, z - v.z);
511         }
512    
513         /** ditto */
514         void opSubAssign(Vector3 v)
515         {
516             x -= v.x;
517             y -= v.y;
518             z -= v.z;
519         }
520    
521         /** ditto */
522         Vector3 opMul(real k)
523         {
524             return Vector3(x * k, y * k, z * k);
525         }
526    
527         /** ditto */
528         void opMulAssign(real k)
529         {
530             x *= k;
531             y *= k;
532             z *= k;
533         }
534    
535         /** ditto */
536         Vector3 opMul_r(real k)
537         {
538             return Vector3(x * k, y * k, z * k);
539         }
540    
541         /** ditto */
542         Vector3 opDiv(real k)
543         {
544             return Vector3(x / k, y / k, z / k);
545         }
546    
547         /** ditto */
548         void opDivAssign(real k)
549         {
550             x /= k;
551             y /= k;
552             z /= k;
553         }
554        
555         /** Returns: Copy of this vector with float type components */
556         Vector3f toVector3f()
557         {
558             return Vector3f(cast(float)x, cast(float)y, cast(float)z);
559         }
560        
561         /** Returns: Copy of this vector with double type components */
562         Vector3d toVector3d()
563         {
564             return Vector3d(cast(double)x, cast(double)y, cast(double)z);
565         }
566
567         /** Returns: Copy of this vector with real type components */
568         Vector3r toVector3r()
569         {
570             return Vector3r(cast(real)x, cast(real)y, cast(real)z);
571         }
572
573    
574         /**
575         Routines known as swizzling.
576         Returns:
577             New vector constructed from this one and having component values
578             that correspond to method name.
579         */
580         Vector4 xyz0()        { return Vector4(x,y,z,0); }
581         Vector4 xyz1()        { return Vector4(x,y,z,1); } /// ditto
582         Vector2 xy()          { return Vector2(x, y); }    /// ditto
583         Vector2 xz()          { return Vector2(x, z); }    /// ditto
584        
585         /**
586         Routines known as swizzling.
587         Assigns new values to some components corresponding to method name.
588         */
589         void xy(Vector2 v)    { x = v.x; y = v.y; }
590         void xz(Vector2 v)    { x = v.x; z = v.y; }        /// ditto
591     }
592    
593     /** Returns: Dot product between passed vectors. */
594     real dp(Vector3 a, Vector3 b)
595     {
596         return a.x * b.x + a.y * b.y + a.z * b.z;
597     }
598    
599     /**
600     Returns: Cross product between passed vectors. Result is vector c
601     so that a, b, c forms right-hand tripple.
602     */
603     Vector3 cp(Vector3 a, Vector3 b)
604     {
605         return Vector3(
606             a.y * b.z - b.y * a.z,
607             a.z * b.x - b.z * a.x,
608             a.x * b.y - b.x * a.y  );
609     }
610    
611     /**
612     Returns: Whether passed basis is orthogonal.
613     Params:
614         r, s, t =          Vectors that form a basis.
615         relprec, absprec = Parameters passed to equal function while calculations.
616                            Have the same meaning as in equal function.
617     References:
618         $(LINK http://en.wikipedia.org/wiki/Orthogonal_basis)
619     */
620     bool isBasisOrthogonal(Vector3 r, Vector3 s, Vector3 t, int relprec = defrelprec, int absprec = defabsprec)
621     {
622         return equal( cp(r, cp(s, t)).normSquare, 0, relprec, absprec );
623     }
624    
625     /**
626     Returns: Whether passed basis is orthonormal.
627     Params:
628         r, s, t =   Vectors that form a basis.
629         relprec, absprec = Parameters passed to equal function while calculations.
630                            Have the same meaning as in equal function.
631     References:
632         $(LINK http://en.wikipedia.org/wiki/Orthonormal_basis)
633     */
634     bool isBasisOrthonormal(Vector3 r, Vector3 s, Vector3 t, int relprec = defrelprec, int absprec = defabsprec)
635     {
636         return isBasisOrthogonal(r, s, t, relprec, absprec) &&
637             r.isUnit(relprec, absprec) &&
638             s.isUnit(relprec, absprec) &&
639             t.isUnit(relprec, absprec);
640     }
641    
642     alias EqualityByNorm!(Vector3).equal equal; /// Introduces approximate equality function for Vector3.
643     alias Lerp!(Vector3).lerp lerp;             /// Introduces linear interpolation function for Vector3.
644    
645    
646     /************************************************************************************
647     4D vector.
648
649     For formal definition of vector, meaning of possible operations and related
650     information see $(LINK http://en.wikipedia.org/wiki/Vector_(spatial)),
651     $(LINK http://en.wikipedia.org/wiki/Homogeneous_coordinates).
652     *************************************************************************************/
653     struct Vector4
654     {
655         align(1)
656         {
657             float_t x; /// Components of vector.
658             float_t y; /// ditto
659             float_t z; /// ditto
660             float_t w; /// ditto
661         }
662        
663         /// Vector with all components seted to NaN.
664         static Vector4 nan = { float_t.nan, float_t.nan, float_t.nan, float_t.nan };
665         static Vector4 unitX = { 1, 0, 0, 0 }; /// Unit vector codirectional with corresponding axis.
666         static Vector4 unitY = { 0, 1, 0, 0 }; /// ditto
667         static Vector4 unitZ = { 0, 0, 1, 0 }; /// ditto
668         static Vector4 unitW = { 0, 0, 0, 1 }; /// ditto
669        
670         /**
671         Methods to construct vector in C-like syntax.
672
673         Examples:
674         ------------
675         Vector4 myVector = Vector4(1, 2, 3, 1);
676         Vector4 myVector = Vector4(Vector3(1, 2, 3), 0);
677         ------------
678         */
679         static Vector4 opCall(float_t x, float_t y, float_t z, float_t w)
680         {
681             Vector4 v;
682             v.set(x, y, z, w);
683             return v;
684         }
685        
686         /** ditto */
687         static Vector4 opCall(Vector3 xyz, float_t w)
688         {
689             Vector4 v;
690             v.set(xyz, w);
691             return v;
692         }
693    
694         /** Sets values of components to passed values. */
695         void set(float_t x, float_t y, float_t z, float_t w)
696         {
697             this.x = x;
698             this.y = y;
699             this.z = z;
700             this.w = w;
701         }
702    
703         /** ditto */
704         void set(Vector3 xyz, float_t w)
705         {
706             this.x = xyz.x;
707             this.y = xyz.y;
708             this.z = xyz.z;
709             this.w = w;
710         }
711    
712         /**
713         Returns: Norm (also known as length, magnitude) of vector.
714         
715         W-component is taken into account.
716         */
717         real norm()
718         {
719             return sqrt(x*x + y*y + z*z + w*w);
720         }
721    
722         /**
723         Returns: Square of vector's norm.
724
725         W-component is taken into account.
726         
727         Since this method doesn't need calculation of square root it is better
728         to use it instead of norm() when you can. For example, if you want just
729         to know which of 2 vectors is longer it's better to compare their norm
730         squares instead of their norm.
731         */
732         real normSquare()
733         {
734             return x*x + y*y + z*z + w*w;
735         }
736    
737         /** Normalizes this vector. */
738         void normalize()
739         {
740             *this /= norm;
741         }
742    
743         /** Returns: Normalized copy of this vector. */
744         Vector4 normalized()
745         {
746             real n = norm;
747             return Vector4(x / n, y / n, z / n, w / n);
748         }
749    
750         /**
751         Returns: Whether this vector is unit.
752         Params:
753             relprec, absprec = Parameters passed to equal function while comparison of
754                                norm square and 1. Have the same meaning as in equal function.
755         */
756         bool isUnit(int relprec = defrelprec, int absprec = defabsprec)
757         {
758             return equal( normSquare, 1, relprec, absprec );
759         }
760    
761         /**
762         Returns: Axis for which projection of this vector on it will be longest.
763         
764         W-component is taken into account.
765         */
766         Ort dominatingAxis()
767         {
768             if (x > y)
769             {
770                 if (x > z)
771                     return (x > w) ? Ort.X : Ort.W;
772                 else
773                     return (z > w) ? Ort.Z : Ort.W;
774             }
775             else
776             {
777                 if (y > z)
778                     return (y > w) ? Ort.Y : Ort.W;
779                 else
780                     return (z > w) ? Ort.Z : Ort.W;
781             }
782         }
783    
784         /** Returns: Whether all components are normalized numbers. */
785         bool isnormal()
786         {
787             return std.math.isnormal(x) && std.math.isnormal(y) && std.math.isnormal(z) && std.math.isnormal(w);
788         }
789    
790         /** Returns: float_t pointer to x component of this vector. It's like a _ptr method for arrays. */
791         float_t* ptr()
792         {
793             return cast(float_t*)this;
794         }
795        
796         /** Returns: Component corresponded to passed index. */
797         float_t opIndex(Ort ort)
798         in { assert(ort <= Ort.W); }
799         body
800         {
801             return ptr[cast(int)ort];
802         }
803    
804         /** Assigns new value to component corresponded to passed index. */
805         void opIndexAssign(float_t value, Ort ort)
806         in { assert(ort <= Ort.W); }
807         body
808         {
809             ptr[cast(int)ort] = value;
810         }
811    
812         /**
813         Standard operators that have intuitive meaning, same as in classical math.
814         
815         Note that division operators do no cheks of value of k, so in case of division
816         by 0 result vector will have infinity components. You can check this with isnormal()
817         method.
818         */
819         bool opEquals(Vector4 v)
820         {
821             return x == v.x && y == v.y && z == v.z && w == v.w;
822         }
823    
824         /** ditto */
825         Vector4 opNeg()
826         {
827             return Vector4(-x, -y, -z, -w);
828         }
829    
830         /** ditto */
831         Vector4 opAdd(Vector4 v)
832         {
833             return Vector4(x + v.x, y + v.y, z + v.z, w + v.w);
834         }
835    
836         /** ditto */
837         void opAddAssign(Vector4 v)
838         {
839             x += v.x;
840             y += v.y;
841             z += v.z;
842             w += v.w;
843         }
844    
845         /** ditto */
846         Vector4 opSub(Vector4 v)
847         {
848             return Vector4(x - v.x, y - v.y, z - v.z, w - v.w);
849         }
850    
851         /** ditto */
852         void opSubAssign(Vector4 v)
853         {
854             x -= v.x;
855             y -= v.y;
856             z -= v.z;
857             w -= v.w;
858         }
859    
860         /** ditto */
861         Vector4 opMul(real k)
862         {
863             return Vector4(x * k, y * k, z * k, w * k);
864         }
865    
866         /** ditto */
867         void opMulAssign(real k)
868         {
869             x *= k;
870             y *= k;
871             z *= k;
872             w *= k;
873         }
874    
875         /** ditto */
876         Vector4 opMul_r(real k)
877         {
878             return Vector4(x * k, y * k, z * k, w * k);
879         }
880    
881         /** ditto */
882         Vector4 opDiv(real k)
883         {
884             return Vector4(x / k, y / k, z / k, w / k);
885         }
886    
887         /** ditto */
888         void opDivAssign(real k)
889         {
890             x /= k;
891             y /= k;
892             z /= k;
893             w /= k;
894         }
895    
896         /** Returns: Copy of this vector with float type components */
897         Vector4f toVector4f()
898         {
899             return Vector4f(cast(float)x, cast(float)y, cast(float)z, cast(float)w);
900         }
901        
902         /** Returns: Copy of this vector with double type components */
903         Vector4d toVector4d()
904         {
905             return Vector4d(cast(double)x, cast(double)y, cast(double)z, cast(double)w);
906         }
907        
908         /** Returns: Copy of this vector with real type components */
909         Vector4r toVector4r()
910         {
911             return Vector4r(cast(real)x, cast(real)y, cast(real)z, cast(real)w);
912         }
913    
914         /**
915         Routine known as swizzling.
916         Returns:
917             Vector3 that has the same x, y, z components values.
918         */
919         Vector3 xyz()   { return Vector3(x,y,z); }   
920        
921         /**
922         Routine known as swizzling.
923         Assigns new values to x, y, z components corresponding to argument's components values.
924         */
925         void xyz(Vector3 v)    { x = v.x; y = v.y; z = v.z; }       
926     }
927    
928     /** Returns: Dot product between passed vectors. */
929     real dp(Vector4 a, Vector4 b)
930     {
931         return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
932     }
933    
934     alias EqualityByNorm!(Vector4).equal equal; /// Introduces approximate equality function for Vector4.
935     alias Lerp!(Vector4).lerp lerp;             /// Introduces linear interpolation function for Vector4.
936    
937    
938     /************************************************************************************
939     _Quaternion.
940
941     For formal definition of quaternion, meaning of possible operations and related
942     information see $(LINK http://en.wikipedia.org/wiki/_Quaternion),
943     $(LINK http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation).
944     *************************************************************************************/
945     struct Quaternion
946     {
947         align(1)
948         {
949             union
950             {
951                 struct
952                 {
953                     float_t x; /// Components of quaternion.
954                     float_t y; /// ditto
955                     float_t z; /// ditto
956                 }
957                
958                 Vector3 vector; /// Vector part. Can be used instead of explicit members x, y and z.
959             }
960    
961             union
962             {
963                 float_t w;      /// Scalar part.
964                 float_t scalar; /// Another name for _scalar part.
965             }
966         }
967        
968         /// Identity quaternion.
969         static Quaternion identity;
970         /// Quaternion with all components seted to NaN.
971         static Quaternion nan = { x: float_t.nan, y: float_t.nan, z: float_t.nan, w: float_t.nan };
972    
973         /**
974         Methods to construct quaternion in C-like syntax.
975
976         Examples:
977         ------------
978         Quaternion q1 = Quaternion(0, 0, 0, 1);
979         Quaternion q2 = Quaternion(Vector3(0, 0, 0), 1);
980         Quaternion q3 = Quaternion(Matrix33.rotationY(PI / 6), 1);
981         ------------
982         */
983         static Quaternion opCall(float_t x, float_t y, float_t z, float_t w)
984         {
985             Quaternion q;
986             q.set(x, y, z, w);
987             return q;
988         }
989    
990         /** ditto */
991         static Quaternion opCall(Vector3 vector, float_t scalar)
992         {
993             Quaternion q;
994             q.set(vector, scalar);
995             return q;
996         }
997        
998         /** ditto */
999         static Quaternion opCall(Matrix33 mat)
1000         {
1001             Quaternion q;
1002             q.set(mat);
1003             return q;
1004         }
1005        
1006         /** Sets values of components according to passed values. */
1007         void set(float_t x, float_t y, float_t z, float_t w)
1008         {
1009             this.x = x;
1010             this.y = y;
1011             this.z = z;
1012             this.w = w;
1013         }
1014    
1015         /** ditto */
1016         void set(Vector3 vector, float_t scalar)
1017         {
1018             this.vector = vector;
1019             this.scalar = scalar;
1020         }
1021        
1022         /**
1023         Sets quaternion, so that, it will represent same rotation as in mat matrix argument.
1024         Params:
1025             mat = Matrix to extract rotation from. Should be pure rotation matrix.
1026         Throws:
1027             AssertError if mat is not pure rotation matrix and module was compiled with
1028             contract checkings are enabled.
1029         */
1030         // NOTE: refactor to use mat.ptr instead of [] operator if
1031         // perforance will be unsatisfactory.
1032         void set(Matrix33 mat)
1033         in { assert(mat.isRotation()); }
1034         body
1035         {
1036             // Algorithm stolen from OGRE (http://ogre.sourceforge.net)
1037             real trace = mat[0, 0] + mat[1, 1] + mat[2, 2];
1038             real root;
1039        
1040             if ( trace > 0 )
1041             {
1042                 // |w| > 1/2, may as well choose w > 1/2
1043                 root = sqrt(trace + 1);  // 2w
1044                 w = 0.5 * root;
1045                 root = 0.5 / root;  // 1/(4w)
1046                 x = (mat[2, 1] - mat[1, 2]) * root;
1047                 y = (mat[0, 2] - mat[2, 0]) * root;
1048                 z = (mat[1, 0] - mat[0, 1]) * root;
1049             }
1050             else
1051             {
1052                 // |w| <= 1/2
1053                 static int[3] next = [ 1, 2, 0 ];
1054                 int i = 0;
1055                 if ( mat[1, 1] > mat[0, 0] )
1056                     i = 1;
1057                 if ( mat[2, 2] > mat[i, i] )
1058                     i = 2;
1059                 int j = next[i];
1060                 int k = next[j];
1061                
1062                 root = sqrt(mat[i, i] - mat[j, j] - mat[k, k] + 1);
1063                 *(&x + i) = 0.5 * root;
1064                 root = 0.5 / root;
1065                 w = (mat[j, k] - mat[k, j]) * root;
1066                 *(&x + j) = (mat[i, j] + mat[j, i]) * root;
1067                 *(&x + k) = (mat[i, k] + mat[k, i]) * root;
1068             }
1069         }
1070        
1071         /** Construct quaternion that represents rotation around corresponding axis. */
1072         static Quaternion rotationX(float_t radians)
1073         {
1074             Quaternion q;
1075            
1076             float_t s = sin(radians * 0.5f);
1077             float_t c = cos(radians * 0.5f);
1078             q.x = s;
1079             q.y = 0;
1080             q.z = 0;
1081             q.w = c;
1082            
1083             return q;
1084         }
1085    
1086         /** ditto */
1087         static Quaternion rotationY(float_t radians)
1088         {
1089             Quaternion q;
1090            
1091             float_t s = sin(radians * 0.5f);
1092             float_t c = cos(radians * 0.5f);
1093             q.x = 0;
1094             q.y = s;
1095             q.z = 0;
1096             q.w = c;
1097            
1098             return q;
1099         }
1100    
1101         /** ditto */
1102         static Quaternion rotationZ(float_t radians)
1103         {
1104             Quaternion q;
1105            
1106             float_t s = sin(radians * 0.5f);
1107             float_t c = cos(radians * 0.5f);
1108             q.x = 0;
1109             q.y = 0;
1110             q.z = s;
1111             q.w = c;
1112            
1113             return q;
1114         }
1115    
1116         /**
1117         Constructs quaternion that represents _rotation specified by euler angles passed as arguments.
1118         Order of _rotation application is: roll (Z axis), pitch (X axis), yaw (Y axis).
1119         */
1120         static Quaternion rotation(float_t yaw, float_t pitch, float_t roll)
1121         {
1122             return Quaternion.rotationY(yaw) * Quaternion.rotationX(pitch) * Quaternion.rotationZ(roll);
1123         }
1124    
1125         /**
1126         Constructs quaternion that represents _rotation around 'axis' _axis by 'radians' angle.
1127         */
1128         static Quaternion rotation(Vector3 axis, float_t radians)
1129         {
1130             Quaternion q;
1131            
1132             float_t s = sin(radians * 0.5f);
1133             float_t c = cos(radians * 0.5f);
1134             q.x = axis.x * s;
1135             q.y = axis.y * s;
1136             q.z = axis.z * s;
1137             q.w = c;
1138            
1139             return q;
1140         }
1141    
1142         /** Returns: Norm (also known as length, magnitude) of quaternion. */
1143         real norm()
1144         {
1145             return sqrt(x*x + y*y + z*z + w*w);
1146         }
1147    
1148         /**
1149         Returns: Square of vector's norm.
1150         
1151         Method doesn't need calculation of square root.
1152         */
1153         real normSquare()
1154         {
1155             return x*x + y*y + z*z + w*w;
1156         }
1157    
1158         /** Normalizes this quaternion. */
1159         void normalize()
1160         {
1161             float_t n = norm();
1162             assert( greater(n, 0) );
1163             *this /= n;
1164         }
1165    
1166         /** Returns: Normalized copy of this quaternion. */
1167         Quaternion normalized()
1168         {
1169             float_t n = norm();
1170             assert( greater(n, 0) );
1171             return Quaternion(x / n, y / n, z / n, w / n);
1172         }
1173    
1174         /**
1175         Returns: Whether this quaternion is unit.
1176         Params:
1177             relprec, absprec = Parameters passed to equal function while comparison of
1178                                norm square and 1. Have the same meaning as in equal function.
1179         */
1180         bool isUnit(int relprec = defrelprec, int absprec = defabsprec)
1181         {
1182             return equal( normSquare(), 1, relprec, absprec );
1183         }
1184    
1185         /** Returns: Conjugate quaternion. */
1186         Quaternion conj()
1187         {
1188             return Quaternion(-vector, scalar);
1189         }
1190    
1191         /** Invert this quaternion. */
1192         void invert()
1193         {
1194             float_t n = norm();
1195             assert( greater(n, 0) );
1196             vector = -vector / n;
1197             scalar =  scalar / n;
1198         }
1199    
1200         /** Returns: Inverse copy of this quaternion. */
1201         Quaternion inverse()
1202         {
1203             float_t n = norm();
1204             assert( greater(n, 0) );
1205             return conj / n;
1206         }
1207        
1208         /**
1209         Returns: Extracted euler angle with the assumption that rotation is applied in order:
1210         _roll (Z axis), _pitch (X axis), _yaw (Y axis).
1211         */
1212         real yaw()
1213         {
1214             return atan2(2 * (w*y + x*z), w*w - x*x - y*y + z*z);
1215         }
1216    
1217         /** ditto */
1218         real pitch()
1219         {
1220             return asin(2 * (w*x - y*z));
1221         }
1222        
1223         /** ditto */
1224         real roll()
1225         {
1226             return atan2(2 * (w*z + x*y), w*w - x*x + y*y - z*z);
1227         }
1228        
1229         /** Returns: Whether all components are normalized. */
1230         bool isnormal()
1231         {
1232             return std.math.isnormal(x) && std.math.isnormal(y) && std.math.isnormal(z) && std.math.isnormal(w);
1233         }
1234    
1235         /** Returns: float_t pointer to x component of this vector. It's like a _ptr method for arrays. */
1236         float_t* ptr()
1237         {
1238             return cast(float_t*)this;
1239         }
1240    
1241         /** Returns: Component corresponded to passed index. */
1242         float_t opIndex(Ort ort)
1243         in { assert(ort <= Ort.W); }
1244         body
1245         {
1246             return (cast(float_t*)this)[cast(int)ort];
1247         }
1248    
1249         /** Assigns new _value to component corresponded to passed index. */
1250         void opIndexAssign(float_t value, Ort ort)
1251         in { assert(ort <= Ort.W); }
1252         body
1253         {
1254             (cast(float_t*)this)[cast(int)ort] = value;
1255         }
1256    
1257         /**
1258         Standard operators that have meaning exactly the same as for Vector4.
1259         
1260         Note that division operators do no cheks of value of k, so in case of division
1261         by 0 result vector will have infinity components. You can check this with isnormal()
1262         method.
1263         */
1264         bool opEquals(Quaternion q)
1265         {
1266             return x == q.x && y == q.y && z == q.z && w == q.w;
1267         }
1268    
1269         /** ditto */
1270         Quaternion opNeg()
1271         {
1272             return Quaternion(-x, -y, -z, -w);
1273         }
1274    
1275         /** ditto */
1276         Quaternion opAdd(Quaternion q)
1277         {
1278             return Quaternion(x + q.x, y + q.y, z + q.z, w + q.w);
1279         }
1280    
1281         /** ditto */
1282         void opAddAssign(Quaternion q)
1283         {
1284             x += q.x;
1285             y += q.y;
1286             z += q.z;
1287             w += q.w;
1288         }
1289    
1290         /** ditto */
1291         Quaternion opSub(Quaternion q)
1292         {
1293             return Quaternion(x - q.x, y - q.y, z - q.z, w - q.w);
1294         }
1295    
1296         /** ditto */
1297         void opSubAssign(Quaternion q)
1298         {
1299             x -= q.x;
1300             y -= q.y;
1301             z -= q.z;
1302             w -= q.w;
1303         }
1304    
1305         /** ditto */
1306         Quaternion opMul(float_t k)
1307         {
1308             return Quaternion(x * k, y * k, z * k, w * k);
1309         }
1310
1311         /** ditto */
1312         Quaternion opMul_r(float_t k)
1313         {
1314             return Quaternion(x * k, y * k, z * k, w * k);
1315         }
1316    
1317         /** ditto */
1318         Quaternion opDiv(float_t k)
1319         {
1320             return Quaternion(x / k, y / k, z / k, w / k);
1321         }
1322    
1323         /** ditto */
1324         void opDivAssign(float_t k)
1325         {
1326             x /= k;
1327             y /= k;
1328             z /= k;
1329             w /= k;
1330         }
1331    
1332         /**
1333         Quaternion multiplication operators. Result of Q1*Q2 is quaternion that represents
1334         rotation which has meaning of application Q2's rotation and the Q1's rotation.
1335         */
1336         Quaternion opMul(Quaternion q)
1337         {
1338             return Quaternion(
1339                 w * q.x + x * q.w + y * q.z - z * q.y,
1340                 w * q.y + y * q.w + z * q.x - x * q.z,
1341                 w * q.z + z * q.w + x * q.y - y * q.x,
1342                 w * q.w - x * q.x - y * q.y - z * q.z );
1343         }
1344        
1345         /** ditto */
1346         void opMulAssign(Quaternion q)
1347         {
1348             set(w * q.x + x * q.w + y * q.z - z * q.y,
1349                 w * q.y + y * q.w + z * q.x - x * q.z,
1350                 w * q.z + z * q.w + x * q.y - y * q.x,
1351                 w * q.w - x * q.x - y * q.y - z * q.z );
1352         }
1353    
1354         /** Returns: Copy of this quaternion with float type components. */
1355         Quaternionf toQuaternionf()
1356         {
1357             return Quaternionf(cast(float)x, cast(float)y, cast(float)z, cast(float)w);
1358         }
1359        
1360         /** Returns: Copy of this vector with double type components. */
1361         Quaterniond toQuaterniond()
1362         {
1363             return Quaterniond(cast(double)x, cast(double)y, cast(double)z, cast(double)w);
1364         }
1365        
1366         /** Returns: Copy of this vector with real type components. */
1367         Quaternionr toQuaternionr()
1368         {
1369             return Quaternionr(cast(real)x, cast(real)y, cast(real)z, cast(real)w);
1370         }
1371     }   
1372    
1373     alias EqualityByNorm!(Quaternion).equal equal;  /// Introduces approximate equality function for Quaternion.
1374     alias Lerp!(Quaternion).lerp lerp;              /// Introduces linear interpolation function for Quaternion.
1375    
1376     /**
1377     Returns:
1378         Product of spherical linear interpolation between q0 and q1 with parameter t.
1379     References:
1380         $(LINK http://en.wikipedia.org/wiki/Slerp).
1381     */
1382     Quaternion slerp(Quaternion q0, Quaternion q1, real t)
1383     {
1384         real cosTheta = q0.x * q1.x + q0.y * q1.y + q0.z * q1.z + q0.w * q1.w;
1385         real theta = acos(cosTheta);
1386    
1387         if ( equal(fabs(theta), 0) )
1388             return lerp(q0, q1, t);
1389    
1390         real sinTheta = sin(theta);
1391         real coeff0 = sin((1 - t) * theta) / sinTheta;
1392         real coeff1 = sin(t * theta) / sinTheta;
1393        
1394         // Invert rotation if necessary
1395         if (cosTheta < 0.0f)
1396         {
1397             coeff0 = -coeff0;
1398             // taking the complement requires renormalisation
1399             Quaternion ret = coeff0 * q0 + coeff1 * q1;
1400             return ret.normalized();
1401         }
1402        
1403         return coeff0 * q0 + coeff1 * q1;   
1404     }
1405    
1406     /************************************************************************************
1407     3x3 Matrix.
1408
1409     For formal definition of quaternion, meaning of possible operations and related
1410     information see $(LINK http://en.wikipedia.org/wiki/Matrix(mathematics)),
1411     $(LINK http://en.wikipedia.org/wiki/Transformation_matrix).
1412     *************************************************************************************/
1413     struct Matrix33
1414     {
1415         private align(1) union
1416         {
1417             struct
1418             {
1419                 float_t m00, m10, m20;
1420                 float_t m01, m11, m21;
1421                 float_t m02, m12, m22;
1422             }
1423    
1424             float_t[3][3] m;
1425             Vector3[3]    v;
1426             float_t[9]    a;
1427         }
1428    
1429         /// Identity matrix.
1430         static Matrix33 identity = {
1431             1, 0, 0,
1432             0, 1, 0,
1433             0, 0, 1 };
1434         /// Matrix with all elements seted to NaN.
1435         static Matrix33 nan = {
1436             float_t.nan, float_t.nan, float_t.nan,
1437             float_t.nan, float_t.nan, float_t.nan,
1438             float_t.nan, float_t.nan, float_t.nan };
1439         /// Matrix with all elements seted to 0.
1440         static Matrix33 zero = {
1441             0, 0, 0,
1442             0, 0, 0,
1443             0, 0, 0 };
1444    
1445         /**
1446         Methods to construct matrix in C-like syntax.
1447
1448         In case with array remember about column-major matrix memory layout,
1449         note last line with assert in example.
1450
1451         Examples:
1452         ------------
1453         Matrix33 mat1 = Matrix33(1,2,3,4,5,6,7,8,9);
1454         static float[9] a = [1,2,3,4,5,6,7,8,9];
1455         Matrix33 mat2 = Matrix33(a);
1456
1457         assert(mat1 == mat2.transposed);
1458         ------------
1459         */
1460         static Matrix33 opCall(float_t m00, float_t m01, float_t m02,
1461                                float_t m10, float_t m11, float_t m12,
1462                                float_t m20, float_t m21, float_t m22)
1463         {
1464             Matrix33 mat;
1465             mat.m00 = m00;        mat.m01 = m01;        mat.m02 = m02;
1466             mat.m10 = m10;        mat.m11 = m11;        mat.m12 = m12;
1467             mat.m20 = m20;        mat.m21 = m21;        mat.m22 = m22;
1468             return mat;
1469         }
1470        
1471         /** ditto */
1472         static Matrix33 opCall(float_t[9] a)
1473         {
1474             Matrix33 mat;
1475             mat.a[0..9] = a[0..9].dup;
1476             return mat;
1477         }
1478        
1479         /**
1480         Method to construct matrix in C-like syntax. Sets columns to passed vector
1481         arguments.
1482         */
1483         static Matrix33 opCall(Vector3 basisX, Vector3 basisY, Vector3 basisZ)
1484         {
1485             Matrix33 mat;
1486             mat.v[0] = basisX;
1487             mat.v[1] = basisY;
1488             mat.v[2] = basisZ;
1489             return mat;
1490         }
1491    
1492         /** Sets elements to passed values. */
1493         void set(float_t m00, float_t m01, float_t m02,
1494                  float_t m10, float_t m11, float_t m12,
1495                  float_t m20, float_t m21, float_t m22)
1496         {
1497             this.m00 = m00;        this.m01 = m01;        this.m02 = m02;
1498             this.m10 = m10;        this.m11 = m11;        this.m12 = m12;
1499             this.m20 = m20;        this.m21 = m21;        this.m22 = m22;
1500         }
1501        
1502         /** Sets elements as _a copy of a contents. Remember about column-major matrix memory layout. */
1503         void set(float_t[9] a)
1504         {
1505             this.a[0..9] = a[0..9].dup;
1506         }
1507        
1508         /** Sets columns to passed basis vectors. */
1509         void set(Vector3 basisX, Vector3 basisY, Vector3 basisZ)
1510         {
1511             v[0] = basisX;
1512             v[1] = basisY;
1513             v[2] = basisZ;
1514         }
1515        
1516         /** Returns: Whether all components are normalized numbers. */
1517         bool isnormal()
1518         {
1519             return
1520                 std.math.isnormal(m00) && std.math.isnormal(m01) && std.math.isnormal(m02) &&
1521                 std.math.isnormal(m10) && std.math.isnormal(m11) && std.math.isnormal(m12) &&
1522                 std.math.isnormal(m20) && std.math.isnormal(m21) && std.math.isnormal(m22);
1523         }
1524        
1525         /**
1526         Returns: Whether this matrix is identity.
1527         Params:
1528             relprec, absprec = Parameters passed to equal function while calculations.
1529                                Have the same meaning as in equal function.
1530         */
1531         bool isIdentity(int relprec = defrelprec, int absprec = defabsprec)
1532         {
1533             return equal(*this, identity, relprec, absprec);
1534         }
1535        
1536         /**
1537         Returns: Whether this matrix is zero.
1538         Params:
1539             relprec, absprec = Parameters passed to equal function while calculations.
1540                                Have the same meaning as in equal function.
1541         */
1542         bool isZero(int relprec = defrelprec, int absprec = defabsprec)
1543         {
1544             return equal(normSquare(), 0, relprec, absprec);
1545         }
1546        
1547         /**
1548         Returns: Whether this matrix is orthogonal.
1549         Params:
1550             relprec, absprec = Parameters passed to equal function while calculations.
1551                                Have the same meaning as in equal function.
1552         References:
1553             $(LINK http://en.wikipedia.org/wiki/Orthogonal_matrix).
1554         */
1555         bool isOrthogonal(int relprec = defrelprec, int absprec = defabsprec)
1556         {
1557             return isBasisOrthonormal(v[0], v[1], v[2], relprec, absprec);
1558         }
1559        
1560         /**
1561         Returns: Whether this matrix represents pure rotation. I.e. hasn't scale admixture.
1562         Params:
1563             relprec, absprec = Parameters passed to equal function while calculations.
1564                                Have the same meaning as in equal function.
1565         */
1566         bool isRotation(int relprec = defrelprec, int absprec = defabsprec)
1567         {
1568             return isOrthogonal(relprec, absprec) && equal(v[2], cp(v[0], v[1]), relprec, absprec);
1569         }
1570    
1571         /** Constructs _scale matrix with _scale coefficients specified as arguments. */
1572         static Matrix33 scale(float_t x, float_t y, float_t z)
1573         {
1574             Matrix33 mat = identity;
1575             with (mat)
1576             {
1577                 m00 = x;
1578                 m11 = y;
1579                 m22 = z;
1580             }
1581    
1582             return mat;
1583         }
1584    
1585         /** Constructs _scale matrix with _scale coefficients specified as v's components. */
1586         static Matrix33 scale(Vector3 v)
1587         {
1588             return scale(v.x, v.y, v.z);
1589         }
1590    
1591         /** Construct matrix that represents rotation around corresponding axis. */
1592         static Matrix33 rotationX(float_t radians)
1593         {
1594             Matrix33 mat = identity;
1595             float_t c = cos(radians);
1596             float_t s = sin(radians);
1597             with (mat)
1598             {
1599                 m11 = m22 = c;
1600                 m21 = s;
1601                 m12 = -s;           
1602             }
1603    
1604             return mat;
1605         }
1606    
1607         /** ditto */
1608         static Matrix33 rotationY(float_t radians)
1609         {
1610             Matrix33 mat = identity;
1611             float_t c = cos(radians);
1612             float_t s = sin(radians);
1613             with (mat)
1614             {
1615                 m00 = m22 = c;
1616                 m20 = -s;
1617                 m02 = s;           
1618             }
1619    
1620             return mat;
1621         }
1622    
1623         /** ditto */
1624         static Matrix33 rotationZ(float_t radians)
1625         {
1626             Matrix33 mat = identity;
1627             float_t c = cos(radians);
1628             float_t s = sin(radians);
1629             with (mat)
1630             {
1631                 m00 = m11 = c;
1632                 m10 = s;
1633                 m01 = -s;           
1634             }
1635    
1636             return mat;
1637         }
1638    
1639         /**
1640         Constructs matrix that represents _rotation specified by euler angles passed as arguments.
1641         Order of _rotation application is: roll (Z axis), pitch (X axis), yaw (Y axis).
1642         */
1643         static Matrix33 rotation(float_t yaw, float_t pitch, float_t roll)
1644         {
1645             return Matrix33.rotationY(yaw) * Matrix33.rotationX(pitch) * Matrix33.rotationZ(roll);
1646         }
1647    
1648         /**
1649         Constructs matrix that represents _rotation specified by axis and angle.
1650         Method works with assumption that axis is unit vector.       
1651         Throws:
1652             AssertError on non-unit axis call attempt if module was compiled with
1653             contract checks enabled.
1654         */
1655         static Matrix33 rotation(Vector3 axis, float_t radians)
1656         in { assert( axis.isUnit() ); }
1657         body
1658         {
1659             real c = cos(radians);
1660             real s = sin(radians);
1661             real cc = 1.0 - c;
1662             real x2 = axis.x * axis.x;
1663             real y2 = axis.y * axis.y;
1664             real z2 = axis.z * axis.z;
1665             real xycc = axis.x * axis.y * cc;
1666             real xzcc = axis.x * axis.z * cc;
1667             real yzcc = axis.y * axis.z * cc;
1668             real xs = axis.x * s;
1669             real ys = axis.y * s;
1670             real zs = axis.z * s;
1671    
1672             Matrix33 mat;
1673             with (mat)
1674             {
1675                 m00 = x2 * cc + c;      m01 = xycc - zs;        m02 = xzcc + ys;
1676                 m10 = xycc + zs;        m11 = y2 * cc + c;      m12 = yzcc - xs;
1677                 m20 = xzcc - ys;        m21 = yzcc + xs;        m22 = z2 * cc + c;
1678             }
1679    
1680             return mat;
1681         }
1682        
1683         /**
1684         Constructs matrix that represents _rotation same as in passed quaternion q.
1685         Method works with assumption that q is unit.
1686         Throws:
1687             AssertError on non-unit quaternion call attempt if you compile with
1688             contract checks enabled.
1689         */
1690         static Matrix33 rotation(Quaternion q)
1691         in { assert( q.isUnit() ); }
1692         body
1693         {
1694             float_t tx  = 2.f * q.x;
1695             float_t ty  = 2.f * q.y;
1696             float_t tz  = 2.f * q.z;
1697             float_t twx = tx * q.w;
1698             float_t twy = ty * q.w;
1699             float_t twz = tz * q.w;
1700             float_t txx = tx * q.x;
1701             float_t txy = ty * q.x;
1702             float_t txz = tz * q.x;
1703             float_t tyy = ty * q.y;
1704             float_t tyz = tz * q.y;
1705             float_t tzz = tz * q.z;
1706            
1707             Matrix33 mat;
1708             with (mat)
1709             {
1710                 m00 = 1.f - (tyy + tzz);    m01 = txy + twz;            m02 = txz - twy;       
1711                 m10 = txy - twz;            m11 = 1.f - (txx + tzz);    m12 = tyz + twx;       
1712                 m20 = txz + twy;            m21 = tyz - twx;            m22 = 1.f - (txx + tyy);
1713             }
1714            
1715             return mat;
1716         }
1717        
1718         /**
1719         Returns: Inverse copy of this matrix.
1720         
1721         In case if this matrix is singular (i.e. determinant = 0) result matrix will has
1722         infinity elements. You can check this with isnormal() method.
1723         */
1724         Matrix33 inverse()
1725         {
1726             Matrix33 mat;
1727            
1728             mat.m00 = m11 * m22 - m12 * m21;
1729             mat.m01 = m02 * m21 - m01 * m22;
1730             mat.m02 = m01 * m12 - m02 * m11;
1731             mat.m10 = m12 * m20 - m10 * m22;
1732             mat.m11 = m00 * m22 - m02 * m20;
1733             mat.m12 = m02 * m10 - m00 * m12;
1734             mat.m20 = m10 * m21 - m11 * m20;
1735             mat.m21 = m01 * m20 - m00 * m21;
1736             mat.m22 = m00 * m11 - m01 * m10;
1737            
1738             real det = m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20;
1739            
1740             for (int i = 9; i--; )
1741                 mat.a[i] /= det;
1742    
1743             return mat;
1744         }
1745        
1746         /**
1747         Inverts this matrix.
1748         
1749         In case if matrix is singular (i.e. determinant = 0) result matrix will has
1750         infinity elements. You can check this with isnormal() method.
1751         */
1752         void invert()
1753         {
1754             *this = inverse();
1755         }
1756        
1757         /** Returns: Determinant */
1758         real determinant()
1759         {
1760             real cofactor00 = m11 * m22 - m12 * m21;
1761             real cofactor10 = m12 * m20 - m10 * m22;
1762             real cofactor20 = m10 * m21 - m11 * m20;
1763            
1764             return m00 * cofactor00 + m01 * cofactor10 + m02 * cofactor20;;
1765         }
1766        
1767         /**
1768         Returns: Frobenius _norm of matrix. I.e. square root from summ of all elements' squares.
1769         References:
1770             $(LINK http://en.wikipedia.org/wiki/Frobenius_norm#Frobenius_norm).
1771         */
1772         real norm()
1773         {
1774             return sqrt( normSquare );
1775         }
1776        
1777         /**
1778         Returns: Square of Frobenius _norm of matrix. I.e. summ of all elements' squares.
1779
1780         Method doesn't need calculation of square root.
1781
1782         References:
1783             $(LINK http://en.wikipedia.org/wiki/Frobenius_norm#Frobenius_norm).
1784         */
1785         real normSquare()
1786         {
1787             real ret = 0;
1788             for (int i = 9; i--; )
1789             {
1790                 real x = a[i];
1791                 ret += x * x;
1792             }
1793            
1794             return ret;
1795         }
1796        
1797         /** Transposes this matrix. */
1798         void transpose()
1799         {
1800             /*           */        swap(m01, m10);        swap(m02, m20);
1801             /*           */        /*           */        swap(m12, m21);
1802             /*           */        /*           */        /*           */
1803         }
1804        
1805         /** Returns: Transposed copy of this matrix. */
1806         Matrix33 transposed()
1807         {
1808             return Matrix33(
1809                 m00, m10, m20,
1810                 m01, m11, m21,
1811                 m02, m12, m22 );
1812         }
1813        
1814         /**
1815         Makes polar decomposition of this matrix. Denote this matrix with 'M', in
1816         that case M=Q*S.
1817         
1818         Method is useful to decompose your matrix into rotation 'Q' and scale+shear 'S'. If you
1819         didn't use shear transform matrix S will be diagonal, i.e. represent scale. This can
1820         have many applications, particulary you can use method for suppressing errors in pure
1821         rotation matrices after long multiplication chain.
1822         
1823         Params:
1824             Q = Output matrix, will be orthogonal after decomposition.
1825                 Argument shouldn't be null.
1826             S = Output matrix, will be symmetric non-negative definite after
1827                 decomposition. Argument shouldn't be null.
1828
1829         Examples:
1830         --------
1831         Matrix33 Q, S;
1832         Matrix33 rot = Matrix33.rotationZ(PI / 7);
1833         Matrix33 scale = Matrix33.scale(-1, 2, 3);
1834         Matrix33 composition = rot * scale;
1835         composition.polarDecomposition(Q, S);   
1836         assert( equal(Q * S, composition) );
1837         --------
1838
1839         References:
1840             $(LINK http://www.cs.wisc.edu/graphics/Courses/cs-838-2002/Papers/polar-decomp.pdf)
1841         */
1842         void polarDecomposition(out Matrix33 Q, out Matrix33 S)
1843         out { assert(Q.isRotation()); }
1844         body
1845         {
1846             // TODO: Optimize, we need only sign of determinant, not value
1847             if (determinant < 0)
1848                 Q = (*this) * (-identity);
1849             else
1850                 Q = *this;
1851                
1852             // use scaled Newton method to orthonormalize Q
1853             int maxIterations = 100; // avoid deadlock
1854             Matrix33 Qp = Q;
1855             Q = 0.5f * (Q + Q.transposed.inverse);
1856             while (!(Q - Qp).isZero && maxIterations--)
1857             {
1858                 Matrix33 Qinv = Q.inverse;
1859                 real gamma = sqrt( Qinv.norm / Q.norm );
1860                 Qp = Q;
1861                 Q = 0.5f * (gamma * Q + (1 / gamma) * Qinv.transposed);
1862             }
1863            
1864             assert( maxIterations != -1 );
1865            
1866             S = Q.transposed * (*this);
1867         }
1868    
1869         /**
1870         Standard operators that have intuitive meaning, same as in classical math.
1871         
1872         Note that division operators do no cheks of value of k, so in case of division
1873         by 0 result matrix will have infinity components. You can check this with isnormal()
1874         method.
1875         */
1876         Matrix33 opNeg()
1877         {
1878             return Matrix33(-m00, -m01, -m02,
1879                             -m10, -m11, -m12,
1880                             -m20, -m21, -m22);
1881         }
1882    
1883         /** ditto */
1884         Matrix33 opAdd(Matrix33 mat)
1885         {
1886             return Matrix33(m00 + mat.m00, m01 + mat.m01, m02 + mat.m02,
1887                             m10 + mat.m10, m11 + mat.m11, m12 + mat.m12,
1888                             m20 + mat.m20, m21 + mat.m21, m22 + mat.m22);
1889         }
1890    
1891         /** ditto */
1892         void opAddAssign(Matrix33 mat)
1893         {
1894             m00 += mat.m00; m01 += mat.m01; m02 += mat.m02;
1895             m10 += mat.m10; m11 += mat.m11; m12 += mat.m12;
1896             m20 += mat.m20; m21 += mat.m21; m22 += mat.m22;
1897         }
1898    
1899         /** ditto */
1900         Matrix33 opSub(Matrix33 mat)
1901         {
1902             return Matrix33(m00 - mat.m00, m01 - mat.m01, m02 - mat.m02,
1903                             m10 - mat.m10, m11 - mat.m11, m12 - mat.m12,
1904                             m20 - mat.m20, m21 - mat.m21, m22 - mat.m22);
1905         }
1906    
1907         /** ditto */
1908         void opSubAssign(Matrix33 mat)
1909         {
1910             m00 -= mat.m00; m01 -= mat.m01; m02 -= mat.m02;
1911             m10 -= mat.m10; m11 -= mat.m11; m12 -= mat.m12;
1912             m20 -= mat.m20; m21 -= mat.m21; m22 -= mat.m22;       
1913         }
1914    
1915         /** ditto */
1916         Matrix33 opMul(float_t k)
1917         {
1918             return Matrix33(m00 * k, m01 * k, m02 * k,
1919                             m10 * k, m11 * k, m12 * k,
1920                             m20 * k, m21 * k, m22 * k);
1921         }
1922    
1923         /** ditto */
1924         void opMulAssign(float_t k)
1925         {
1926             m00 *= k; m01 *= k; m02 *= k;
1927             m10 *= k; m11 *= k; m12 *= k;
1928             m20 *= k; m21 *= k; m22 *= k;
1929         }
1930    
1931         /** ditto */
1932         Matrix33 opMul_r(float_t k)
1933         {
1934             return Matrix33(m00 * k, m01 * k, m02 * k,
1935                             m10 * k, m11 * k, m12 * k,
1936                             m20 * k, m21 * k, m22 * k);
1937         }
1938    
1939         /** ditto */
1940         Matrix33 opDiv(float_t k)
1941         {
1942            
1943             return Matrix33(m00 / k, m01 / k, m02 / k,
1944                             m10 / k, m11 / k, m12 / k,
1945                             m20 / k, m21 / k, m22 / k);
1946         }
1947    
1948         /** ditto */
1949         void opDivAssign(float_t k)
1950         {
1951             m00 /= k; m01 /= k; m02 /= k;
1952             m10 /= k; m11 /= k; m12 /= k;
1953             m20 /= k; m21 /= k; m22 /= k;
1954         }
1955    
1956         /** ditto */
1957         bool opEquals(Matrix33 mat)
1958         {
1959             return m00 == mat.m00 && m01 == mat.m01 && m02 == mat.m02 &&
1960                    m10 == mat.m10 && m11 == mat.m11 && m12 == mat.m12 &&
1961                    m20 == mat.m20 && m21 == mat.m21 && m22 == mat.m22;
1962         }
1963
1964         /** ditto */
1965         Matrix33 opMul(Matrix33 mat)
1966         {
1967             return Matrix33(m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20,
1968                             m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21,
1969                             m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22,
1970                             m10 * mat.m00 + m11 * mat.m10 + m12 * mat.m20,
1971                             m10 * mat.m01 + m11 * mat.m11 + m12 * mat.m21,
1972                             m10 * mat.m02 + m11 * mat.m12 + m12 * mat.m22,
1973                             m20 * mat.m00 + m21 * mat.m10 + m22 * mat.m20,
1974                             m20 * mat.m01 + m21 * mat.m11 + m22 * mat.m21,
1975                             m20 * mat.m02 + m21 * mat.m12 + m22 * mat.m22 );
1976         }
1977    
1978         /** ditto */
1979         void opMulAssign(Matrix33 mat)
1980         {
1981             *this = *this * mat;
1982         }
1983    
1984         /** ditto */
1985         Vector3 opMul(Vector3 v)
1986         {
1987             return Vector3(v.x * m00 + v.y * m01 + v.z * m02,
1988                            v.x * m10 + v.y * m11 + v.z * m12,
1989                            v.x * m20 + v.y * m21 + v.z * m22 );
1990         }
1991    
1992         /** Returns: Element at row'th _row and col'th column. */
1993         float_t opIndex(uint row, uint col)
1994         in { assert( row < 3 && col < 3 ); }
1995         body
1996         {
1997             return m[col][row];
1998         }
1999    
2000         /** Assigns value f to element at row'th _row and col'th column. */
2001         void opIndexAssign(float_t f, uint row, uint col)
2002         in { assert( row < 3 && col < 3 ); }
2003         body
2004         {
2005             m[col][row] = f;
2006         }
2007        
2008         /** Returns: Vector representing col'th column. */
2009         Vector3 opIndex(uint col)
2010         in { assert( col < 3 ); }
2011         body
2012         {
2013             return v[col];
2014         }
2015        
2016         /** Replaces elements in col'th column with v's values. */
2017         void opIndexAssign(Vector3 v, uint col)
2018         in { assert( col < 3 ); }
2019         body
2020         {
2021             return this.v[col] = v;
2022         }
2023    
2024         /**
2025         Returns: float_t pointer to [0,0] element of this matrix. It's like a _ptr method for arrays.
2026         
2027         Remember about column-major matrix memory layout.
2028         */
2029         float_t* ptr()
2030         {
2031             return a.ptr;
2032         }
2033        
2034         /** Returns: Copy of this matrix with float type elements. */
2035         Matrix33f toMatrix33f()
2036         {
2037             return Matrix33f(
2038                 cast(float)m00, cast(float)m01, cast(float)m02,
2039                 cast(float)m10, cast(float)m11, cast(float)m12,
2040                 cast(float)m20, cast(float)m21, cast(float)m22 );
2041         }
2042        
2043         /** Returns: Copy of this matrix with double type elements. */
2044         Matrix33d toMatrix33d()
2045         {
2046             return Matrix33d(
2047                 cast(double)m00, cast(double)m01, cast(double)m02,
2048                 cast(double)m10, cast(double)m11, cast(double)m12,
2049                 cast(double)m20, cast(double)m21, cast(double)m22 );
2050         }
2051        
2052         /** Returns: Copy of this matrix with real type elements. */
2053         Matrix33r toMatrix33r()
2054         {
2055             return Matrix33r(
2056                 cast(real)m00, cast(real)m01, cast(real)m02,
2057                 cast(real)m10, cast(real)m11, cast(real)m12,
2058                 cast(real)m20, cast(real)m21, cast(real)m22 );
2059         }
2060     }
2061    
2062    
2063     alias EqualityByNorm!(Matrix33).equal equal; /// Introduces approximate equality function for Matrix33.
2064     alias Lerp!(Matrix33).lerp lerp;             /// Introduces linear interpolation function for Matrix33.
2065    
2066     /************************************************************************************
2067     4x4 Matrix.
2068
2069     Helix matrices uses column-major memory layout.
2070     *************************************************************************************/
2071     struct Matrix44
2072     {
2073         private align (1) union
2074         {
2075             struct
2076             {
2077                 float_t m00, m10, m20, m30;
2078                 float_t m01, m11, m21, m31;
2079                 float_t m02, m12, m22, m32;
2080                 float_t m03, m13, m23, m33;
2081             }
2082    
2083             float_t[4][4] m;
2084             float_t[16]   a;
2085             Vector4[4]    v;
2086         }
2087    
2088         /// Identity matrix.
2089         static Matrix44 identity = {
2090             1, 0, 0, 0,
2091             0, 1, 0, 0,
2092             0, 0, 1, 0,
2093             0, 0, 0, 1 };
2094         /// Matrix with all elements seted to NaN.
2095         static Matrix44 nan = {
2096             float_t.nan, float_t.nan, float_t.nan, float_t.nan,
2097             float_t.nan, float_t.nan, float_t.nan, float_t.nan,
2098             float_t.nan, float_t.nan, float_t.nan, float_t.nan,
2099             float_t.nan, float_t.nan, float_t.nan, float_t.nan };
2100         /// Matrix with all elements seted to 0.
2101         static Matrix44 zero = {
2102             0, 0, 0, 0,
2103             0, 0, 0, 0,
2104             0, 0, 0, 0,
2105             0, 0, 0, 0 };
2106    
2107         /**
2108         Methods to construct matrix in C-like syntax.
2109
2110         In case with array remember about column-major matrix memory layout,
2111         note last line with assert in example - it'll be passed.
2112
2113         Examples:
2114         ------------
2115         Matrix33 mat1 = Matrix33(
2116              1,  2,  3,  4,
2117              5,  6,  7,  8,
2118              9, 10, 11, 12,
2119             13, 14, 15, 16 );
2120             
2121         static float[16] a = [
2122              1,  2,  3,  4,
2123              5,  6,  7,  8,
2124              9, 10, 11, 12,
2125             13, 14, 15, 16 ];
2126         Matrix33 mat2 = Matrix33(a);
2127
2128         assert(mat1 == mat2.transposed);
2129         ------------
2130         */
2131         static Matrix44 opCall(float_t m00, float_t m01, float_t m02, float_t m03,
2132                                float_t m10, float_t m11, float_t m12, float_t m13,
2133                                float_t m20, float_t m21, float_t m22, float_t m23,
2134                                float_t m30, float_t m31, float_t m32, float_t m33)
2135         {
2136             Matrix44 mat;
2137             mat.m00 = m00;        mat.m01 = m01;        mat.m02 = m02;        mat.m03 = m03;
2138             mat.m10 = m10;        mat.m11 = m11;        mat.m12 = m12;        mat.m13 = m13;
2139             mat.m20 = m20;        mat.m21 = m21;        mat.m22 = m22;        mat.m23 = m23;
2140             mat.m30 = m30;        mat.m31 = m31;        mat.m32 = m32;        mat.m33 = m33;
2141             return mat;
2142         }
2143        
2144         /** ditto */
2145         static Matrix44 opCall(float_t[16] a)
2146         {
2147             Matrix44 mat;
2148             mat.a[0..16] = a[0..16].dup;
2149             return mat;
2150         }
2151        
2152         /**
2153         Method to construct matrix in C-like syntax. Sets columns to passed vector
2154         arguments.
2155         */
2156         static Matrix44 opCall(Vector4 basisX, Vector4 basisY, Vector4 basisZ,
2157                                Vector4 basisW = Vector4(0, 0, 0, 1))
2158         {
2159             Matrix44 mat;
2160             mat.v[0] = basisX;
2161             mat.v[1] = basisY;
2162             mat.v[2] = basisZ;
2163             mat.v[3] = basisW;
2164             return mat;
2165         }
2166        
2167         /**
2168         Method to construct matrix in C-like syntax. Constructs affine transform
2169         matrix based on passed vector arguments.
2170         References:
2171             $(LINK http://en.wikipedia.org/wiki/Affine_transformation).
2172         */
2173         static Matrix44 opCall(Vector3 basisX, Vector3 basisY, Vector3 basisZ,
2174                                Vector3 translation = Vector3(0, 0, 0))
2175         {
2176             return opCall(Vector4(basisX, 0), Vector4(basisX, 0), Vector4(basisX, 0), Vector4(translation, 1));
2177         }
2178    
2179         /** Sets elements to passed values. */
2180         void set(float_t m00, float_t m01, float_t m02, float_t m03,
2181                  float_t m10, float_t m11, float_t m12, float_t m13,
2182                  float_t m20, float_t m21, float_t m22, float_t m23,
2183                  float_t m30, float_t m31, float_t m32, float_t m33)
2184         {
2185             this.m00 = m00;        this.m01 = m01;        this.m02 = m02;        this.m03 = m03;
2186             this.m10 = m10;        this.m11 = m11;        this.m12 = m12;        this.m13 = m13;
2187             this.m20 = m20;        this.m21 = m21;        this.m22 = m22;        this.m23 = m23;
2188             this.m30 = m30;        this.m31 = m31;        this.m32 = m32;        this.m33 = m33;   
2189         }
2190        
2191         /** Sets elements as _a copy of a contents. Remember about column-major matrix memory layout. */
2192         void set(float_t[16] a)
2193         {
2194             this.a[0..16] = a[0..16].dup;
2195         }
2196    
2197         /** Sets columns to passed basis vectors. */
2198         void set(Vector4 basisX, Vector4 basisY, Vector4 basisZ,
2199                  Vector4 basisW = Vector4(0, 0, 0, 1))
2200         {
2201             v[0] = basisX;
2202             v[1] = basisY;
2203             v[2] = basisZ;
2204             v[3] = basisW;
2205         }
2206
2207         /** Returns: Whether all components are normalized numbers. */
2208         bool isnormal()
2209         {
2210             return
2211                 std.math.isnormal(m00) && std.math.isnormal(m01) && std.math.isnormal(m02) && std.math.isnormal(m03) &&
2212                 std.math.isnormal(m10) && std.math.isnormal(m11) && std.math.isnormal(m12) && std.math.isnormal(m13) &&
2213                 std.math.isnormal(m20) && std.math.isnormal(m21) && std.math.isnormal(m22) && std.math.isnormal(m23) &&
2214                 std.math.isnormal(m30) && std.math.isnormal(m31) && std.math.isnormal(m32) && std.math.isnormal(m33);
2215         }
2216
2217         /**
2218         Returns: Whether this matrix is identity.
2219         Params:
2220             relprec, absprec = Parameters passed to equal function while calculations.
2221                                Have the same meaning as in equal function.
2222         */
2223         bool isIdentity(int relprec = defrelprec, int absprec = defabsprec)
2224         {
2225             return equal(*this, identity, relprec, absprec);
2226         }
2227        
2228         /**
2229         Returns: Whether this matrix is zero.
2230         Params:
2231             relprec, absprec = Parameters passed to equal function while calculations.
2232                         Has the same meaning as in equal function.
2233         */
2234         bool isZero(int relprec = defrelprec, int absprec = defabsprec)
2235         {
2236             return equal(normSquare(), 0, relprec, absprec);
2237         }
2238        
2239         /**
2240         Resets this matrix to affine transform matrix based on passed
2241         vector arguments.
2242         */
2243         void set(Vector3 basisX, Vector3 basisY, Vector3 basisZ,
2244                  Vector3 translation = Vector3(0, 0, 0))
2245         {
2246             set(Vector4(basisX, 0), Vector4(basisX, 0), Vector4(basisX, 0), Vector4(translation, 1));
2247         }
2248    
2249         /** Constructs _scale matrix with _scale coefficients specified as arguments. */
2250         static Matrix44 scale(float_t x, float_t y, float_t z)
2251         {
2252             Matrix44 mat = identity;
2253             with (mat)
2254             {
2255                 m00 = x;
2256                 m11 = y;
2257                 m22 = z;           
2258             }
2259    
2260             return mat;
2261         }
2262    
2263         /** Constructs _scale matrix with _scale coefficients specified as v's components. */
2264         static Matrix44 scale(Vector3 v)
2265         {
2266             return scale(v.x, v.y, v.z);
2267         }
2268    
2269         /** Construct matrix that represents rotation around corresponding axis. */
2270         static Matrix44 rotationX(float_t radians)
2271         {
2272             Matrix44 mat = identity;
2273             float_t c = cos(radians);
2274             float_t s = sin(radians);
2275             with (mat)
2276             {
2277                 m11 = m22 = c;
2278                 m21 = s;
2279                 m12 = -s;           
2280             }
2281    
2282             return mat;
2283         }
2284    
2285         /** ditto */
2286         static Matrix44 rotationY(float_t radians)
2287         {
2288             Matrix44 mat = identity;
2289             float_t c = cos(radians);
2290             float_t s = sin(radians);
2291             with (mat)
2292             {
2293                 m00 = m22 = c;
2294                 m20 = -s;
2295                 m02 = s;           
2296             }
2297    
2298             return mat;
2299         }
2300    
2301         /** ditto */
2302         static Matrix44 rotationZ(float_t radians)
2303         {
2304             Matrix44 mat = identity;
2305             float_t c = cos(radians);
2306             float_t s = sin(radians);
2307             with (mat)
2308             {
2309                 m00 = m11 = c;
2310                 m10 = s;
2311                 m01 = -s;           
2312             }
2313    
2314             return mat;
2315         }
2316    
2317         /**
2318         Constructs matrix that represents _rotation specified by euler angles passed as arguments.
2319         Order of _rotation application is: roll (Z axis), pitch (X axis), yaw (Y axis).
2320         */
2321         static Matrix44 rotation(float_t yaw, float_t pitch, float_t roll)
2322         {
2323             return Matrix44.rotationY(yaw) * Matrix44.rotationX(pitch) * Matrix44.rotationZ(roll);
2324         }
2325    
2326         /**
2327         Constructs matrix that represents _rotation specified by axis and angle.
2328         Method works with assumption that axis is unit vector.       
2329         Throws:
2330             AssertError on non-unit axis call attempt if module was compiled with
2331             contract checks enabled.
2332         */
2333         static Matrix44 rotation(Vector3 axis, float_t radians)
2334         in { assert( axis.isUnit() ); }
2335         body
2336         {
2337             real c = cos(radians);
2338             real s = sin(radians);
2339             real cc = 1.0 - c;
2340             real x2 = axis.x * axis.x;
2341             real y2 = axis.y * axis.y;
2342             real z2 = axis.z * axis.z;
2343             real xycc = axis.x * axis.y * cc;
2344             real xzcc = axis.x * axis.z * cc;
2345             real yzcc = axis.y * axis.z * cc;
2346             real xs = axis.x * s;
2347             real ys = axis.y * s;
2348             real zs = axis.z * s;
2349    
2350             Matrix44 mat = identity;
2351             with (mat)
2352             {
2353                 m00 = x2 * cc + c;      m01 = xycc - zs;        m02 = xzcc + ys;
2354                 m10 = xycc + zs;        m11 = y2 * cc + c;      m12 = yzcc - xs;
2355                 m20 = xzcc - ys;        m21 = yzcc + xs;        m22 = z2 * cc + c;
2356             }
2357    
2358             return mat;
2359         }
2360        
2361         /**
2362         Constructs matrix that represents _rotation specified by quaternion.
2363         Method works with assumption that quaternion is unit.       
2364         Throws:
2365             AssertError on non-unit quaternion call attempt if module was compiled with
2366             contract checks enabled.
2367         */
2368         static Matrix44 rotation(Quaternion q)
2369         in { assert( q.isUnit() ); }
2370         body
2371         {
2372             float_t tx  = 2.f * q.x;
2373             float_t ty  = 2.f * q.y;
2374             float_t tz  = 2.f * q.z;
2375             float_t twx = tx * q.w;
2376             float_t twy = ty * q.w;
2377             float_t twz = tz * q.w;
2378             float_t txx = tx * q.x;
2379             float_t txy = ty * q.x;
2380             float_t txz = tz * q.x;
2381             float_t tyy = ty * q.y;
2382             float_t tyz = tz * q.y;
2383             float_t tzz = tz * q.z;
2384            
2385             Matrix44 mat = identity;
2386             with (mat)
2387             {
2388                 m00 = 1.f - (tyy + tzz);
2389                 m01 = txy - twz;
2390                 m02 = txz + twy;
2391                 m10 = txy + twz;
2392                 m11 = 1.f - (txx + tzz);
2393                 m12 = tyz - twx;
2394                 m20 = txz - twy;
2395                 m21 = tyz + twx;
2396                 m22 = 1.f - (txx + tyy);
2397             }
2398            
2399             return mat;
2400         }
2401    
2402         /** Constructs _translation matrix with offset values specified as arguments. */
2403         static Matrix44 translation(float_t x, float_t y, float_t z)
2404         {
2405             return Matrix44(1, 0, 0, x,
2406                             0, 1, 0, y,
2407                             0, 0, 1, z,
2408                             0, 0, 0, 1);
2409         }
2410    
2411         /** Constructs _translation matrix with offset values specified as v's components. */
2412         static Matrix44 translation(Vector3 v)
2413         {
2414             return translation(v.x, v.y, v.z);
2415         }
2416        
2417         /**
2418         Constructs one-point perspecive projection matrix.
2419         Params:
2420             fov =       Field of view in vertical plane in radians.
2421             aspect =    Frustum's width / height coefficient. It shouldn't be 0.
2422             near =      Distance to near plane.
2423             near =      Distance to far plane.
2424         */
2425         static Matrix44 perspective(float_t fov, float_t aspect, float_t near, float_t far)
2426         in
2427         {
2428             assert( fov < 2*PI );
2429             assert( !equal(aspect, 0) );
2430             assert( near > 0 );
2431             assert( far > near );
2432         }
2433         body
2434         {
2435             real cot = 1. / tan(fov / 2.);
2436                    
2437             return Matrix44(cot / aspect,    0,                            0,                                  0,
2438                             0,             cot,                            0,                                  0,
2439                             0,               0,  (near + far) / (near - far),  2.f * (near * far) / (near - far),
2440                             0,               0,                           -1,                                  0);
2441         }
2442        
2443         /**
2444         Constructs view matrix.
2445         Params:
2446             eye =       Viewer's eye position.
2447             target =    View target.
2448             up =        View up vector.
2449         
2450         Arguments should not be complanar, elsewise matrix will contain infinity
2451         elements. You can check this with isnormal() method.
2452         */
2453         static Matrix44 lookAt(Vector3 eye, Vector3 target, Vector3 up)
2454         {
2455             Vector3 z = (eye - target).normalized();
2456             alias up y;
2457             Vector3 x = cp(y, z);
2458             y = cp(z, x);
2459             x.normalize();
2460             y.normalize();
2461                    
2462             Matrix44 mat = identity;
2463             mat.v[0].xyz = Vector3(x.x, y.x, z.x);
2464             mat.v[1].xyz = Vector3(x.y, y.y, z.y);
2465             mat.v[2].xyz = Vector3(x.z, y.z, z.z);
2466                    
2467             mat.m03 = -dp(eye, x);
2468             mat.m13 = -dp(eye, y);
2469             mat.m23 = -dp(eye, z);
2470                    
2471             return mat;   
2472         }
2473        
2474         /**
2475         Returns: Inverse copy of this matrix.
2476         
2477         In case if this matrix is singular (i.e. determinant = 0) result matrix will has
2478         infinity elements. You can check this with isnormal() method.
2479         */
2480         Matrix44 inverse()
2481         {
2482             real det = determinant();
2483             //if (equal(det, 0))
2484             //{
2485             //    return nan;
2486             //}
2487            
2488             real rdet = 1/det;
2489             return Matrix44(
2490                 rdet * (m11 * (m22 * m33 - m23 * m32) + m12 * (m23 * m31 - m21 * m33) + m13 * (m21 * m32 - m22 * m31)),
2491                 rdet * (m21 * (m02 * m33 - m03 * m32) + m22 * (m03 * m31 - m01 * m33) + m23 * (m01 * m32 - m02 * m31)),
2492                 rdet * (m31 * (m02 * m13 - m03 * m12) + m32 * (m03 * m11 - m01 * m13) + m33 * (m01 * m12 - m02 * m11)),
2493                 rdet * (m01 * (m13 * m22 - m12 * m23) + m02 * (m11 * m23 - m13 * m21) + m03 * (m12 * m21 - m11 * m22)),
2494                 rdet * (m12 * (m20 * m33 - m23 * m30) + m13 * (m22 * m30 - m20 * m32) + m10 * (m23 * m32 - m22 * m33)),
2495                 rdet * (m22 * (m00 * m33 - m03 * m30) + m23 * (m02 * m30 - m00 * m32) + m20 * (m03 * m32 - m02 * m33)),
2496                 rdet * (m32 * (m00 * m13 - m03 * m10) + m33 * (m02 * m10 - m00 * m12) + m30 * (m03 * m12 - m02 * m13)),
2497                 rdet * (m02 * (m13 * m20 - m10 * m23) + m03 * (m10 * m22 - m12 * m20) + m00 * (m12 * m23 - m13 * m22)),
2498                 rdet * (m13 * (m20 * m31 - m21 * m30) + m10 * (m21 * m33 - m23 * m31) + m11 * (m23 * m30 - m20 * m33)),
2499                 rdet * (m23 * (m00 * m31 - m01 * m30) + m20 * (m01 * m33 - m03 * m31) + m21 * (m03 * m30 - m00 * m33)),
2500                 rdet * (m33 * (m00 * m11 - m01 * m10) + m30 * (m01 * m13 - m03 * m11) + m31 * (m03 * m10 - m00 * m13)),
2501                 rdet * (m03 * (m11 * m20 - m10 * m21) + m00 * (m13 * m21 - m11 * m23) + m01 * (m10 * m23 - m13 * m20)),
2502                 rdet * (m10 * (m22 * m31 - m21 * m32) + m11 * (m20 * m32 - m22 * m30) + m12 * (m21 * m30 - m20 * m31)),
2503                 rdet * (m20 * (m02 * m31 - m01 * m32) + m21 * (m00 * m32 - m02 * m30) + m22 * (m01 * m30 - m00 * m31)),
2504                 rdet * (m30 * (m02 * m11 - m01 * m12) + m31 * (m00 * m12 - m02 * m10) + m32 * (m01 * m10 - m00 * m11)),
2505                 rdet * (m00 * (m11 * m22 - m12 * m21) + m01 * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20)));
2506         }
2507        
2508         /**
2509         Inverts this matrix.
2510         
2511         In case if matrix is singular (i.e. determinant = 0) result matrix will has
2512         infinity elements. You can check this with isnormal() method.
2513         */
2514         void invert()
2515         {
2516             real det = determinant();
2517             //if (equal(det, 0))
2518             //{
2519             //    *this = nan;
2520             //    return;
2521             //}
2522            
2523             real rdet = 1/det;
2524             set(rdet * (m11 * (m22 * m33 - m23 * m32) + m12 * (m23 * m31 - m21 * m33) + m13 * (m21 * m32 - m22 * m31)),
2525                 rdet * (m21 * (m02 * m33 - m03 * m32) + m22 * (m03 * m31 - m01 * m33) + m23 * (m01 * m32 - m02 * m31)),
2526                 rdet * (m31 * (m02 * m13 - m03 * m12) + m32 * (m03 * m11 - m01 * m13) + m33 * (m01 * m12 - m02 * m11)),
2527                 rdet * (m01 * (m13 * m22 - m12 * m23) + m02 * (m11 * m23 - m13 * m21) + m03 * (m12 * m21 - m11 * m22)),
2528                 rdet * (m12 * (m20 * m33 - m23 * m30) + m13 * (m22 * m30 - m20 * m32) + m10 * (m23 * m32 - m22 * m33)),
2529                 rdet * (m22 * (m00 * m33 - m03 * m30) + m23 * (m02 * m30 - m00 * m32) + m20 * (m03 * m32 - m02 * m33)),
2530                 rdet * (m32 * (m00 * m13 - m03 * m10) + m33 * (m02 * m10 - m00 * m12) + m30 * (m03 * m12 - m02 * m13)),
2531                 rdet * (m02 * (m13 * m20 - m10 * m23) + m03 * (m10 * m22 - m12 * m20) + m00 * (m12 * m23 - m13 * m22)),
2532                 rdet * (m13 * (m20 * m31 - m21 * m30) + m10 * (m21 * m33 - m23 * m31) + m11 * (m23 * m30 - m20 * m33)),
2533                 rdet * (m23 * (m00 * m31 - m01 * m30) + m20 * (m01 * m33 - m03 * m31) + m21 * (m03 * m30 - m00 * m33)),
2534                 rdet * (m33 * (m00 * m11 - m01 * m10) + m30 * (m01 * m13 - m03 * m11) + m31 * (m03 * m10 - m00 * m13)),
2535                 rdet * (m03 * (m11 * m20 - m10 * m21) + m00 * (m13 * m21 - m11 * m23) + m01 * (m10 * m23 - m13 * m20)),
2536                 rdet * (m10 * (m22 * m31 - m21 * m32) + m11 * (m20 * m32 - m22 * m30) + m12 * (m21 * m30 - m20 * m31)),
2537                 rdet * (m20 * (m02 * m31 - m01 * m32) + m21 * (m00 * m32 - m02 * m30) + m22 * (m01 * m30 - m00 * m31)),
2538                 rdet * (m30 * (m02 * m11 - m01 * m12) + m31 * (m00 * m12 - m02 * m10) + m32 * (m01 * m10 - m00 * m11)),
2539                 rdet * (m00 * (m11 * m22 - m12 * m21) + m01 * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20)));
2540         }
2541        
2542         /** Returns: Determinant */
2543         real determinant()
2544         {
2545             return
2546                 + (m00 * m11 - m01 * m10) * (m22 * m33 - m23 * m32)
2547                 - (m00 * m12 - m02 * m10) * (m21 * m33 - m23 * m31)
2548                 + (m00 * m13 - m03 * m10) * (m21 * m32 - m22 * m31)
2549                 + (m01 * m12 - m02 * m11) * (m20 * m33 - m23 * m30)
2550                 - (m01 * m13 - m03 * m11) * (m20 * m32 - m22 * m30)
2551                 + (m02 * m13 - m03 * m12) * (m20 * m31 - m21 * m30);
2552         }
2553        
2554         /**
2555         Returns: Frobenius _norm of matrix.
2556         References:
2557             $(LINK http://en.wikipedia.org/wiki/Frobenius_norm#Frobenius_norm).       
2558         */
2559         real norm()
2560         {
2561             return sqrt( normSquare );
2562         }
2563        
2564         /**
2565         Returns: Square of Frobenius norm of matrix.
2566
2567         Method doesn't need calculation of square root.
2568
2569         References:
2570             $(LINK http://en.wikipedia.org/wiki/Frobenius_norm#Frobenius_norm).
2571         */
2572         real normSquare()
2573         {
2574             real ret = 0;
2575             for (int i = 16; i--; )
2576             {
2577                 real x = a[i];
2578                 ret += x * x;
2579             }
2580            
2581             return ret;
2582         }
2583        
2584         /**
2585         Returns: Whether this matrix represents affine transformation.
2586         References:
2587             $(LINK http://en.wikipedia.org/wiki/Affine_transformation).
2588         */
2589         bool isAffine()
2590         {
2591             return equal(m30, 0) && equal(m31, 0) && equal(m32, 0) && equal(m33, 1);
2592         }
2593        
2594         /** Transposes this matrix. */
2595         void transpose()
2596         {
2597             /*           */        swap(m01, m10);        swap(m02, m20);        swap(m03, m30);
2598             /*           */        /*           */        swap(m12, m21);        swap(m13, m31);
2599             /*           */        /*           */        /*           */        swap(m23, m32);
2600             /*           */        /*           */        /*           */        /*           */
2601         }
2602        
2603         /** Returns: Transposed copy of this matrix. */
2604         Matrix44 transposed()
2605         {
2606             return Matrix44(
2607                 m00, m10, m20, m30,
2608                 m01, m11, m21, m31,
2609                 m02, m12, m22, m32,
2610                 m03, m13, m23, m33 );
2611         }
2612        
2613         /** R/W property. Corner 3x3 minor. */
2614         Matrix33 cornerMinor()
2615         {
2616             return Matrix33(m00, m01, m02,
2617                             m10, m11, m12,
2618                             m20, m21, m22);
2619         }
2620        
2621         /** ditto */
2622         void cornerMinor(Matrix33 mat)
2623         {
2624             m00 = mat.m00;        m01 = mat.m01;        m02 = mat.m02;
2625             m10 = mat.m10;        m11 = mat.m11;        m12 = mat.m12;
2626             m20 = mat.m20;        m21 = mat.m21;        m22 = mat.m22;
2627         }
2628        
2629         /**
2630         Standard operators that have intuitive meaning, same as in classical math. Exception
2631         is multiplication with Vecto3 that doesn't make sense for classical math, in that case
2632         Vector3 is implicitl expanded to Vector4 with w=1.
2633         
2634         Note that division operators do no cheks of value of k, so in case of division
2635         by 0 result matrix will have infinity components. You can check this with isnormal()
2636         method.
2637         */
2638         Matrix44 opNeg()
2639         {
2640             return Matrix44(-m00, -m01, -m02, -m03,
2641                             -m10, -m11, -m12, -m13,
2642                             -m20, -m21, -m22, -m23,
2643                             -m30, -m31, -m32, -m33);
2644         }
2645    
2646         /** ditto */
2647         Matrix44 opAdd(Matrix44 mat)
2648         {
2649             return Matrix44(m00 + mat.m00, m01 + mat.m01, m02 + mat.m02, m03 + mat.m03,
2650                             m10 + mat.m10, m11 + mat.m11, m12 + mat.m12, m13 + mat.m13,
2651                             m20 + mat.m20, m21 + mat.m21, m22 + mat.m22, m23 + mat.m23,
2652                             m30 + mat.m30, m31 + mat.m31, m32 + mat.m32, m33 + mat.m33);
2653         }
2654    
2655         /** ditto */
2656         void opAddAssign(Matrix44 mat)
2657         {
2658             m00 += mat.m00; m01 += mat.m01; m02 += mat.m02; m03 += mat.m03;
2659             m10 += mat.m10; m11 += mat.m11; m12 += mat.m12; m13 += mat.m13;
2660             m20 += mat.m20; m21 += mat.m21; m22 += mat.m22; m23 += mat.m23;
2661             m30 += mat.m30; m31 += mat.m31; m32 += mat.m32; m33 += mat.m33;
2662         }
2663    
2664         /** ditto */
2665         Matrix44 opSub(Matrix44 mat)
2666         {
2667             return Matrix44(m00 - mat.m00, m01 - mat.m01, m02 - mat.m02, m03 - mat.m03,
2668                             m10 - mat.m10, m11 - mat.m11, m12 - mat.m12, m13 - mat.m13,
2669                             m20 - mat.m20, m21 - mat.m21, m22 - mat.m22, m23 - mat.m23,
2670                             m30 - mat.m30, m31 - mat.m31, m32 - mat.m32, m33 - mat.m33);
2671         }
2672    
2673         /** ditto */
2674         void opSubAssign(Matrix44 mat)
2675         {
2676             m00 -= mat.m00; m01 -= mat.m01; m02 -= mat.m02; m03 -= mat.m03;
2677             m10 -= mat.m10; m11 -= mat.m11; m12 -= mat.m12; m13 -= mat.m13;
2678             m20 -= mat.m20; m21 -= mat.m21; m22 -= mat.m22; m23 -= mat.m23;       
2679             m30 -= mat.m30; m31 -= mat.m31; m32 -= mat.m32; m33 -= mat.m33;       
2680         }
2681    
2682         /** ditto */
2683         Matrix44 opMul(float_t k)
2684         {
2685             return Matrix44(m00 * k, m01 * k, m02 * k, m03 * k,
2686                             m10 * k, m11 * k, m12 * k, m13 * k,
2687                             m20 * k, m21 * k, m22 * k, m23 * k,
2688                             m30 * k, m31 * k, m32 * k, m33 * k);
2689         }
2690    
2691         /** ditto */
2692         void opMulAssign(float_t k)
2693         {
2694             m00 *= k; m01 *= k; m02 *= k; m03 *= k;
2695             m10 *= k; m11 *= k; m12 *= k; m13 *= k;
2696             m20 *= k; m21 *= k; m22 *= k; m23 *= k;
2697             m30 *= k; m31 *= k; m32 *= k; m33 *= k;
2698         }
2699    
2700         /** ditto */
2701         Matrix44 opMul_r(float_t k)
2702         {
2703             return Matrix44(m00 * k, m01 * k, m02 * k, m03 * k,
2704                             m10 * k, m11 * k, m12 * k, m13 * k,
2705                             m20 * k, m21 * k, m22 * k, m23 * k,
2706                             m30 * k, m31 * k, m32 * k, m33 * k);
2707         }
2708    
2709         /** ditto */
2710         Matrix44 opDiv(float_t k)
2711         {
2712            
2713             return Matrix44(m00 / k, m01 / k, m02 / k, m03 / k,
2714                             m10 / k, m11 / k, m12 / k, m13 / k,
2715                             m20 / k, m21 / k, m22 / k, m23 / k,
2716                             m30 / k, m31 / k, m32 / k, m33 / k);
2717         }
2718    
2719         /** ditto */
2720         void opDivAssign(float_t k)
2721         {
2722             m00 /= k; m01 /= k; m02 /= k; m03 /= k;
2723             m10 /= k; m11 /= k; m12 /= k; m13 /= k;
2724             m20 /= k; m21 /= k; m22 /= k; m23 /= k;
2725             m30 /= k; m31 /= k; m32 /= k; m33 /= k;
2726         }
2727    
2728         /** ditto */
2729         bool opEquals(Matrix44 mat)
2730         {
2731             return m00 == mat.m00 && m01 == mat.m01 && m02 == mat.m02 && m03 == mat.m03 &&
2732                    m10 == mat.m10 && m11 == mat.m11 && m12 == mat.m12 && m13 == mat.m13 &&
2733                    m20 == mat.m20 && m21 == mat.m21 && m22 == mat.m22 && m23 == mat.m23 &&
2734                    m30 == mat.m30 && m31 == mat.m31 && m32 == mat.m32 && m33 == mat.m33;
2735         }
2736
2737         /** ditto */
2738         Matrix44 opMul(Matrix44 mat)
2739         {
2740             return Matrix44(m00 * mat.m00 + m01 * mat.m10 + m02 * mat.m20 + m03 * mat.m30,
2741                             m00 * mat.m01 + m01 * mat.m11 + m02 * mat.m21 + m03 * mat.m31,
2742                             m00 * mat.m02 + m01 * mat.m12 + m02 * mat.m22 + m03 * mat.m32,
2743                             m00 * mat.m03 + m01 * mat.m13 + m02 * mat.m23 + m03 * mat.m33,
2744    
2745                             m10 * mat.m00 + m11 * mat.m10 + m12 * mat.m20 + m13 * mat.m30,
2746                             m10 * mat.m01 + m11 * mat.m11 + m12 * mat.m21 + m13 * mat.m31,
2747                             m10 * mat.m02 + m11 * mat.m12 + m12 * mat.m22 + m13 * mat.m32,
2748                             m10 * mat.m03 + m11 * mat.m13 + m12 * mat.m23 + m13 * mat.m33,
2749    
2750                             m20 * mat.m00 + m21 * mat.m10 + m22 * mat.m20 + m23 * mat.m30,
2751                             m20 * mat.m01 + m21 * mat.m11 + m22 * mat.m21 + m23 * mat.m31,
2752                             m20 * mat.m02 + m21 * mat.m12 + m22 * mat.m22 + m23 * mat.m32,
2753                             m20 * mat.m03 + m21 * mat.m13 + m22 * mat.m23 + m23 * mat.m33,
2754    
2755                             m30 * mat.m00 + m31 * mat.m10 + m32 * mat.m20 + m33 * mat.m30,
2756                             m30 * mat.m01 + m31 * mat.m11 + m32 * mat.m21 + m33 * mat.m31,
2757                             m30 * mat.m02 + m31 * mat.m12 + m32 * mat.m22 + m33 * mat.m32,
2758                             m30 * mat.m03 + m31 * mat.m13 + m32 * mat.m23 + m33 * mat.m33);
2759         }
2760    
2761         /** ditto */
2762         void opMulAssign(Matrix44 mat)
2763         {
2764             *this = *this * mat;
2765         }
2766    
2767         /** ditto */
2768         Vector3 opMul(Vector3 v)
2769         {
2770             return Vector3(v.x * m00 + v.y * m01 + v.z * m02 + m03,
2771                            v.x * m10 + v.y * m11 + v.z * m12 + m13,
2772                            v.x * m20 + v.y * m21 + v.z * m22 + m23 );
2773         }
2774    
2775         /** ditto */
2776         Vector4 opMul(Vector4 v)
2777         {
2778             return Vector4(v.x * m00 + v.y * m01 + v.z * m02 + v.w * m03,
2779                            v.x * m10 + v.y * m11 + v.z * m12 + v.w * m13,
2780                            v.x * m20 + v.y * m21 + v.z * m22 + v.w * m23,
2781                            v.x * m30 + v.y * m31 + v.z * m32 + v.w * m33);
2782         }
2783    
2784         /** Returns: Element at row'th _row and col'th column. */
2785         float_t opIndex(uint row, uint col)
2786         in { assert( col < 4 && row < 4 ); }
2787         body
2788         {
2789             return m[col][row];
2790         }
2791    
2792         /** Assigns value f to element at row'th _row and col'th column. */
2793         void opIndexAssign(float_t f, uint row, uint col)
2794         in { assert( col < 4 && row < 4 ); }
2795         body
2796         {
2797             m[col][row] = f;
2798         }
2799        
2800         /** Returns: Vector representing col'th column. */
2801         Vector4 opIndex(uint col)
2802         in { assert( col < 4 ); }
2803         body
2804         {
2805             return v[col];
2806         }
2807    
2808         /** Replaces elements in col'th column with v's values. */
2809         void opIndexAssign(Vector4 v, uint col)
2810         in { assert( col < 4 ); }
2811         body
2812         {
2813             this.v[col] = v;
2814         }
2815    
2816         /**
2817         Returns: float_t pointer to [0,0] element of this matrix. It's like a _ptr method for arrays.
2818         
2819         Remember about column-major matrix memory layout.
2820         */
2821         float_t* ptr()
2822         {
2823             return a.ptr;
2824         }
2825        
2826         /** Returns: Copy of this matrix with float type elements. */
2827         Matrix44f toMatrix44f()
2828         {
2829             return Matrix44f(
2830                 cast(float)m00, cast(float)m01, cast(float)m02, cast(float)m03,
2831                 cast(float)m10, cast(float)m11, cast(float)m12, cast(float)m13,
2832                 cast(float)m20, cast(float)m21, cast(float)m22, cast(float)m23,
2833                 cast(float)m30, cast(float)m31, cast(float)m32, cast(float)m33 );
2834         }
2835        
2836         /** Returns: Copy of this matrix with double type elements. */
2837         Matrix44d toMatrix44d()
2838         {
2839             return Matrix44d(
2840                 cast(double)m00, cast(double)m01, cast(double)m02, cast(double)m03,
2841                 cast(double)m10, cast(double)m11, cast(double)m12, cast(double)m13,
2842                 cast(double)m20, cast(double)m21, cast(double)m22, cast(double)m23,
2843                 cast(double)m30, cast(double)m31, cast(double)m32, cast(double)m33 );
2844         }
2845        
2846         /** Returns: Copy of this matrix with real type elements. */
2847         Matrix44r toMatrix44r()
2848         {
2849             return Matrix44r(
2850                 cast(real)m00, cast(real)m01, cast(real)m02, cast(real)m03,
2851                 cast(real)m10, cast(real)m11, cast(real)m12, cast(real)m13,
2852                 cast(real)m20, cast(real)m21, cast(real)m22, cast(real)m23,
2853                 cast(real)m30, cast(real)m31, cast(real)m32, cast(real)m33 );
2854         }
2855     }
2856    
2857     alias EqualityByNorm!(Matrix44).equal equal; /// Introduces approximate equality function for Matrix44.
2858     alias Lerp!(Matrix44).lerp lerp;             /// Introduces linear interpolation function for Matrix44.   
2859 }
2860
2861 alias LinearAlgebra!(float).Vector2             Vector2f;
2862 alias LinearAlgebra!(float).Vector3             Vector3f;
2863 alias LinearAlgebra!(float).Vector4             Vector4f;
2864 alias LinearAlgebra!(float).Matrix33            Matrix33f;
2865 alias LinearAlgebra!(float).Matrix44            Matrix44f;
2866 alias LinearAlgebra!(float).equal               equal;
2867 alias LinearAlgebra!(float).dp                  dp;
2868 alias LinearAlgebra!(float).cp                  cp;
2869 alias LinearAlgebra!(float).isBasisOrthogonal   isBasisOrthogonal;
2870 alias LinearAlgebra!(float).isBasisOrthonormal  isBasisOrthonormal;
2871 alias LinearAlgebra!(float).lerp                lerp;
2872 alias LinearAlgebra!(float).slerp               slerp;
2873
2874 alias LinearAlgebra!(double).Vector2            Vector2d;
2875 alias LinearAlgebra!(double).Vector3            Vector3d;
2876 alias LinearAlgebra!(double).Vector4            Vector4d;
2877 alias LinearAlgebra!(double).Quaternion         Quaterniond;
2878 alias LinearAlgebra!(double).Matrix33           Matrix33d;
2879 alias LinearAlgebra!(double).Matrix44           Matrix44d;
2880 alias LinearAlgebra!(double).equal              equal;
2881 alias LinearAlgebra!(double).dp                 dp;
2882 alias LinearAlgebra!(double).cp                 cp;
2883 alias LinearAlgebra!(double).isBasisOrthogonal  isBasisOrthogonal;
2884 alias LinearAlgebra!(double).isBasisOrthonormal isBasisOrthonormal;
2885 alias LinearAlgebra!(double).lerp               lerp;
2886 alias LinearAlgebra!(double).slerp              slerp;
2887
2888 alias LinearAlgebra!(real).Vector2              Vector2r;
2889 alias LinearAlgebra!(real).Vector3              Vector3r;
2890 alias LinearAlgebra!(real).Vector4              Vector4r;
2891 alias LinearAlgebra!(real).Quaternion           Quaternionr;
2892 alias LinearAlgebra!(real).Matrix33             Matrix33r;
2893 alias LinearAlgebra!(real).Matrix44             Matrix44r;
2894 alias LinearAlgebra!(real).equal                equal;
2895 alias LinearAlgebra!(real).dp                   dp;
2896 alias LinearAlgebra!(real).cp                   cp;
2897 alias LinearAlgebra!(real).isBasisOrthogonal    isBasisOrthogonal;
2898 alias LinearAlgebra!(real).isBasisOrthonormal   isBasisOrthonormal;
2899 alias LinearAlgebra!(real).lerp                 lerp;
2900 alias LinearAlgebra!(real).slerp                slerp;
2901
2902 alias LinearAlgebra!(helix.config.float_t).Vector2     Vector2;
2903 alias LinearAlgebra!(helix.config.float_t).Vector3     Vector3;
2904 alias LinearAlgebra!(helix.config.float_t).Vector4     Vector4;
2905 alias LinearAlgebra!(helix.config.float_t).Quaternion  Quaternion;
2906 alias LinearAlgebra!(helix.config.float_t).Matrix33    Matrix33;
2907 alias LinearAlgebra!(helix.config.float_t).Matrix44    Matrix44;
2908
2909 unittest
2910 {
2911     assert( Vector2(1, 2).normalized().isUnit() );
2912     assert( Vector3(1, 2, 3).normalized().isUnit() );
2913     assert( Vector4(1, 2, 3, 4).normalized().isUnit() );
2914
2915     assert( Vector2(1, 2).dominatingAxis() == Ort.Y );
2916     assert( Vector3(1, 2, 3).dominatingAxis() == Ort.Z );
2917     assert( Vector4(1, 2, 3, 4).dominatingAxis() == Ort.W );
2918
2919     Vector4 v;
2920     v.set(1, 2, 3, 4);
2921     assert( v.isnormal() );
2922     v /= 0;
2923     assert( !v.isnormal() );
2924
2925     v.set(1, 2, 3, 4);
2926     v[Ort.Y] = v[Ort.X];
2927     assert( v == Vector4(1, 1, 3, 4) );
2928
2929     Vector4 t = Vector4(100, 200, 300, 400);
2930     Vector4 s;
2931     v.set(1, 2, 3, 4);
2932     s = v;
2933     v += t;
2934     v -= t;
2935     v = (v + t) - t;
2936     v *= 100;
2937     v /= 100;
2938     v = (10 * v * 10) / 100;
2939     assert( equal(v, s) );
2940
2941     assert( dp( cp( Vector3(1, 0, 2), Vector3(4, 0, 5) ), Vector3(3, 0, -2) )  == 0 );
2942 }
2943
2944 unittest
2945 {
2946     real yaw = PI / 8;
2947     real pitch = PI / 3;
2948     real roll = PI / 4;
2949    
2950     Quaternion q = Quaternion( Matrix33.rotation(yaw, pitch, roll) );
2951     assert( equal(q.yaw, yaw) );
2952     assert( equal(q.pitch, pitch) );
2953     assert( equal(q.roll, roll) );
2954 }
2955
2956 unittest
2957 {
2958     Matrix33 mat1 = Matrix33(1,2,3,4,5,6,7,8,9);
2959     static float[9] a = [1,2,3,4,5,6,7,8,9];
2960     Matrix33 mat2 = Matrix33(a);
2961
2962     assert(mat1 == mat2.transposed);
2963 }
2964
2965 /*
2966 unittest
2967 {
2968     Matrix33 a;
2969     
2970     a.m01 = 2;
2971     a.a[1] = 3;
2972     a.v[0].z = 4;
2973     assert(a[0, 1] == 2);
2974     assert(a[1, 0] == 3);
2975     assert(a[2, 0] == 4);
2976 }
2977 */
2978 unittest
2979 {
2980     Matrix33 a = Matrix33.rotation( Vector3(1, 2, 3).normalized, PI / 7.f );
2981     Matrix33 b = a.inverse;
2982     b.invert();
2983     assert( equal(a, b) );
2984     assert( equal(a.transposed.inverse, a.inverse.transposed) );
2985 }
2986
2987 unittest
2988 {
2989     Matrix33 Q, S;
2990     Matrix33 rot = Matrix33.rotationZ(PI / 7);
2991     Matrix33 scale = Matrix33.scale(-1, 2, 3);
2992     Matrix33 composition = rot * scale;
2993     composition.polarDecomposition(Q, S);   
2994     assert( equal(Q * S, composition) );
2995 }
Note: See TracBrowser for help on using the browser.