doxygen: add newline after \file
[blender.git] / intern / elbeem / intern / ntl_ray.h
index c433c45..064fce2 100644 (file)
@@ -1,40 +1,33 @@
+/** \file
+ * \ingroup elbeem
+ */
 /******************************************************************************
  *
  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
- * Copyright 2003,2004 Nils Thuerey
+ * Copyright 2003-2006 Nils Thuerey
  *
  * ray class
  *
  *****************************************************************************/
-#ifndef NTL_RAY_HH
-#define NTL_RAY_HH
+#ifndef NTL_RAY_H
+#define NTL_RAY_H
 
+#include <sstream>
 #include "ntl_vector3dim.h"
-#include "ntl_lightobject.h"
+#include "ntl_lighting.h"
 #include "ntl_geometryobject.h"
-#include "ntl_renderglobals.h"
-
-
-/* Minimum value for refl/refr to be traced */
-#define RAY_THRESHOLD 0.001
-
-#if GFX_PRECISION==1
-// float values
-//! the minimal triangle determinant length
-#define RAY_TRIANGLE_EPSILON (1e-08)
-//! Minimal contribution for rays to be traced on
-#define RAY_MINCONTRIB (1e-04)
-
-#else 
-// double values
-//! the minimal triangle determinant length
-#define RAY_TRIANGLE_EPSILON (1e-15)
-//! Minimal contribution for rays to be traced on
-#define RAY_MINCONTRIB (1e-05)
-
-#endif 
+#include "ntl_bsptree.h"
 
+#ifdef WITH_CXX_GUARDEDALLOC
+#  include "MEM_guardedalloc.h"
+#endif
 
+class ntlTriangle;
+class ntlRay;
+class ntlTree;
+class ntlScene;
+class ntlRenderGlobals;
+class ntlGeometryObject;
 
 //! store data for an intersection of a ray and a triangle
 // NOT YET USED
@@ -50,6 +43,11 @@ class ntlIntersection {
                ntlRay *ray; 
                ntlTriangle *tri;
                char flags;
+
+private:
+#ifdef WITH_CXX_GUARDEDALLOC
+       MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlIntersection")
+#endif
 };
 
 //! the main ray class
@@ -84,8 +82,11 @@ public:
   void intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &normal, ntlVec3Gfx &retcoord) const;
   void intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &normal, ntlVec3Gfx &retcoord) const;
   void intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const;
+       // intersection routines in bsptree.cpp
   //! optimized intersect ray with triangle
   inline void intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
+  //! optimized intersect ray with triangle along +X axis dir
+  inline void intersectTriangleX(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
   //! intersect only with front side
   inline void intersectTriangleFront(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
   //! intersect ray only with backsides
@@ -146,88 +147,291 @@ private:
        /*! ID of this ray (from renderglobals */
        int mID;
 
+private:
+#ifdef WITH_CXX_GUARDEDALLOC
+       MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlRay")
+#endif
 };
 
 
+/******************************************************************************
+ *
+ * a single triangle
+ *
+ *****************************************************************************/
 
+// triangle intersection code in bsptree.cpp
+// intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v);
 
+/*! Triangle flag defines */
+#define TRI_GEOMETRY      (1<<0)
+#define TRI_CASTSHADOWS   (1<<1)
 
-/******************************************************************
- * triangle intersection with triangle pointer,
- * returns t,u,v by references 
- */
-inline void ntlRay::intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const
+
+class ntlTriangle
 {
-  /* (cf. moeller&haines, page 305) */
-  t = GFX_REAL_MAX;
-  ntlVec3Gfx  e0 = (*mpV)[ tri->getPoints()[0] ];
-  ntlVec3Gfx  e1 = (*mpV)[ tri->getPoints()[1] ] - e0;
-  ntlVec3Gfx  e2 = (*mpV)[ tri->getPoints()[2] ] - e0;
-  ntlVec3Gfx  p  = cross( mDirection, e2 );
-  gfxReal a  = dot(e1, p);     
-  if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return;
-      
-  gfxReal f  = 1/a;
-  ntlVec3Gfx  s  = mOrigin - e0;
-  u  = f * dot(s, p);
-  if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return;
-      
-  ntlVec3Gfx  q  = cross( s,e1 );
-  v  = f * dot(mDirection, q);
-  if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return;
-      
-  t = f * dot(e2, q);      
+public:
+  /* CONSTRUCTORS */
+  /*! Default constructor */
+  inline ntlTriangle( void );
+  /*! Constructor with parameters */
+  inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags);
+  /*! Copy - Constructor */
+  inline ntlTriangle(const ntlTriangle &tri);
+  /*! Destructor */
+  inline ~ntlTriangle() {}
+
+       /* Access methods */
+
+       /*! Acces to points of triangle */
+       inline int *getPoints( void ) { return mPoints; }
+       /*! Acces normal smoothing */
+       inline bool getSmoothNormals( void ) const { return mSmoothNormals; }
+       inline void setSmoothNormals( bool set){ mSmoothNormals = set; }
+       /*! Access object */
+       inline int getObjectId( void ) const { return mObjectId; }
+       inline void setObjectId( int set) { mObjectId = set; }
+       /*! Acces normal index */
+       inline ntlVec3Gfx getNormal( void ) const { return mNormal; }
+       inline void setNormal( ntlVec3Gfx set ) { mNormal = set; }
+       /*! Acces flags */
+       inline int getFlags( void ) const { return mFlags; }
+       inline void setFlags( int set ) { mFlags = set; }
+       /*! Access last intersection ray ID */
+       inline int  getLastRay( void ) const { return mLastRay; }
+       inline void setLastRay( int set ) { mLastRay = set; }
+       /*! Acces bbox id */
+       inline int getBBoxId( void ) const { return mBBoxId; }
+       inline void setBBoxId( int set ) { mBBoxId = set; }
+
+       /*! Get average of the three points for this axis */
+       inline gfxReal getAverage( int axis ) const;
+
+       /*! operator < for sorting, uses global sorting axis */
+       inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs);
+       /*! operator > for sorting, uses global sorting axis */
+       inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs);
+
+protected:
+
+private:
+
+       /*! indices to the three points of the triangle */
+       int mPoints[3];
+
+       /*! bounding box id (for tree generation), -1 if invalid */
+       int mBBoxId;
+
+       /*! Should the normals of this triangle get smoothed? */
+       bool mSmoothNormals;
+
+       /*! Id of parent object */
+       int mObjectId;
+
+       /*! Index to normal (for not smooth triangles) */
+       //int mNormalIndex; ??
+       ntlVec3Gfx mNormal;
+
+       /*! Flags for object attributes cast shadows */
+       int mFlags;
+
+       /*! ID of last ray that an intersection was calculated for */
+       int mLastRay;
+
+private:
+#ifdef WITH_CXX_GUARDEDALLOC
+       MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlTriangle")
+#endif
+};
+
+
+       
+
+/******************************************************************************
+ * Default Constructor
+ *****************************************************************************/
+ntlTriangle::ntlTriangle( void ) :
+       mBBoxId(-1),
+       mLastRay( 0 )
+{
+       mPoints[0] = mPoints[1] = mPoints[2] = 0;
+       mSmoothNormals = 0;
+       mObjectId = 0;
+       mNormal = ntlVec3Gfx(0.0);
+       mFlags = 0;
 }
