be78db9b2937c2618422b44e3d1f78d0fe0bad94
[blender.git] / intern / elbeem / intern / isosurface.h
1 /** \file elbeem/intern/isosurface.h
2  *  \ingroup elbeem
3  */
4 /******************************************************************************
5  *
6  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
7  * Copyright 2003-2006 Nils Thuerey
8  *
9  * Marching Cubes "displayer"
10  *
11  *****************************************************************************/
12
13 #ifndef ISOSURFACE_H
14
15 #include "ntl_geometryobject.h"
16 #include "ntl_bsptree.h"
17
18 #define ISO_STRICT_DEBUG 0
19 #define ISOSTRICT_EXIT *((int *)0)=0;
20
21 /* access some 3d array */
22 #define ISOLEVEL_INDEX(ii,ij,ik) ((mSizex*mSizey*(ik))+(mSizex*(ij))+((ii)))
23
24 class ParticleTracer;
25
26 /* struct for a small cube in the scalar field */
27 typedef struct {
28   ntlVec3Gfx   pos[8];
29   double  value[8];
30   int i,j,k;
31 } IsoLevelCube;
32
33
34 typedef struct {
35   ntlVec3Gfx v; // vertex
36   ntlVec3Gfx n; // vertex normal
37 } IsoLevelVertex;
38
39 //! class to triangulate a scalar field, e.g. for
40 // the fluid surface, templated by scalar field access object 
41 class IsoSurface : 
42         public ntlGeometryObject //, public S
43 {
44
45         public:
46
47                 /*! Constructor */
48                 IsoSurface(double iso);
49                 /*! Destructor */
50                 virtual ~IsoSurface();
51
52                 /*! Init ararys etc. */
53                 virtual void initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx extent);
54
55                 /*! Reset all values */
56                 void resetAll(gfxReal val);
57
58                 /*! triangulate the scalar field given by pointer*/
59                 void triangulate( void );
60
61                 /*! set particle pointer */
62                 void setParticles(ParticleTracer *pnt,float psize){ mpIsoParts = pnt; mPartSize=psize; };
63                 /*! set # of subdivisions, this has to be done before init! */
64                 void setSubdivs(int s) { 
65                         if(mInitDone) errFatal("IsoSurface::setSubdivs","Changing subdivs after init!", SIMWORLD_INITERROR);
66                         if(s<1) s=1; if(s>10) s=10;
67                         mSubdivs = s; }
68                 int  getSubdivs() { return mSubdivs;}
69                 /*! set full edge settings, this has to be done before init! */
70                 void setUseFulledgeArrays(bool set) { 
71                         if(mInitDone) errFatal("IsoSurface::setUseFulledgeArrays","Changing usefulledge after init!", SIMWORLD_INITERROR);
72                         mUseFullEdgeArrays = set;}
73
74         protected:
75
76                 /* variables ... */
77
78                 //! size
79                 int mSizex, mSizey, mSizez;
80
81                 //! data pointer
82                 float *mpData;
83
84                 //! Level of the iso surface 
85                 double mIsoValue;
86
87                 //! Store all the triangles vertices 
88                 vector<IsoLevelVertex> mPoints;
89
90                 //! use full arrays? (not for farfield)
91                 bool mUseFullEdgeArrays;
92                 //! Store indices of calculated points along the cubie edges 
93                 int *mpEdgeVerticesX;
94                 int *mpEdgeVerticesY;
95                 int *mpEdgeVerticesZ;
96                 int mEdgeArSize;
97
98
99                 //! vector for all the triangles (stored as 3 indices) 
100                 vector<unsigned int> mIndices;
101
102                 //! start and end vectors for the triangulation region to create triangles in 
103                 ntlVec3Gfx mStart, mEnd;
104
105                 //! normalized domain extent from parametrizer/visualizer 
106                 ntlVec3Gfx mDomainExtent;
107
108                 //! initialized? 
109                 bool mInitDone;
110
111                 //! amount of surface smoothing
112                 float mSmoothSurface;
113                 //! amount of normal smoothing
114                 float mSmoothNormals;
115                 
116                 //! grid data
117                 vector<int> mAcrossEdge;
118                 vector< vector<int> > mAdjacentFaces;
119
120                 //! cutoff border area
121                 int mCutoff;
122                 //! cutoff heigh values
123                 int *mCutArray;
124                 //! particle pointer 
125                 ParticleTracer *mpIsoParts;
126                 //! particle size
127                 float mPartSize;
128                 //! no of subdivisions
129                 int mSubdivs;
130                 
131                 //! trimesh vars
132                 vector<int> flags;
133                 int mFlagCnt;
134                 vector<ntlVec3Gfx> cornerareas;
135                 vector<float> pointareas;
136                 vector< vector<int> > neighbors;
137
138         public:
139                 // miscelleanous access functions 
140
141                 //! set geometry start (for renderer) 
142                 void setStart(ntlVec3Gfx set) { mStart = set; };
143                 ntlVec3Gfx getStart() { return mStart; };
144                 //! set geometry end (for renderer) 
145                 void setEnd(ntlVec3Gfx set) { mEnd = set; };
146                 ntlVec3Gfx getEnd() { return mEnd; };
147                 //! set iso level value for surface reconstruction 
148                 inline void setIsolevel(double set) { mIsoValue = set; };
149                 //! set loop subdiv num
150                 inline void setSmoothSurface(float set) { mSmoothSurface = set; };
151                 inline void setSmoothNormals(float set) { mSmoothNormals = set; };
152                 inline float getSmoothSurface() { return mSmoothSurface; }
153                 inline float getSmoothNormals() { return mSmoothNormals; }
154
155                 // geometry object functions 
156                 virtual void getTriangles(double t, vector<ntlTriangle> *triangles, 
157                                 vector<ntlVec3Gfx> *vertices, 
158                                 vector<ntlVec3Gfx> *normals, int objectId );
159
160                 //! for easy GUI detection get start of axis aligned bounding box, return NULL of no BB 
161                 virtual inline ntlVec3Gfx *getBBStart()         { return &mStart; }
162                 virtual inline ntlVec3Gfx *getBBEnd()           { return &mEnd; }
163
164                 //! access data array
165                 inline float* getData(){ return mpData; }
166                 inline float* getData(int ii, int jj, int kk){ 
167 #if ISO_STRICT_DEBUG==1
168                         if(ii<0){ errMsg("IsoStrict"," invX- |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
169                         if(jj<0){ errMsg("IsoStrict"," invY- |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
170                         if(kk<0){ errMsg("IsoStrict"," invZ- |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
171                         if(ii>mSizex-1){ errMsg("IsoStrict"," invX+ |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
172                         if(jj>mSizey-1){ errMsg("IsoStrict"," invY+ |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
173                         if(kk>mSizez-1){ errMsg("IsoStrict"," invZ+ |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
174                         return mpData + ISOLEVEL_INDEX(ii, jj, kk); 
175 #else //ISO_STRICT_DEBUG==1
176                         return mpData + ISOLEVEL_INDEX(ii, jj, kk); 
177 #endif
178                 }
179                 inline float* lbmGetData(int ii, int jj, int kk){ 
180 #if ISO_STRICT_DEBUG==1
181                         ii++; jj++; kk++;
182                         if(ii<0){ errMsg("IsoStrict"," invX- |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
183                         if(jj<0){ errMsg("IsoStrict"," invY- |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
184                         if(kk<0){ errMsg("IsoStrict"," invZ- |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
185                         if(ii>mSizex-1){ errMsg("IsoStrict"," invX+ |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
186                         if(jj>mSizey-1){ errMsg("IsoStrict"," invY+ |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
187                         if(kk>mSizez-1){ errMsg("IsoStrict"," invZ+ |"<<ii<<","<<jj<<","<<kk); ISOSTRICT_EXIT; }
188                         return mpData + ISOLEVEL_INDEX(ii, jj, kk); 
189 #else //ISO_STRICT_DEBUG==1
190                         return mpData + ISOLEVEL_INDEX(ii+1,jj+1,kk+1); 
191 #endif
192                 }
193                 //! set cut off border
194                 inline void setCutoff(int set) { mCutoff = set; };
195                 //! set cut off border
196                 inline void setCutArray(int *set) { mCutArray = set; };
197
198                 //! OpenGL viz "interface"
199                 unsigned int getIsoVertexCount() {
200                         return mPoints.size();
201                 }
202                 unsigned int getIsoIndexCount() {
203                         return mIndices.size();
204                 }
205                 char* getIsoVertexArray() {
206                         return (char *) &(mPoints[0]);
207                 }
208                 unsigned int *getIsoIndexArray() {
209                         return &(mIndices[0]);
210                 }
211                 
212                 // surface smoothing functions
213                 void setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc);
214                 void smoothSurface(float val, bool smoothNorm);
215                 void smoothNormals(float val);
216                 void computeNormals();
217
218         protected:
219
220                 //! compute normal
221                 inline ntlVec3Gfx getNormal(int i, int j,int k);
222                 //! smoothing helper function
223                 bool diffuseVertexField(ntlVec3Gfx *field, int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt);
224                 vector<int> mDboundary;
225                 float mSCrad1, mSCrad2;
226                 ntlVec3Gfx mSCcenter;
227 };
228
229
230 #define ISOSURFACE_H
231 #endif
232
233