blender/intern/elbeem/intern/ntl_ray.h

439 lines
13 KiB
C++

/** \file elbeem/intern/ntl_ray.h
* \ingroup elbeem
*/
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003-2006 Nils Thuerey
*
* ray class
*
*****************************************************************************/
#ifndef NTL_RAY_H
#define NTL_RAY_H
#include <sstream>
#include "ntl_vector3dim.h"
#include "ntl_lighting.h"
#include "ntl_geometryobject.h"
#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
class ntlIntersection {
public:
ntlIntersection() :
distance(-1.0), normal(0.0),
ray(NULL), tri(NULL), flags(0) { };
gfxReal distance;
ntlVec3Gfx normal;
ntlRay *ray;
ntlTriangle *tri;
char flags;
private:
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("ELBEEM:ntlIntersection")
#endif
};
//! the main ray class
class ntlRay
{
public:
// CONSTRUCTORS
//! Initialize ray memebers, prints error message
ntlRay();
//! Copy constructor, copy all members
ntlRay(const ntlRay &r);
//! Explicitly init member variables with global render object
ntlRay(const ntlVec3Gfx &o, const ntlVec3Gfx &d, unsigned int i, gfxReal contrib, ntlRenderGlobals *glob);
//! Destructor
~ntlRay();
//! Set the refraction flag for refracted rays
inline void setRefracted(unsigned char set) { mIsRefracted = set; }
inline void setReflected(unsigned char set) { mIsReflected = set; }
//! main ray recursion function
/*!
* First get closest object intersection, return background color if nothing
* was hit, else calculate shading and reflection components
* and return mixed color */
const ntlColor shade() /*const*/;
/*! Trace a photon through the scene */
void tracePhoton(ntlColor) const;
//! intersect ray with AABB
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
inline void intersectTriangleBack(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
// access methods
//! Returns the ray origin
inline ntlVec3Gfx getOrigin() const { return ntlVec3Gfx(mOrigin); }
//! Returns the ray direction
inline ntlVec3Gfx getDirection() const { return ntlVec3Gfx(mDirection); }
/*! Returns the ray relfection normal */
inline ntlVec3Gfx getNormal() const { return ntlVec3Gfx(mvNormal); }
//! Is this ray refracted?
inline unsigned char getRefracted() const { return mIsRefracted; }
inline unsigned char getReflected() const { return mIsReflected; }
/*! Get position along ray */
inline ntlVec3Gfx getPositionAt(gfxReal t) const { return (mOrigin+(mDirection*t)); }
/*! Get render globals pointer of this ray */
inline ntlRenderGlobals *getRenderglobals( void ) const { return mpGlob; }
/*! get this ray's ID */
inline int getID( void ) const { return mID; }
/*! Set origin of this ray */
inline void setOrigin(ntlVec3Gfx set) { mOrigin = set; }
/*! Set direction of this ray */
inline void setDirection(ntlVec3Gfx set) { mDirection = set; }
/*! Set normal of this ray */
inline void setNormal(ntlVec3Gfx set) { mvNormal = set; }
protected:
/* Calulates the Lambertian and Specular color for
* the given reflection and returns it */
const ntlColor getShadedColor(ntlLightObject *light, const ntlRay &reflectedray,
const ntlVec3Gfx &normal, ntlMaterial *surf) const;
private:
/*! Origin of ray */
ntlVec3Gfx mOrigin;
/*! Normalized direction vector of ray */
ntlVec3Gfx mDirection;
/*! For reflected/refracted rays, the normal is stored here */
ntlVec3Gfx mvNormal;
/*! recursion depth */
unsigned int mDepth;
/*! How much does this ray contribute to the surface color? abort if too small */
gfxReal mContribution;
/*! Global rendering settings */
ntlRenderGlobals *mpGlob;
/*! If this ray is a refracted one, this flag has to be set
* This is necessary to for example also give the background color
* to refracted rays. Otherwise things may look strange...
*/
unsigned char mIsRefracted;
unsigned char mIsReflected;
/*! 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)
class ntlTriangle
{
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;
}
/******************************************************************************
* 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)
{
return ( lhs.getAverage(globalSortingAxis) <
rhs.getAverage(globalSortingAxis) );
}
bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs)
{
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