-/******************************************************************
- * intersect only front or backsides
- */
-inline void ntlRay::intersectTriangleFront(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const
+
+
+/******************************************************************************
+ * Constructor
+ *****************************************************************************/
+ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) :
+       mBBoxId(-1),
+       mLastRay( 0 )
+{
+       mPoints[0] = p[0];
+       mPoints[1] = p[1];
+       mPoints[2] = p[2];
+       mSmoothNormals = smooth;
+       mObjectId = obj;
+       mNormal = norm;
+       mFlags = setflags;
+}
+
+
+/******************************************************************************
+ * Copy Constructor
+ *****************************************************************************/
+ntlTriangle::ntlTriangle(const ntlTriangle &tri) :
+       mBBoxId(-1),
+       mLastRay( 0 )
+{
+       mPoints[0] = tri.mPoints[0];
+       mPoints[1] = tri.mPoints[1];
+       mPoints[2] = tri.mPoints[2];
+       mSmoothNormals = tri.mSmoothNormals;
+       mObjectId      = tri.mObjectId;
+       mNormal        = tri.mNormal;
+       mFlags         = tri.mFlags;
+}
+
+
+
+
+/******************************************************************************
+ * Triangle sorting functions
+ *****************************************************************************/
+
+/* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */
+/* Static global variable for sorting direction */
+extern int globalSortingAxis;
+/* Access to points array for sorting */
+extern vector<ntlVec3Gfx> *globalSortingPoints;
+       
+
+gfxReal ntlTriangle::getAverage( int axis ) const
+{ 
+       return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] + 
+                                                (*globalSortingPoints)[ mPoints[1] ][axis] + 
+                                                (*globalSortingPoints)[ mPoints[2] ][axis] )/3.0);
+}
+
+bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs)
 {
-  t = GFX_REAL_MAX;
-  ntlVec3Gfx  e0 = (*mpV)[ tri->getPoints()[0] ];
-  ntlVec3Gfx  e1 = (*mpV)[ tri->getPoints()[1] ] - e0;
-  ntlVec3Gfx  e2 = (*mpV)[ tri->getPoints()[2] ] - e0;
-  ntlVec3Gfx  p  = cross( mDirection, e2 );
-  gfxReal a  = dot(e1, p);     
-  //if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return;
-  if(a < RAY_TRIANGLE_EPSILON) return; // cull backsides
-      
-  gfxReal f  = 1/a;
-  ntlVec3Gfx  s  = mOrigin - e0;
-  u  = f * dot(s, p);
-  if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return;
-      
-  ntlVec3Gfx  q  = cross( s,e1 );
-  v  = f * dot(mDirection, q);
-  if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return;
-      
-  t = f * dot(e2, q);      
+       return ( lhs.getAverage(globalSortingAxis) < 
+                                        rhs.getAverage(globalSortingAxis) );
 }
