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

Revision 176, 11.8 KB checked in by bittner, 19 years ago (diff)

cosine sampling bug fixed

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