source: trunk/VUT/GtpVisibilityPreprocessor/src/Vector3.h @ 372

Revision 372, 12.8 KB checked in by bittner, 19 years ago (diff)

preparation for vss preprocessor. converted all .cpp and .h to dos new line format

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