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

Revision 2582, 13.7 KB checked in by bittner, 17 years ago (diff)

Havran Ray Caster compiles and links, but still does not work

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