]> git.mxchange.org Git - simgear.git/blob - simgear/scene/sky/clouds3d/vec3f.hpp
Clouds3D crashes because there is no Light
[simgear.git] / simgear / scene / sky / clouds3d / vec3f.hpp
1 //-----------------------------------------------------------------------------
2 // File : vec3f.hpp
3 //-----------------------------------------------------------------------------
4 // GLVU : Copyright 1997 - 2002 
5 //        The University of North Carolina at Chapel Hill
6 //-----------------------------------------------------------------------------
7 // Permission to use, copy, modify, distribute and sell this software
8 // and its documentation for any purpose is hereby granted without
9 // fee, provided that the above copyright notice appear in all copies
10 // and that both that copyright notice and this permission notice
11 // appear in supporting documentation.  Binaries may be compiled with
12 // this software without any royalties or restrictions.
13 //
14 // The University of North Carolina at Chapel Hill makes no representations 
15 // about the suitability of this software for any purpose. It is provided 
16 // "as is" without express or implied warranty.
17
18 //==========================================================================
19 // Vec3.hpp : 3d vector class template. Works for any integer or real type.
20 //==========================================================================
21
22 #ifndef VEC3_H
23 #define VEC3_H
24
25 #include <stdio.h>
26 #include <math.h>
27
28 /**
29  * @class Vec3
30  * @brief A templated 3-vector class
31  *
32  * Everybody in graphics has to write their own basic 3-vector class.
33  * And we're no exception.  This one uses templates, so that with one
34  * definition of the class you can have a 3-vector of floats or doubles
35  * depending on how precise you are, or you can make 3-vectors of ints
36  * or unsigned char, handy for representing colors.
37  *
38  * A couple of typedefs for common instatiations are provided by
39  * default: Vec3f, and Vec3d, the float and double versions,
40  * respectively.
41  *
42  */
43 template<class Type>
44 class Vec3
45 {
46   public:
47     Type x, y, z;  ///< The storage for the three components of the vector
48
49     /// Default constructor.
50     /// Note: does \em not initialize x, y, and z!
51     Vec3 (void) 
52       {};
53     /// Three component constructor
54     Vec3 (const Type X, const Type Y, const Type Z) 
55       { x=X; y=Y; z=Z; };
56     /// Copy constructor
57     Vec3 (const Vec3& v) 
58       { x=v.x; y=v.y; z=v.z; };
59     /// Construct from array
60     Vec3 (const Type v[3])
61       { x=v[0]; y=v[1]; z=v[2]; };
62     /// Set from components
63     void Set (const Type X, const Type Y, const Type Z)
64       { x=X; y=Y; z=Z; }
65     /// Set from array
66     void Set (const Type v[3])
67       { x=v[0]; y=v[1]; z=v[2]; };
68
69     operator Type*()                            /// Type * CONVERSION
70       { return (Type *)&x; }
71     operator const Type*() const                /// CONST Type * CONVERSION
72       { return &x; }
73
74     bool operator == (const Vec3& A) const       /// COMPARISON (==)
75       { return (x==A.x && y==A.y && z==A.z); }
76     bool operator != (const Vec3& A) const       /// COMPARISON (!=)
77       { return (x!=A.x || y!=A.y || z!=A.z); }
78
79     Vec3& operator = (const Vec3& A)            /// ASSIGNMENT (=)
80       { x=A.x; y=A.y; z=A.z; 
81         return(*this);  };
82     Vec3 operator + (const Vec3& A) const       /// ADDITION (+)
83       { Vec3 Sum(x+A.x, y+A.y, z+A.z); 
84         return(Sum); };
85     Vec3 operator - (const Vec3& A) const       /// SUBTRACTION (-)
86       { Vec3 Diff(x-A.x, y-A.y, z-A.z);
87         return(Diff); };
88     Type operator * (const Vec3& A) const       /// DOT-PRODUCT (*)
89       { Type DotProd = x*A.x+y*A.y+z*A.z; 
90         return(DotProd); };
91     Vec3 operator / (const Vec3& A) const       /// CROSS-PRODUCT (/)
92       { Vec3 CrossProd(y*A.z-z*A.y, z*A.x-x*A.z, x*A.y-y*A.x);
93         return(CrossProd); };
94     Vec3 operator ^ (const Vec3& A) const       /// ALSO CROSS-PRODUCT (^)
95       { Vec3 CrossProd(y*A.z-z*A.y, z*A.x-x*A.z, x*A.y-y*A.x);
96         return(CrossProd); };
97     Vec3 operator * (const Type s) const        /// MULTIPLY BY SCALAR V*s (*)
98       { Vec3 Scaled(x*s, y*s, z*s); 
99         return(Scaled); };
100     Vec3 operator / (const Type s) const        /// DIVIDE BY SCALAR (/)
101       { Vec3 Scaled(x/s, y/s, z/s);
102         return(Scaled); };
103     Vec3 operator & (const Vec3& A) const       /// COMPONENT MULTIPLY (&)
104       { Vec3 CompMult(x*A.x, y*A.y, z*A.z);
105         return(CompMult); }
106
107     friend inline Vec3 operator *(Type s, const Vec3& v)  /// SCALAR MULT s*V
108       { return Vec3(v.x*s, v.y*s, v.z*s); }
109
110     Vec3& operator += (const Vec3& A)    /// ACCUMULATED VECTOR ADDITION (+=)
111       { x+=A.x; y+=A.y; z+=A.z;
112         return *this;}
113     Vec3& operator -= (const Vec3& A)    /// ACCUMULATED VECTOR SUBTRACTION (-=)
114       { x-=A.x; y-=A.y; z-=A.z; 
115         return *this; }
116     Vec3& operator *= (const Type s)     /// ACCUMULATED SCALAR MULT (*=)
117       { x*=s; y*=s; z*=s; 
118         return *this; }
119     Vec3& operator /= (const Type s)     /// ACCUMULATED SCALAR DIV (/=)
120       { x/=s; y/=s; z/=s; 
121         return *this; }
122     Vec3& operator &= (const Vec3& A)  /// ACCUMULATED COMPONENT MULTIPLY (&=)
123       { x*=A.x; y*=A.y; z*=A.z; return *this; }
124     Vec3 operator - (void) const        /// NEGATION (-)
125       { Vec3 Negated(-x, -y, -z);
126         return(Negated); };
127
128 /*
129     const Type& operator [] (const int i) const // ALLOWS VECTOR ACCESS AS AN ARRAY.
130       { return( (i==0)?x:((i==1)?y:z) ); };
131     Type & operator [] (const int i)
132       { return( (i==0)?x:((i==1)?y:z) ); };
133 */
134
135     Type Length (void) const                     /// LENGTH OF VECTOR
136       { return ((Type)sqrt(x*x+y*y+z*z)); };
137     Type LengthSqr (void) const                  /// LENGTH OF VECTOR (SQUARED)
138       { return (x*x+y*y+z*z); };
139     Vec3& Normalize (void)                       /// NORMALIZE VECTOR
140       { Type L = Length();                       //  CALCULATE LENGTH
141         if (L>0) { x/=L; y/=L; z/=L; }           //  DIV COMPONENTS BY LENGTH
142         return *this;
143       };                                         
144
145     /// Returns the 'star' matrix for a vector
146     /** This is the skew-symmetric matrix \b A such that 
147      *  \b A \b v == \p this x \b v 
148      * (the cross-product of \p this and \b v), for any vector \b v.
149      *  The matrix looks like this given vector (x,y,z):
150      *  @verbatim
151             | 0  -z   y|
152             | z   0  -x|
153             |-y   x   0|
154         @endverbatim
155      * 
156      * Return format is just an array in row-major (OpenGL/Fortran) order. 
157      * That is [0, -z, y, z, 0, -x, -y, x, 0].
158      */
159     Type* Star() const {
160       Type s[] = ( 0, -z,  y,
161                    z,  0, -x,
162                   -y,  x,  0);
163       return s;
164     }
165
166     /// Update \p Min and \p Max to enclose \p this
167     /** A very handy routine for working with min-max or axis aligned 
168      *  bounding boxes.
169      */
170     void UpdateMinMax(Vec3 &Min, Vec3 &Max) const
171     {
172       if (x<Min.x) Min.x=x; else if (x>Max.x) Max.x=x;
173       if (y<Min.y) Min.y=y; else if (y>Max.y) Max.y=y;
174       if (z<Min.z) Min.z=z; else if (z>Max.z) Max.z=z;
175     }
176
177     /// Construct an orthonormal basis from \p this
178     /** Compute two unit vectors \p U and \p V that are orthogonal
179      * to this vector and to each other.  Note that \p *this need
180      * not be a unit vector.
181      *
182      * The algorithm works as follows:
183      * Find smallest component of L (this), zero it, 
184      * negate one of the other two and swap them.  Then normalize.
185      * Ex. if x1 is the smallest, assign (x2,y2,z2):=(0,z1,-y1)
186      * Clearly now v1 dot v2 = x1*0 + y1*z1 + z1*-y1 = 0;
187      * Zeroing out the smallest means that the magnitude of 
188      * the remaining vector will be as  big as possible so that 
189      * when we normalize, we are safe from dividing by anything
190      * close to zero (unless *this was near 0 magnitude to 
191      * begin with, in which case lack of precision can't be avoided)
192      */
193   void CompleteOrthonormalBasis(Vec3 &U, Vec3 &V) const
194     {
195       U = *this;
196       unsigned char s[3] = {0, 1, 2}; 
197       unsigned char tmpa;
198       U.x = U.x < 0 ? -U.x : -U.x;
199       U.y = U.y < 0 ? -U.y : -U.y;
200       U.z = U.z < 0 ? -U.z : -U.z;
201       if ( U[0] > U[1] )
202       {
203         tmpa = s[0];
204         s[0] = s[1];
205         s[1] = tmpa;
206       }
207       // xy min in s[0] now.
208       if ( U[s[0]] > U[2] ) {
209         tmpa = s[2];
210         s[2] = s[0];
211         s[0] = tmpa;
212       }
213       // xyz min in s[0] now
214       U = *this;
215       U[s[0]] = 0;
216
217       // Voila U is now perpendicular to *this
218       U.Normalize();
219
220       // And so it's easy to find a v that is too, with cross product.
221       V = *this ^ U;
222       // Or by removing components projected onto other two...
223       // I think the cross product may be cheaper
224       // V = something - V * (*this.Normalize() + U);
225
226       V.Normalize(); // wouldn't be necessary if we knew *this were normalized
227     }
228
229     /// Dump the vector to \c stdout in a pretty way
230     void Print() const
231       { printf("(%.3f, %.3f, %.3f)\n",x, y, z); }
232
233     /// This is a handy way to get the zero vector just use Vec3<Type>::ZERO
234     static Vec3 ZERO;
235 };
236
237 typedef Vec3<float> Vec3f;
238 typedef Vec3<double> Vec3d;
239
240 template<class Type> Vec3<Type> Vec3<Type>::ZERO = Vec3<Type>(0,0,0);
241
242 #endif
243
244