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

Revision 2582, 12.8 KB checked in by bittner, 16 years ago (diff)

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

Line 
1// ============================================================================
2// $Id: raypack.h $
3//
4// raypack.h
5//        CRayPacket class - core of the ray-packet traversal routines
6//
7// Class: CRayPacket2x2
8//
9// REPLACEMENT_STRING
10//
11// Initial coding by Vlastimil Havran, 2006. The data design is in fact
12// Jakko Biker layout as propose in the article on Intel Web Site in year 2005
13// http://www.intel.com/cd/ids/developer/asmo-na/eng/245711.htm?page=1
14
15#ifndef __RAYPACK_H__
16#define __RAYPACK_H__
17
18#include <cassert>
19
20namespace GtpVisibilityPreprocessor {
21
22#include "Vector3.h"
23 
24// $$JB __SSE__ macro not define in _WIN32
25//#ifdef __SSE__
26#if 1
27
28// System headers for SSE
29#ifdef __INTEL_COMPILER
30#include <xmmintrin.h>
31#else
32// We assume GNU GCC compiler 3.4 or higher
33#include <xmmintrin.h>
34#endif
35
36
37// forward declarations
38#define SSE_INTRINSIC
39#ifdef SSE_INTRINSIC
40#define ALIGN16             __declspec(align(16))
41
42#ifdef _MSC_VER
43#define NEW_ALIGN16(type,n)  ((type*)_aligned_malloc((n)*sizeof(type),16))
44#define FREE_ALIGN16(array)  if(array){_aligned_free(array);(array)=0;}
45#else
46#define NEW_ALIGN16(type,n)  ((type*)malloc((n)*sizeof(type)))
47#define FREE_ALIGN16(array)  if (array) { free(array);(array)=0;}
48#endif // _MSC_VC
49
50#define PAD_FOUR(h)           mulFour(h)
51union extract_m128
52{
53  __m128 m;
54  float f[4];
55};
56#else
57#define NEW_ALIGN16(type,n)  ((type*)malloc((n)*sizeof(type)))
58#define ALIGN16             
59#define FREE_ALIGN16(array)  if(array){free(array);(array)=0;}
60#define PAD_FOUR(h)           (h)
61#endif
62 
63// -------------------------------------------------------------------
64// RayPacket2x2 class.  A set of 4 ray is defined by a location and a
65// direction. The direction is always normalized (length == 1) during
66// use.
67// -------------------------------------------------------------------
68class RayPacket2x2
69{
70public:
71  enum {
72    // The number of rays in one packet
73    PACKSIZE = 4
74  };
75 
76  // constructor
77  RayPacket2x2(
78    // origin and the direction of rays
79    const Vector3 orf[],
80    const Vector3 dirf[],
81    // The same type for all four rays
82    const int _type,
83    // All the rays has to start at the same cell
84    const void *_originCell = NULL,
85    // All the rays has to start at the same object
86    const Intersectable *_startObject = NULL,
87    // and also for shadow rays finish at the same object
88    const Intersectable *_stopObject = NULL
89  )
90  {
91    // location
92    ox[0] = orf[0].x; ox[1] = orf[1].x; ox[2] = orf[2].x; ox[3] = orf[3].x;
93    oy[0] = orf[0].y; oy[1] = orf[1].y; oy[2] = orf[2].y; oy[3] = orf[3].y;
94    oz[0] = orf[0].z; oz[1] = orf[1].z; oz[2] = orf[2].z; oz[3] = orf[3].z;
95    // direction, we assume to be normalized
96    dx[0] = dirf[0].x; dx[1] = dirf[1].x; dx[2] = dirf[2].x; dx[3] = dirf[3].x;
97    dy[0] = dirf[0].y; dy[1] = dirf[1].y; dy[2] = dirf[2].y; dy[3] = dirf[3].y;
98    dz[0] = dirf[0].z; dz[1] = dirf[1].z; dz[2] = dirf[2].z; dz[3] = dirf[3].z;
99    // Other components
100    ttype = _type;
101    origin = _originCell;
102    termination = NULL;
103    startObject = _startObject;
104    stopObject = _stopObject;
105    Init();
106  }
107  // dummy constructor
108  RayPacket2x2() {}
109
110  // Inititalize the ray again when already constructed
111  void Init(
112    // origin and the direction of rays
113    const Vector3 orf[],
114    const Vector3 dirf[],
115    // The same type for all four rays
116    const int _type,
117    // All the rays has to start at the same cell
118    const void *_originCell = NULL,
119    // All the rays has to start at the same object
120    const Intersectable *_startObject = NULL,
121    // and also for shadow rays finish at the same object
122    const Intersectable *_stopObject = NULL,
123    // if the direction of rays is normalized or not
124    bool dirNormalized = false)
125  {
126    // location
127    ox[0] = orf[0].x; ox[1] = orf[1].x; ox[2] = orf[2].x; ox[3] = orf[3].x;
128    oy[0] = orf[0].y; oy[1] = orf[1].y; oy[2] = orf[2].y; oy[3] = orf[3].y;
129    oz[0] = orf[0].z; oz[1] = orf[1].z; oz[2] = orf[2].z; oz[3] = orf[3].z;
130    // direction
131    if (dirNormalized) {
132      // already normalized
133      dx[0] = dirf[0].x; dx[1] = dirf[1].x; dx[2] = dirf[2].x; dx[3] = dirf[3].x;
134      dy[0] = dirf[0].y; dy[1] = dirf[1].y; dy[2] = dirf[2].y; dy[3] = dirf[3].y;
135      dz[0] = dirf[0].z; dz[1] = dirf[1].z; dz[2] = dirf[2].z; dz[3] = dirf[3].z;
136    }
137    else {
138      dx[0] = dirf[0].x; dx[1] = dirf[1].x; dx[2] = dirf[2].x; dx[3] = dirf[3].x;
139      dy[0] = dirf[0].y; dy[1] = dirf[1].y; dy[2] = dirf[2].y; dy[3] = dirf[3].y;
140      dz[0] = dirf[0].z; dz[1] = dirf[1].z; dz[2] = dirf[2].z; dz[3] = dirf[3].z;
141      std::cerr << "Normalization not yet implemented" << std::endl;
142      abort();
143    }
144    // other components
145    ttype = _type;
146    origin = _originCell;
147    termination = NULL;
148    startObject = _startObject;
149    stopObject = _stopObject;
150    Init();
151  }
152
153  // Computes the inverted direction of the rays, used optionally by
154  // a ray traversal algorithm. This has to be reconsidered, if it
155  // is really valuable. !!!
156  void ComputeInvertedDir() const;
157
158  // Computes the sign of the rays and returns false if all the directions
159  // for all three axes are the same, but it could be different among axes,
160  // but for one axis all 4 rays must have the same direction
161  bool ComputeDirSign() const;
162 
163  // the cell in the ASDS, where ray starts from
164  void SetOrigin(const void *c) {origin = c;}
165  const void *GetOrigin() const  { return origin; }
166
167  // the cell in the ASDS, where ray finishes the walk
168  void SetTermination(const void *c) {termination = c; }
169  const void* GetTermination() const { return termination;}
170
171  // the object on which the ray starts at
172  const Intersectable* GetStartObject() const { return startObject;}
173  const Intersectable* GetStopObject() const { return stopObject;}
174
175  void SetStartObject(const Intersectable *newStartObject) {
176    startObject = newStartObject;
177  }
178  void SetStopObject(const Intersectable *newStopObject) {
179    stopObject = newStopObject;
180  }
181  int GetType() const { return ttype; }
182
183  // Reading and Setting origin of the ray and direction
184  // Ray origin
185  inline void SetLoc(int i, const Vector3 &l);
186  Vector3  GetLoc(int i) const;
187  // Direction
188  void SetDir(int i, const Vector3 &ndir);
189  Vector3  GetDir(int i) const;
190
191  // Retuns an object that is intersected by i-th ray
192  Intersectable* GetObject(int i) const;
193  void SetObject(int i, Intersectable* obj);
194  // Retuns a signed distance that is intersected by i-th ray
195  float GetT(int i) const;
196  void SetT(int i, float t);
197  // Retuns maximum signed distance that is intersected by i-th ray
198  float GetMaxT(int i) const;
199  void SetMaxT(int i, float t);
200 
201  // make such operation to slightly change the ray direction
202  // in case any component of ray direction is zero. This is
203  // carried out for all the rays in a packet
204  void CorrectZeroComponents();
205
206  // Returns the sign of the direction if this was precomputed
207  const int &GetSign(int axis) const { return sign_dir[axis];}
208
209  // Reset the result of intersection
210  void ResetObjects() {
211    obj[0] = obj[1] = obj[2] = obj[3] = 0;
212  }
213 
214private:
215  // Here it is crucial the layout of the rays in memory
216  // The layout by Jakko Biker is used
217  typedef float real;
218  union
219  {
220    struct
221    {
222      // ox[N],oy[N],oz[N] - origin of the ray N
223      union { real ox[4]; __m128 ox4; };
224      union { real oy[4]; __m128 oy4; };
225      union { real oz[4]; __m128 oz4; };
226    };
227    __m128 orig[3];
228  };
229  union
230  {
231    struct
232    {
233      // dx[N],dy[N],dz[N] - direction of the ray N
234      union { real dx[4]; __m128 dx4; };
235      union { real dy[4]; __m128 dy4; };
236      union { real dz[4]; __m128 dz4; };
237    };
238    __m128 dir[3];
239  };
240
241#define _USE_INVDIR_RP
242#ifdef _USE_INVDIR_RP
243  union
244  {
245    struct
246    {
247      // idx[N],idy[N],idz[N] - direction of the ray N
248      // inverted dir - maybe an overkill for SSE
249      // to be checked !
250      union { real idx[4]; __m128 idx4; };
251      union { real idy[4]; __m128 idy4; };
252      union { real idz[4]; __m128 idz4; };
253    };
254    __m128 idir[3];
255  };
256#endif
257
258  // The auxiliary and result values for traversal
259     
260  // Here is the result - currently computed signed distance
261  union { real t[4]; __m128 t4; };
262  // and so far minimum signed distance computed. This is required
263  // for computing ray object intersections
264  union { real tmax[4]; __m128 tmax4; };
265  // Here are the pointers to the objects that correspond to tmax[4]
266  // above. They can be different for all the rays !
267  union { Intersectable* obj[4]; __m128 obj4; };
268
269  friend class CKTBTraversal;
270 
271  // Type of the ray: primary, shadow, dummy etc., see ERayType above
272  int ttype;
273
274  // The sign of direction to be used in some algorithms. The sign
275  // has to be the same for all the rays in all the components of the
276  // direction vector !!!!
277  mutable int      sign_dir[3];
278 
279  // I should have some abstract cell data type !!! here
280  // corresponds to the spatial elementary cell
281  const void *origin;
282  const void *termination;
283 
284  // the object on which surface a ray starts from
285  const Intersectable *startObject;
286  // the object on which surface a ray ends, for computation
287  // of the visibility queries between two points
288  const Intersectable *stopObject;
289
290  /// Precompute some CRay parameters. Most of them used for ropes traversal.
291  inline void Init();
292
293  // Precompute some values that are necessary.
294  inline void Precompute();
295};
296
297// --------------------------------------------------------------------------
298//  RayPacket2x2::SetLoc()
299// --------------------------------------------------------------------------
300inline void
301RayPacket2x2::SetLoc(int i, const Vector3 &l)
302{
303  assert( (i>=0) && (i<4));
304  ox[i] = l.x;
305  oy[i] = l.y;
306  oz[i] = l.z;
307}
308
309inline void
310RayPacket2x2::SetDir(int i, const Vector3 &ndr)
311{
312  // We assume that the direction is normalized !!!
313  assert( (i>=0) && (i<4));
314  dx[i] = ndr.x;
315  dy[i] = ndr.y;
316  dz[i] = ndr.z;
317}
318
319inline Vector3
320RayPacket2x2::GetLoc(int i) const
321{
322  assert( (i>=0) && (i<4));
323  return Vector3(ox[i],oy[i],oz[i]);
324}
325
326inline Vector3
327RayPacket2x2::GetDir(int i) const
328{
329  assert( (i>=0) && (i<4));
330  return Vector3(dx[i],dy[i],dz[i]);
331}
332
333// --------------------------------------------------------------------------
334//  RayPacket2x2::Precompute()
335// --------------------------------------------------------------------------
336inline void
337RayPacket2x2::Precompute()
338{
339  // initialize inverted dir ?
340#ifdef _USE_INVDIR_RP
341  // inverted dir - maybe an overkill for SSE
342  // to be checked !
343  idx[0] = 1.0f / dx[0];
344  idx[1] = 1.0f / dx[1];
345  idx[2] = 1.0f / dx[2];
346  idx[3] = 1.0f / dx[3];
347 
348  idy[0] = 1.0f / dy[0];
349  idy[1] = 1.0f / dy[1];
350  idy[2] = 1.0f / dy[2];
351  idy[3] = 1.0f / dy[3];
352
353  idz[0] = 1.0f / dz[0];
354  idz[1] = 1.0f / dz[1];
355  idz[2] = 1.0f / dz[2];
356  idz[3] = 1.0f / dz[3];
357#endif
358}
359
360// --------------------------------------------------------------------------
361//  RayPacket2x2::Init()
362// --------------------------------------------------------------------------
363inline void
364RayPacket2x2::Init()
365{
366  // apply the standard precomputation
367  Precompute();
368}
369
370// Computes the sign of the rays and returns false if all the directions
371// for all three axes are the same, but it could be different among axes,
372// but for one axis all 4 rays must have the same direction
373inline bool
374RayPacket2x2::ComputeDirSign() const
375{
376  // Set the sign of the direction 1 when negative
377  sign_dir[0] = (dx[0] < 0.0f);
378  sign_dir[1] = (dy[0] < 0.0f);
379  sign_dir[2] = (dz[0] < 0.0f);
380  for (int i = 1; i < 4; i++) {
381    if (sign_dir[0] != (dx[i] < 0.0f))
382      return true; // different direction in x
383    if (sign_dir[1] != (dy[i] < 0.0f))
384      return true; // different direction in y
385    if (sign_dir[2] != (dz[i] < 0.0f))
386      return true; // different direction in z
387  }// for
388
389  // Returns false if all 4 rays have the consistent direction
390  return false;
391}
392
393inline Intersectable*
394RayPacket2x2::GetObject(int i) const
395{
396  assert( (i>=0) && (i<4));
397  return obj[i];
398}
399
400inline void
401RayPacket2x2::SetObject(int i, Intersectable* object)
402{
403  assert( (i>=0) && (i<4));
404  obj[i] = object;
405}
406
407inline float
408RayPacket2x2::GetT(int i) const
409{
410  assert( (i>=0) && (i<4));
411  return t[i];
412}
413
414inline void
415RayPacket2x2::SetT(int i, float tnew)
416{
417  assert( (i>=0) && (i<4));
418  t[i] = tnew;
419}
420
421inline float
422RayPacket2x2::GetMaxT(int i) const
423{
424  assert( (i>=0) && (i<4));
425  return tmax[i];
426}
427
428inline void
429RayPacket2x2::SetMaxT(int i, float tmaxnew)
430{
431  assert( (i>=0) && (i<4));
432  tmax[i] = tmaxnew;
433}
434#else // __SSE__
435
436// ? What to do here
437//#error "AAA"
438
439#endif // __SSE__
440
441} // namespace
442
443#endif // __RAYPACK_H__
444
Note: See TracBrowser for help on using the repository browser.