-inline void ntlRay::intersectTriangleBack(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const
+
+bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs)
 {
-  t = GFX_REAL_MAX;
-  ntlVec3Gfx  e0 = (*mpV)[ tri->getPoints()[0] ];
-  ntlVec3Gfx  e1 = (*mpV)[ tri->getPoints()[1] ] - e0;
-  ntlVec3Gfx  e2 = (*mpV)[ tri->getPoints()[2] ] - e0;
-  ntlVec3Gfx  p  = cross( mDirection, e2 );
-  gfxReal a  = dot(e1, p);     
-  //if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return;
-  if(a > -RAY_TRIANGLE_EPSILON) return; // cull frontsides
-      
-  gfxReal f  = 1/a;
-  ntlVec3Gfx  s  = mOrigin - e0;
-  u  = f * dot(s, p);
-  if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return;
-      
-  ntlVec3Gfx  q  = cross( s,e1 );
-  v  = f * dot(mDirection, q);
-  if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return;
-      
-  t = f * dot(e2, q);      
+       return ( lhs.getAverage(globalSortingAxis) > 
+                                        rhs.getAverage(globalSortingAxis) );
 }
 
 
 
+/******************************************************************************
+ *
+ * Scene object, that contains and manages all geometry objects
+ *
+ *****************************************************************************/
+
+
+
+class ntlScene
+{
+public:
+  /* CONSTRUCTORS */
+  /*! Default constructor */
+  ntlScene( ntlRenderGlobals *glob, bool del=true );
+  /*! Default destructor  */
+  ~ntlScene();
+
+       /*! Add an object to the scene */
+       inline void addGeoClass(ntlGeometryClass *geo) { 
+               mGeos.push_back( geo ); 
+               geo->setObjectId(mGeos.size());
+       }
+       /*! Add a geo object to the scene, warning - only needed for hand init */
+       inline void addGeoObject(ntlGeometryObject *geo) { mObjects.push_back( geo ); }
+
+       /*! Acces a certain object */
+       inline ntlGeometryObject *getObject(int id) { 
+               if(!mSceneBuilt) { errFatal("ntlScene::getObject","Scene not inited!", SIMWORLD_INITERROR); }
+               return mObjects[id]; }
+
+       /*! Acces object array */
+       inline vector<ntlGeometryObject*> *getObjects() { 
+               if(!mSceneBuilt) { errFatal("ntlScene::getObjects[]","Scene not inited!", SIMWORLD_INITERROR); }
+               return &mObjects; }
+
+       /*! Acces geo class array */
+       inline vector<ntlGeometryClass*> *getGeoClasses() { 
+               if(!mSceneBuilt) { errFatal("ntlScene::getGeoClasses[]","Scene not inited!", SIMWORLD_INITERROR); }
+               return &mGeos; }
+
+       /*! draw scene with opengl */
+       //void draw();
+       
+       /*! Build/first init the scene arrays */
+       void buildScene(double time, bool firstInit);
+       
+       //! Prepare the scene triangles and maps for raytracing
+       void prepareScene(double time);
+       //! Do some memory cleaning, when frame is finished
+       void cleanupScene( void );
+
+       /*! Intersect a ray with the scene triangles */
+       void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const;
+
+       /*! return a vertex */
+       ntlVec3Gfx getVertex(int index) { return mVertices[index]; } 
+
+       // for tree generation 
+       /*! return pointer to vertices vector */
+       vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; }
+       /*! return pointer to vertices vector */
+       vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; }
+       /*! return pointer to vertices vector */
+       vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; }
+
+private:
+
+       /*! Global settings */
+       ntlRenderGlobals *mpGlob;
+
+       /*! free objects? (only necessary for render scene, which  contains all) */
+       bool mSceneDel;
+
+  /*! List of geometry classes */
+  vector<ntlGeometryClass *> mGeos;
+
+  /*! List of geometry objects */
+  vector<ntlGeometryObject *> mObjects;
+
+  /*! List of triangles */
+  vector<ntlTriangle> mTriangles;
+  /*! List of vertices */
+  vector<ntlVec3Gfx>  mVertices;
+  /*! List of normals */
+  vector<ntlVec3Gfx>  mVertNormals;
+  /*! List of triangle normals */
+  vector<ntlVec3Gfx>  mTriangleNormals;
+
+       /*! Tree to store quickly intersect triangles */
+       ntlTree *mpTree;
+
+       /*! was the scene successfully built? only then getObject(i) requests are valid */
+       bool mSceneBuilt;
+
+       /*! shader/obj initializations are only done on first init */
+       bool mFirstInitDone;
+
+private:
+#ifdef WITH_CXX_GUARDEDALLOC
+       MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlScene")
+#endif
+};
 
 
 #endif