Merge branch 'blender2.7'
[blender.git] / intern / elbeem / intern / ntl_ray.h
1 /** \file \ingroup elbeem
2  */
3 /******************************************************************************
4  *
5  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
6  * Copyright 2003-2006 Nils Thuerey
7  *
8  * ray class
9  *
10  *****************************************************************************/
11 #ifndef NTL_RAY_H
12 #define NTL_RAY_H
13
14 #include <sstream>
15 #include "ntl_vector3dim.h"
16 #include "ntl_lighting.h"
17 #include "ntl_geometryobject.h"
18 #include "ntl_bsptree.h"
19
20 #ifdef WITH_CXX_GUARDEDALLOC
21 #  include "MEM_guardedalloc.h"
22 #endif
23
24 class ntlTriangle;
25 class ntlRay;
26 class ntlTree;
27 class ntlScene;
28 class ntlRenderGlobals;
29 class ntlGeometryObject;
30
31 //! store data for an intersection of a ray and a triangle
32 // NOT YET USED
33 class ntlIntersection {
34         public:
35
36                 ntlIntersection() :
37                         distance(-1.0), normal(0.0),
38                         ray(NULL), tri(NULL), flags(0) { };
39
40                 gfxReal distance;
41                 ntlVec3Gfx normal;
42                 ntlRay *ray; 
43                 ntlTriangle *tri;
44                 char flags;
45
46 private:
47 #ifdef WITH_CXX_GUARDEDALLOC
48         MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlIntersection")
49 #endif
50 };
51
52 //! the main ray class
53 class ntlRay
54 {
55 public:
56   // CONSTRUCTORS
57   //! Initialize ray memebers, prints error message
58   ntlRay();
59   //! Copy constructor, copy all members
60   ntlRay(const ntlRay &r);
61   //! Explicitly init member variables with global render object
62   ntlRay(const ntlVec3Gfx &o, const ntlVec3Gfx &d, unsigned int i, gfxReal contrib, ntlRenderGlobals *glob);
63   //! Destructor
64   ~ntlRay();
65
66   //! Set the refraction flag for refracted rays
67   inline void setRefracted(unsigned char set) { mIsRefracted = set; }
68   inline void setReflected(unsigned char set) { mIsReflected = set; }
69
70   //! main ray recursion function
71   /*!
72    * First get closest object intersection, return background color if nothing
73    * was hit, else calculate shading and reflection components 
74    * and return mixed color */
75   const ntlColor shade() /*const*/;
76
77         /*! Trace a photon through the scene */
78         void tracePhoton(ntlColor) const;
79
80   //! intersect ray with AABB
81   void intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &normal, ntlVec3Gfx &retcoord) const;
82   void intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &normal, ntlVec3Gfx &retcoord) const;
83   void intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const;
84         // intersection routines in bsptree.cpp
85   //! optimized intersect ray with triangle
86   inline void intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
87   //! optimized intersect ray with triangle along +X axis dir
88   inline void intersectTriangleX(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
89   //! intersect only with front side
90   inline void intersectTriangleFront(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
91   //! intersect ray only with backsides
92   inline void intersectTriangleBack(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
93
94   // access methods
95   //! Returns the ray origin
96   inline ntlVec3Gfx getOrigin() const { return ntlVec3Gfx(mOrigin); }
97   //! Returns the ray direction
98   inline ntlVec3Gfx getDirection() const { return ntlVec3Gfx(mDirection); }
99   /*! Returns the ray relfection normal */
100   inline ntlVec3Gfx getNormal() const { return ntlVec3Gfx(mvNormal); }
101                 //! Is this ray refracted?
102   inline unsigned char getRefracted() const  { return mIsRefracted; }
103   inline unsigned char getReflected() const  { return mIsReflected; }
104   /*! Get position along ray */
105   inline ntlVec3Gfx getPositionAt(gfxReal t) const { return (mOrigin+(mDirection*t)); }
106         /*! Get render globals pointer of this ray */
107         inline ntlRenderGlobals *getRenderglobals( void ) const { return mpGlob; }
108         /*! get this ray's ID */
109         inline int getID( void ) const { return mID; }
110
111   /*! Set origin of this ray */
112   inline void setOrigin(ntlVec3Gfx set) { mOrigin = set; }
113         /*! Set direction of this ray */
114   inline void setDirection(ntlVec3Gfx set) { mDirection = set; }
115   /*! Set normal of this ray */
116   inline void setNormal(ntlVec3Gfx set) { mvNormal = set; }
117
118 protected:
119   /* Calulates the Lambertian and Specular color for
120    * the given reflection and returns it */
121   const ntlColor getShadedColor(ntlLightObject *light, const ntlRay &reflectedray, 
122                                                                                                                                 const ntlVec3Gfx &normal, ntlMaterial *surf) const;
123   
124 private:
125   /*! Origin of ray */
126   ntlVec3Gfx     mOrigin;
127   /*! Normalized direction vector of ray */
128   ntlVec3Gfx     mDirection;
129   /*! For reflected/refracted rays, the normal is stored here */
130   ntlVec3Gfx     mvNormal;
131   /*! recursion depth */
132   unsigned int mDepth;
133         /*! How much does this ray contribute to the surface color? abort if too small */
134         gfxReal mContribution;
135
136   /*! Global rendering settings */
137   ntlRenderGlobals *mpGlob;
138
139   /*! If this ray is a refracted one, this flag has to be set
140    *  This is necessary to for example also give the background color
141    *  to refracted rays. Otherwise things may look strange... 
142    */
143   unsigned char mIsRefracted;
144   unsigned char mIsReflected;
145
146         /*! ID of this ray (from renderglobals */
147         int mID;
148
149 private:
150 #ifdef WITH_CXX_GUARDEDALLOC
151         MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlRay")
152 #endif
153 };
154
155
156 /******************************************************************************
157  *
158  * a single triangle
159  *
160  *****************************************************************************/
161
162 // triangle intersection code in bsptree.cpp
163 // intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v);
164
165 /*! Triangle flag defines */
166 #define TRI_GEOMETRY      (1<<0)
167 #define TRI_CASTSHADOWS   (1<<1)
168
169
170 class ntlTriangle
171 {
172 public:
173   /* CONSTRUCTORS */
174   /*! Default constructor */
175   inline ntlTriangle( void );
176   /*! Constructor with parameters */
177   inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags);
178   /*! Copy - Constructor */
179   inline ntlTriangle(const ntlTriangle &tri);
180   /*! Destructor */
181   inline ~ntlTriangle() {}
182
183         /* Access methods */
184
185         /*! Acces to points of triangle */
186         inline int *getPoints( void ) { return mPoints; }
187         /*! Acces normal smoothing */
188         inline bool getSmoothNormals( void ) const { return mSmoothNormals; }
189         inline void setSmoothNormals( bool set){ mSmoothNormals = set; }
190         /*! Access object */
191         inline int getObjectId( void ) const { return mObjectId; }
192         inline void setObjectId( int set) { mObjectId = set; }
193         /*! Acces normal index */
194         inline ntlVec3Gfx getNormal( void ) const { return mNormal; }
195         inline void setNormal( ntlVec3Gfx set ) { mNormal = set; }
196         /*! Acces flags */
197         inline int getFlags( void ) const { return mFlags; }
198         inline void setFlags( int set ) { mFlags = set; }
199         /*! Access last intersection ray ID */
200         inline int  getLastRay( void ) const { return mLastRay; }
201         inline void setLastRay( int set ) { mLastRay = set; }
202         /*! Acces bbox id */
203         inline int getBBoxId( void ) const { return mBBoxId; }
204         inline void setBBoxId( int set ) { mBBoxId = set; }
205
206         /*! Get average of the three points for this axis */
207         inline gfxReal getAverage( int axis ) const;
208
209         /*! operator < for sorting, uses global sorting axis */
210         inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs);
211         /*! operator > for sorting, uses global sorting axis */
212         inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs);
213
214 protected:
215
216 private:
217
218         /*! indices to the three points of the triangle */
219         int mPoints[3];
220
221         /*! bounding box id (for tree generation), -1 if invalid */
222         int mBBoxId;
223
224         /*! Should the normals of this triangle get smoothed? */
225         bool mSmoothNormals;
226
227         /*! Id of parent object */
228         int mObjectId;
229
230         /*! Index to normal (for not smooth triangles) */
231         //int mNormalIndex; ??
232         ntlVec3Gfx mNormal;
233
234         /*! Flags for object attributes cast shadows */
235         int mFlags;
236
237         /*! ID of last ray that an intersection was calculated for */
238         int mLastRay;
239
240 private:
241 #ifdef WITH_CXX_GUARDEDALLOC
242         MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlTriangle")
243 #endif
244 };
245
246
247         
248
249 /******************************************************************************
250  * Default Constructor
251  *****************************************************************************/
252 ntlTriangle::ntlTriangle( void ) :
253         mBBoxId(-1),
254         mLastRay( 0 )
255 {
256         mPoints[0] = mPoints[1] = mPoints[2] = 0;
257         mSmoothNormals = 0;
258         mObjectId = 0;
259         mNormal = ntlVec3Gfx(0.0);
260         mFlags = 0;
261 }
262
263
264 /******************************************************************************
265  * Constructor
266  *****************************************************************************/
267 ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) :
268         mBBoxId(-1),
269         mLastRay( 0 )
270 {
271         mPoints[0] = p[0];
272         mPoints[1] = p[1];
273         mPoints[2] = p[2];
274         mSmoothNormals = smooth;
275         mObjectId = obj;
276         mNormal = norm;
277         mFlags = setflags;
278 }
279
280
281 /******************************************************************************
282  * Copy Constructor
283  *****************************************************************************/
284 ntlTriangle::ntlTriangle(const ntlTriangle &tri) :
285         mBBoxId(-1),
286         mLastRay( 0 )
287 {
288         mPoints[0] = tri.mPoints[0];
289         mPoints[1] = tri.mPoints[1];
290         mPoints[2] = tri.mPoints[2];
291         mSmoothNormals = tri.mSmoothNormals;
292         mObjectId      = tri.mObjectId;
293         mNormal        = tri.mNormal;
294         mFlags         = tri.mFlags;
295 }
296
297
298
299
300 /******************************************************************************
301  * Triangle sorting functions
302  *****************************************************************************/
303
304 /* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */
305 /* Static global variable for sorting direction */
306 extern int globalSortingAxis;
307 /* Access to points array for sorting */
308 extern vector<ntlVec3Gfx> *globalSortingPoints;
309         
310
311 gfxReal ntlTriangle::getAverage( int axis ) const
312
313         return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] + 
314                                                  (*globalSortingPoints)[ mPoints[1] ][axis] + 
315                                                  (*globalSortingPoints)[ mPoints[2] ][axis] )/3.0);
316 }
317
318 bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs)
319 {
320         return ( lhs.getAverage(globalSortingAxis) < 
321                                          rhs.getAverage(globalSortingAxis) );
322 }
323
324 bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs)
325 {
326         return ( lhs.getAverage(globalSortingAxis) > 
327                                          rhs.getAverage(globalSortingAxis) );
328 }
329
330
331
332 /******************************************************************************
333  *
334  * Scene object, that contains and manages all geometry objects
335  *
336  *****************************************************************************/
337
338
339
340 class ntlScene
341 {
342 public:
343   /* CONSTRUCTORS */
344   /*! Default constructor */
345   ntlScene( ntlRenderGlobals *glob, bool del=true );
346   /*! Default destructor  */
347   ~ntlScene();
348
349         /*! Add an object to the scene */
350         inline void addGeoClass(ntlGeometryClass *geo) { 
351                 mGeos.push_back( geo ); 
352                 geo->setObjectId(mGeos.size());
353         }
354         /*! Add a geo object to the scene, warning - only needed for hand init */
355         inline void addGeoObject(ntlGeometryObject *geo) { mObjects.push_back( geo ); }
356
357         /*! Acces a certain object */
358         inline ntlGeometryObject *getObject(int id) { 
359                 if(!mSceneBuilt) { errFatal("ntlScene::getObject","Scene not inited!", SIMWORLD_INITERROR); }
360                 return mObjects[id]; }
361
362         /*! Acces object array */
363         inline vector<ntlGeometryObject*> *getObjects() { 
364                 if(!mSceneBuilt) { errFatal("ntlScene::getObjects[]","Scene not inited!", SIMWORLD_INITERROR); }
365                 return &mObjects; }
366
367         /*! Acces geo class array */
368         inline vector<ntlGeometryClass*> *getGeoClasses() { 
369                 if(!mSceneBuilt) { errFatal("ntlScene::getGeoClasses[]","Scene not inited!", SIMWORLD_INITERROR); }
370                 return &mGeos; }
371
372         /*! draw scene with opengl */
373         //void draw();
374         
375         /*! Build/first init the scene arrays */
376         void buildScene(double time, bool firstInit);
377         
378         //! Prepare the scene triangles and maps for raytracing
379         void prepareScene(double time);
380         //! Do some memory cleaning, when frame is finished
381         void cleanupScene( void );
382
383         /*! Intersect a ray with the scene triangles */
384         void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const;
385
386         /*! return a vertex */
387         ntlVec3Gfx getVertex(int index) { return mVertices[index]; } 
388
389         // for tree generation 
390         /*! return pointer to vertices vector */
391         vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; }
392         /*! return pointer to vertices vector */
393         vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; }
394         /*! return pointer to vertices vector */
395         vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; }
396
397 private:
398
399         /*! Global settings */
400         ntlRenderGlobals *mpGlob;
401
402         /*! free objects? (only necessary for render scene, which  contains all) */
403         bool mSceneDel;
404
405   /*! List of geometry classes */
406   vector<ntlGeometryClass *> mGeos;
407
408   /*! List of geometry objects */
409   vector<ntlGeometryObject *> mObjects;
410
411   /*! List of triangles */
412   vector<ntlTriangle> mTriangles;
413   /*! List of vertices */
414   vector<ntlVec3Gfx>  mVertices;
415   /*! List of normals */
416   vector<ntlVec3Gfx>  mVertNormals;
417   /*! List of triangle normals */
418   vector<ntlVec3Gfx>  mTriangleNormals;
419
420         /*! Tree to store quickly intersect triangles */
421         ntlTree *mpTree;
422
423         /*! was the scene successfully built? only then getObject(i) requests are valid */
424         bool mSceneBuilt;
425
426         /*! shader/obj initializations are only done on first init */
427         bool mFirstInitDone;
428
429 private:
430 #ifdef WITH_CXX_GUARDEDALLOC
431         MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlScene")
432 #endif
433 };
434
435
436 #endif
437