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