source: GTP/trunk/Lib/Vis/Preprocessing/src/Vector3.h @ 2168

Revision 2168, 13.3 KB checked in by mattausch, 17 years ago (diff)
Line 
1#ifndef _Vector3_h__
2#define _Vector3_h__
3
4#include <iostream>
5//using namespace std;
6#include <math.h>
7#include "common.h"
8
9
10namespace GtpVisibilityPreprocessor {
11
12// Forward-declare some other classes.
13class Matrix4x4;
14class Vector2;
15
16
17// HACK of returning vector components as array fields.
18// NOT guarrantied to work with some strange variable allignment !
19#define __VECTOR_HACK
20
21class Vector3
22{
23public:
24  float x, y, z;
25
26  // for compatibility with pascal's code
27  void  setX(float q) { x=q; }
28  void  setY(float q) { y=q; }
29  void  setZ(float q) { z=q; }
30  float getX() const { return x; }
31  float getY() const { return y; }
32  float getZ() const { return z; }
33
34  // constructors
35  Vector3() { }
36
37  Vector3(float X, float Y, float Z) { x = X; y = Y; z = Z; }
38  Vector3(float X) { x = y = z = X; }
39  Vector3(const Vector3 &v) { x = v.x; y = v.y; z = v.z; }
40
41  // Functions to get at the vector components
42  float& operator[] (int inx) {
43#ifndef __VECTOR_HACK
44    if (inx == 0)
45      return x;
46    else
47      if (inx == 1)
48        return y;
49    else
50      return z;
51#else
52    return (&x)[inx];
53#endif
54   
55  }
56
57#ifdef __VECTOR_HACK
58  operator const float*() const { return (const float*) this; }
59#endif
60
61  const float& operator[] (int inx) const {
62#ifndef __VECTOR_HACK
63    if (inx == 0)
64      return x;
65    else
66      if (inx == 1)
67        return y;
68      else
69        return z;
70#else
71    return *(&x+inx);
72#endif
73  }
74
75  void ExtractVerts(float *px, float *py, int which) const;
76 
77  void SetValue(const float &a, const float &b, const float &c)
78  {  x=a; y=b; z=c; }
79
80  void SetValue(const float a) { x = y = z = a; }
81 
82  // returns the axis, where the vector has the largest value
83  int DrivingAxis(void) const;
84
85  // returns the axis, where the vector has the smallest value
86  int TinyAxis(void) const;
87
88  inline float MaxComponent(void) const {
89     // return (x > y && x > z) ? x : ((y > z) ? y : z);
90     return (x > y) ? ( (x > z) ? x : z) : ( (y > z) ? y : z);
91   }
92 
93   inline Vector3 Abs(void) const {
94     return Vector3(fabs(x), fabs(y), fabs(z));
95   }
96
97  // normalizes the vector of unit size corresponding to given vector
98  inline void Normalize();
99 
100  /** Returns false if this vector has a nan component.
101  */
102  bool CheckValidity() const;
103
104  /**
105    ===> Using ArbitraryNormal() for constructing coord systems
106    ===> is obsoleted by RightHandedBase() method (<JK> 12/20/03).   
107
108     Return an arbitrary normal to `v'.
109     In fact it tries v x (0,0,1) an if the result is too small,
110     it definitely does v x (0,1,0). It will always work for
111     non-degenareted vector and is much faster than to use
112     TangentVectors.
113
114     @param v(in) The vector we want to find normal for.
115     @return The normal vector to v.
116  */
117  friend inline Vector3 ArbitraryNormal(const Vector3 &v);
118
119  /**
120    Find a right handed coordinate system with (*this) being
121    the z-axis. For a right-handed system, U x V = (*this) holds.
122    This implementation is here to avoid inconsistence and confusion
123    when construction coordinate systems using ArbitraryNormal():
124    In fact:
125      V = ArbitraryNormal(N);
126      U = CrossProd(V,N);
127    constructs a right-handed coordinate system as well, BUT:
128    1) bugs can be introduced if one mistakenly constructs a
129       left handed sytems e.g. by doing
130       U = ArbitraryNormal(N);
131       V = CrossProd(U,N);
132    2) this implementation gives non-negative base vectors
133       for (*this)==(0,0,1) |  (0,1,0) | (1,0,0), which is
134       good for debugging and is not the case with the implementation
135       using ArbitraryNormal()
136
137    ===> Using ArbitraryNormal() for constructing coord systems
138             is obsoleted by this method (<JK> 12/20/03).   
139  */
140  void RightHandedBase(Vector3& U, Vector3& V) const;
141
142  /// Transforms a vector to the global coordinate frame.
143  /**
144    Given a local coordinate frame (U,V,N) (i.e. U,V,N are
145    the x,y,z axes of the local coordinate system) and
146    a vector 'loc' in the local coordiante system, this
147    function returns a the coordinates of the same vector
148    in global frame (i.e. frame (1,0,0), (0,1,0), (0,0,1).
149  */
150  friend inline Vector3 ToGlobalFrame(const Vector3& loc,
151          const Vector3& U,
152          const Vector3& V,
153          const Vector3& N);
154 
155  /// Transforms a vector to a local coordinate frame.
156  /**
157    Given a local coordinate frame (U,V,N) (i.e. U,V,N are
158    the x,y,z axes of the local coordinate system) and
159    a vector 'loc' in the global coordiante system, this
160    function returns a the coordinates of the same vector
161    in the local frame.
162  */
163  friend inline Vector3 ToLocalFrame(const Vector3& loc,
164          const Vector3& U,
165          const Vector3& V,
166          const Vector3& N);
167
168  /// the magnitude=size of the vector
169  friend inline float Magnitude(const Vector3 &v);
170  /// the squared magnitude of the vector .. for efficiency in some cases
171  friend inline float SqrMagnitude(const Vector3 &v);
172  /// Magnitude(v1-v2)
173  friend inline float Distance(const Vector3 &v1, const Vector3 &v2);
174  /// SqrMagnitude(v1-v2)
175  friend inline float SqrDistance(const Vector3 &v1, const Vector3 &v2);
176
177  // creates the vector of unit size corresponding to given vector
178  friend inline Vector3 Normalize(const Vector3 &A);
179
180  // Rotate a normal vector.
181  friend Vector3 PlaneRotate(const Matrix4x4 &, const Vector3 &);
182
183  // construct view vectors .. DirAt is the main viewing direction
184  // Viewer is the coordinates of viewer location, UpL is the vector.
185  friend void ViewVectors(const Vector3 &DirAt, const Vector3 &Viewer,
186                                                  const Vector3 &UpL, Vector3 &ViewV,
187                                                  Vector3 &ViewU, Vector3 &ViewN );
188
189  // Given the intersection point `P', you have available normal `N'
190  // of unit length. Let us suppose the incoming ray has direction `D'.
191  // Then we can construct such two vectors `U' and `V' that
192  // `U',`N', and `D' are coplanar, and `V' is perpendicular
193  // to the vectors `N','D', and `V'. Then 'N', 'U', and 'V' create
194  // the orthonormal base in space R3.
195  friend void TangentVectors(Vector3 &U, Vector3 &V, // output
196                             const Vector3 &normal, // input
197                             const Vector3 &dirIncoming);
198  // Unary operators
199  Vector3 operator+ () const;
200  Vector3 operator- () const;
201
202  // Assignment operators
203  Vector3& operator+= (const Vector3 &A);
204  Vector3& operator-= (const Vector3 &A);
205  Vector3& operator*= (const Vector3 &A);
206  Vector3& operator*= (float A);
207  Vector3& operator/= (float A);
208
209  // Binary operators
210  friend inline Vector3 operator+ (const Vector3 &A, const Vector3 &B);
211  friend inline Vector3 operator- (const Vector3 &A, const Vector3 &B);
212  friend inline Vector3 operator* (const Vector3 &A, const Vector3 &B);
213  friend inline Vector3 operator* (const Vector3 &A, float B);
214  friend inline Vector3 operator* (float A, const Vector3 &B);
215  friend Vector3 operator* (const Matrix4x4 &, const Vector3 &);
216  friend inline Vector3 operator/ (const Vector3 &A, const Vector3 &B);
217
218  friend inline int operator< (const Vector3 &A, const Vector3 &B);
219  friend inline int operator<= (const Vector3 &A, const Vector3 &B);
220
221  friend inline Vector3 operator/ (const Vector3 &A, float B);
222  friend inline int operator== (const Vector3 &A, const Vector3 &B);
223  friend inline float DotProd(const Vector3 &A, const Vector3 &B);
224  friend inline Vector3 CrossProd (const Vector3 &A, const Vector3 &B);
225
226  friend ostream& operator<< (ostream &s, const Vector3 &A);
227  friend istream& operator>> (istream &s, Vector3 &A);
228   
229  friend void Minimize(Vector3 &min, const Vector3 &candidate);
230  friend void Maximize(Vector3 &max, const Vector3 &candidate);
231
232  friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr);
233  friend inline int EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2);
234
235  friend Vector3 CosineRandomVector(const Vector3 &normal);
236  friend Vector3 UniformRandomVector(const Vector3 &normal);
237  friend Vector3 UniformRandomVector();
238
239  friend Vector3
240  UniformRandomVector(const float r1, const float r2);
241
242  friend Vector3 CosineRandomVector(
243                                                                        const float r1,
244                                                                        const float r2,
245                                                                        const Vector3 &normal
246                                                                        );
247
248
249};
250
251inline Vector3
252ArbitraryNormal(const Vector3 &N)
253{
254  float dist2 = N.x * N.x + N.y * N.y;
255  if (dist2 > 0.0001) {
256    float inv_size = 1.0f/sqrtf(dist2);
257    return Vector3(N.y * inv_size, -N.x * inv_size, 0); // N x (0,0,1)
258  }
259  float inv_size = 1.0f/sqrtf(N.z * N.z + N.x * N.x);
260  return Vector3(-N.z * inv_size, 0, N.x * inv_size); // N x (0,1,0)
261}
262
263
264inline void
265Vector3::RightHandedBase(Vector3& U, Vector3& V) const
266{
267        // HACK
268        V = ArbitraryNormal(*this);
269        U = CrossProd(V, *this);
270}
271
272
273inline Vector3
274ToGlobalFrame(const Vector3 &loc,
275              const Vector3 &U,
276              const Vector3 &V,
277              const Vector3 &N)
278{
279  return loc.x * U + loc.y * V + loc.z * N;
280}
281
282inline Vector3
283ToLocalFrame(const Vector3 &loc,
284             const Vector3 &U,
285             const Vector3 &V,
286             const Vector3 &N)
287{
288  return Vector3( loc.x * U.x + loc.y * U.y + loc.z * U.z,
289                    loc.x * V.x + loc.y * V.y + loc.z * V.z,
290                    loc.x * N.x + loc.y * N.y + loc.z * N.z);
291}
292
293inline float
294Magnitude(const Vector3 &v)
295{
296  return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
297}
298
299inline float
300SqrMagnitude(const Vector3 &v)
301{
302  return v.x * v.x + v.y * v.y + v.z * v.z;
303}
304
305inline float
306Distance(const Vector3 &v1, const Vector3 &v2)
307{
308  return sqrtf(sqr(v1.x-v2.x) + sqr(v1.y-v2.y) + sqr(v1.z-v2.z));
309}
310
311inline float
312SqrDistance(const Vector3 &v1, const Vector3 &v2)
313{
314  return sqr(v1.x-v2.x)+sqr(v1.y-v2.y)+sqr(v1.z-v2.z);
315}
316
317inline Vector3
318Normalize(const Vector3 &A)
319{
320  return A * (1.0f/Magnitude(A));
321}
322
323inline float
324DotProd(const Vector3 &A, const Vector3 &B)
325{
326  return A.x * B.x + A.y * B.y + A.z * B.z;
327}
328
329// angle between two vectors with respect to a surface normal in the
330// range [0 .. 2 * pi]
331inline float
332Angle(const Vector3 &A, const Vector3 &B, const Vector3 &norm)
333{
334        Vector3 cross = CrossProd(A, B);
335
336        float signedAngle;
337
338        if (DotProd(cross, norm) > 0)
339                signedAngle = atan2(-Magnitude(CrossProd(A, B)), DotProd(A, B));
340        else
341                signedAngle = atan2(Magnitude(CrossProd(A, B)), DotProd(A, B));
342
343        if (signedAngle < 0)
344                return 2 * PI + signedAngle;
345
346        return signedAngle;
347}
348
349inline Vector3
350Vector3::operator+() const
351{
352  return *this;
353}
354
355inline Vector3
356Vector3::operator-() const
357{
358  return Vector3(-x, -y, -z);
359}
360
361inline Vector3&
362Vector3::operator+=(const Vector3 &A)
363{
364  x += A.x;  y += A.y;  z += A.z;
365  return *this;
366}
367
368inline Vector3&
369Vector3::operator-=(const Vector3 &A)
370{
371  x -= A.x;  y -= A.y;  z -= A.z;
372  return *this;
373}
374
375inline Vector3&
376Vector3::operator*= (float A)
377{
378  x *= A;  y *= A;  z *= A;
379  return *this;
380}
381
382inline Vector3&
383Vector3::operator/=(float A)
384{
385  float a = 1.0f/A;
386  x *= a;  y *= a;  z *= a;
387  return *this;
388}
389
390inline Vector3&
391Vector3::operator*= (const Vector3 &A)
392{
393  x *= A.x;  y *= A.y;  z *= A.z;
394  return *this;
395}
396
397inline Vector3
398operator+ (const Vector3 &A, const Vector3 &B)
399{
400  return Vector3(A.x + B.x, A.y + B.y, A.z + B.z);
401}
402
403inline Vector3
404operator- (const Vector3 &A, const Vector3 &B)
405{
406  return Vector3(A.x - B.x, A.y - B.y, A.z - B.z);
407}
408
409inline Vector3
410operator* (const Vector3 &A, const Vector3 &B)
411{
412  return Vector3(A.x * B.x, A.y * B.y, A.z * B.z);
413}
414
415inline Vector3
416operator* (const Vector3 &A, float B)
417{
418  return Vector3(A.x * B, A.y * B, A.z * B);
419}
420
421inline Vector3
422operator* (float A, const Vector3 &B)
423{
424  return Vector3(B.x * A, B.y * A, B.z * A);
425}
426
427inline Vector3
428operator/ (const Vector3 &A, const Vector3 &B)
429{
430  return Vector3(A.x / B.x, A.y / B.y, A.z / B.z);
431}
432
433inline Vector3
434operator/ (const Vector3 &A, float B)
435{
436  float b = 1.0f / B;
437  return Vector3(A.x * b, A.y * b, A.z * b);
438}
439
440inline int
441operator< (const Vector3 &A, const Vector3 &B)
442{
443  return A.x < B.x && A.y < B.y && A.z < B.z;
444}
445
446inline int
447operator<= (const Vector3 &A, const Vector3 &B)
448{
449  return A.x <= B.x && A.y <= B.y && A.z <= B.z;
450}
451
452// Might replace floating-point == with comparisons of
453// magnitudes, if needed.
454inline int operator== (const Vector3 &A, const Vector3 &B)
455{
456  return (A.x == B.x) && (A.y == B.y) && (A.z == B.z);
457}
458
459inline Vector3
460CrossProd (const Vector3 &A, const Vector3 &B)
461{
462  return
463        Vector3(A.y * B.z - A.z * B.y,
464                          A.z * B.x - A.x * B.z,
465                        A.x * B.y - A.y * B.x);
466}
467
468
469inline void
470Vector3::Normalize()
471{
472  float sqrmag = x * x + y * y + z * z;
473  if (sqrmag > 0.0f)
474    (*this) *= 1.0f / sqrtf(sqrmag);
475}
476
477
478// Overload << operator for C++-style output
479inline ostream&
480operator<< (ostream &s, const Vector3 &A)
481{
482  return s << "(" << A.x << ", " << A.y << ", " << A.z << ")";
483}
484
485// Overload >> operator for C++-style input
486inline istream&
487operator>> (istream &s, Vector3 &A)
488{
489  char a;
490  // read "(x, y, z)"
491  return s >> a >> A.x >> a >> A.y >> a >> A.z >> a;
492}
493
494inline int
495EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2, float thr)
496{
497  if ( fabsf(v1.x-v2.x) > thr )
498    return false;
499  if ( fabsf(v1.y-v2.y) > thr )
500    return false;
501  if ( fabsf(v1.z-v2.z) > thr )
502    return false;
503  return true;
504}
505
506inline int
507EpsilonEqualV3(const Vector3 &v1, const Vector3 &v2)
508{
509  return EpsilonEqualV3(v1, v2, Limits::Small);
510}
511
512
513
514}
515
516#endif
Note: See TracBrowser for help on using the repository browser.