16d18c4b238bc85d56ad748b710fce686f16d3c5
[blender.git] / intern / elbeem / intern / ntl_geometrymodel.cpp
1 /******************************************************************************
2  *
3  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
4  * Copyright 2003,2004 Nils Thuerey
5  *
6  * A simple box object
7  *
8  *****************************************************************************/
9
10 #include "ntl_geometrymodel.h"
11 #include "ntl_ray.h"
12 #include "ntl_world.h"
13 #include "zlib.h"
14
15 #ifdef WIN32
16 #ifndef strncasecmp
17 #define strncasecmp(a,b,c) strcmp(a,b)
18 #endif
19 #endif // WIN32
20
21
22 /******************************************************************************
23  * Default Constructor 
24  *****************************************************************************/
25 ntlGeometryObjModel::ntlGeometryObjModel( void ) :
26         ntlGeometryObject(),
27         mvStart( 0.0 ), mvEnd( 1.0 ),
28         mLoaded( false ),
29         mTriangles(), mVertices(), mNormals(),
30         mcAniVerts(), mcAniNorms(), 
31         mcAniTimes(), mAniTimeScale(1.), mAniTimeOffset(0.),
32         mvCPSStart(-10000.), mvCPSEnd(10000.),
33         mCPSFilename(""), mCPSWidth(0.1), mCPSTimestep(1.)
34 {
35 }
36
37 /******************************************************************************
38  * Destructor
39  *****************************************************************************/
40 ntlGeometryObjModel::~ntlGeometryObjModel()
41 {
42         if(!mLoaded) {
43                 errMsg("ntlGeometryObjModel","delete obj...");
44         }
45 }
46
47
48 /*! is the mesh animated? */
49 bool ntlGeometryObjModel::getMeshAnimated() { 
50         const bool ret = (mcAniVerts.getSize()>1); 
51         //errMsg("getMeshAnimated","ret="<<ret<<", size="<<mcAniVerts.getSize() );
52         return ret;
53 }
54
55 /*****************************************************************************/
56 /* Init attributes etc. of this object */
57 /*****************************************************************************/
58 void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob) 
59 {
60         // perhaps the model is already inited from initModel below?
61         if(mLoaded==1) {
62                 // init default material
63                 searchMaterial( glob->getMaterials() );
64                 return;
65         }
66         
67         ntlGeometryObject::initialize(glob);
68         mFilename = mpAttrs->readString("filename", mFilename,"ntlGeometryObjModel", "mFilename", true);
69
70         if(mFilename == "") {
71                 errMsg("ntlGeometryObjModel::initialize","Filename not given!");
72                 return;
73         }
74
75         const char *suffix = strrchr(mFilename.c_str(), '.');
76         if (suffix) {
77                 if (!strncasecmp(suffix, ".obj", 4)) {
78                         errMsg("ntlGeometryObjModel::initialize",".obj files not supported!");
79                         return;
80                 } else if (!strncasecmp(suffix, ".gz", 3)) { 
81                         //mType = 1; // assume its .bobj.gz
82                 } else if (!strncasecmp(suffix, ".bobj", 5)) { 
83                         //mType = 1;
84                 }
85         }
86
87         if(getAttributeList()->exists("ani_times") || (!mcAniTimes.isInited()) ) {
88                 mcAniTimes = mpAttrs->readChannelFloat("ani_times");
89         }
90         mAniTimeScale = mpAttrs->readFloat("ani_timescale", mAniTimeScale,"ntlGeometryObjModel", "mAniTimeScale", false);
91         mAniTimeOffset = mpAttrs->readFloat("ani_timeoffset", mAniTimeOffset,"ntlGeometryObjModel", "mAniTimeOffset", false);
92
93         mCPSWidth = mpAttrs->readFloat("cps_width", mCPSWidth,"ntlGeometryObjModel", "mCPSWidth", false);
94         mCPSTimestep = mpAttrs->readFloat("cps_timestep", mCPSTimestep,"ntlGeometryObjModel", "mCPSTimestep", false);
95         mvCPSStart = vec2G( mpAttrs->readVec3d("cps_start", vec2D(mvCPSStart),"ntlGeometryObjModel", "mvCPSStart", false));
96         mvCPSEnd = vec2G( mpAttrs->readVec3d("cps_end", vec2D(mvCPSEnd),"ntlGeometryObjModel", "mvCPSEnd", false));
97
98         // continue with standard obj
99         if(loadBobjModel(mFilename)==0) mLoaded=1;
100         if(!mLoaded) {
101                 debMsgStd("ntlGeometryObjModel",DM_WARNING,"Unable to load object file '"<<mFilename<<"' !", 0);
102         }
103         if(getMeshAnimated()) {
104                 this->mIsAnimated = true;
105         }
106 }
107
108 /******************************************************************************
109  * init model from given vertex and triangle arrays 
110  *****************************************************************************/
111
112 int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles,
113                 int channelSize, float *channelVertices)
114 {
115         mVertices.clear();
116         mVertices.resize( numVertices );
117         mNormals.resize( numVertices );
118         for(int i=0; i<numVertices; i++) {
119                 mVertices[i] = ntlVec3Gfx(vertices[i*3+0],vertices[i*3+1],vertices[i*3+2]);
120                 mNormals[i] = ntlVec3Gfx(1.0); // unused, set to !=0.0
121         }
122
123         mTriangles.clear();
124         mTriangles.resize( 3*numTriangles );
125         int triangleErrs=0;
126         for(int i=0; i<numTriangles; i++) {
127                 for(int j=0;j<3;j++) {
128                         mTriangles[3*i+j] = triangles[i*3+j];
129                         if(mTriangles[3*i+j]<0) { mTriangles[3*i+j]=0; triangleErrs++; }
130                         if(mTriangles[3*i+j]>=numVertices) { mTriangles[3*i+j]=0; triangleErrs++; }
131                 }
132         }
133         if(triangleErrs>0) {
134                 errMsg("ntlGeometryObjModel::initModel","Triangle errors occurred ("<<triangleErrs<<")!");
135         }
136
137         //fprintf(stderr,"initModel DEBUG %d \n",channelSize);
138         debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Csize:"<<channelSize<<", Cvert:"<<(long)(channelVertices) ,10);
139         if(channelVertices && (channelSize>0)) {
140                 vector<ntlSetVec3f> aniverts;
141                 vector<ntlSetVec3f> aninorms;
142                 vector<double> anitimes;
143                 aniverts.clear();
144                 aninorms.clear();
145                 anitimes.clear();
146                 for(int frame=0; frame<channelSize; frame++) {
147                         ntlSetVec3f averts; averts.mVerts.clear();
148                         ntlSetVec3f anorms; averts.mVerts.clear();
149                         int setsize = (3*numVertices+1);
150
151                         ntlVec3Gfx p(0.),n(1.);
152                         for(int i=0; i<numVertices; i++) {
153                                 for(int j=0; j<3; j++) p[j] = channelVertices[frame*setsize+ 3*i +j];
154                                 averts.mVerts.push_back(p);
155                                 anorms.mVerts.push_back(p);
156                                 //debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Frame:"<<frame<<",i:"<<i<<" "<<p,10);
157                         }
158                         if( ((int)averts.mVerts.size()==numVertices) && 
159                                 ((int)anorms.mVerts.size()==numVertices) ) {
160                                 aniverts.push_back(averts);
161                                 aninorms.push_back(anorms);
162                                 double time = (double)channelVertices[frame*setsize+ setsize-1];
163                                 anitimes.push_back(time);
164                         } else {
165                                 errMsg("ntlGeometryObjModel::initModel","Invalid mesh, obj="<<this->getName()<<" frame="<<frame<<" verts="<<averts.mVerts.size()<<"/"<<numVertices<<". Skipping...");
166                         }
167                         //debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Frame:"<<frame<<" at t="<<time,10);
168                 }
169
170                 mcAniVerts = AnimChannel<ntlSetVec3f>(aniverts,anitimes);
171                 mcAniNorms = AnimChannel<ntlSetVec3f>(aninorms,anitimes);
172                 debMsgStd("ntlGeometryObjModel::initModel",DM_MSG, "Ani sets inited: "<< mcAniVerts.accessValues().size() <<","<<mcAniNorms.accessValues().size() <<" ", 1 );
173         }
174         if(getMeshAnimated()) {
175                 this->mIsAnimated = true;
176         }
177
178         // inited, no need to parse attribs etc.
179         mLoaded = 1;
180         return 0;
181 }
182
183 /*! init triangle divisions */
184 void ntlGeometryObjModel::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri) {
185         // warning - copied from geomobj calc!
186         errMsg("ntlGeometryObjModel","calcTriangleDivs special!");
187         mTriangleDivs1.resize( tris.size() );
188         mTriangleDivs2.resize( tris.size() );
189         mTriangleDivs3.resize( tris.size() );
190         for(size_t i=0; i<tris.size(); i++) {
191                 ntlVec3Gfx p0 = verts[ tris[i].getPoints()[0] ];
192                 ntlVec3Gfx p1 = verts[ tris[i].getPoints()[1] ];
193                 ntlVec3Gfx p2 = verts[ tris[i].getPoints()[2] ];
194                 ntlVec3Gfx side1 = p1 - p0;
195                 ntlVec3Gfx side2 = p2 - p0;
196                 ntlVec3Gfx side3 = p1 - p2;
197                 int divs1=0, divs2=0, divs3=0;
198                 if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
199                 if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
200                 //if(normNoSqrt(side3) > fsTri*fsTri) { divs3 = (int)(norm(side3)/fsTri); }
201
202                 // special handling
203                 // warning, requires objmodel triangle treatment (no verts dups)
204                 if(getMeshAnimated()) {
205                         vector<ntlSetVec3f> &sverts = mcAniVerts.accessValues();
206                         for(int s=0; s<(int)sverts.size(); s++) {
207                                 p0 = sverts[s].mVerts[ tris[i].getPoints()[0] ];
208                                 p1 = sverts[s].mVerts[ tris[i].getPoints()[1] ];
209                                 p2 = sverts[s].mVerts[ tris[i].getPoints()[2] ];
210                                 side1 = p1 - p0; side2 = p2 - p0; side3 = p1 - p2;
211                                 int tdivs1=0, tdivs2=0, tdivs3=0;
212                                 if(normNoSqrt(side1) > fsTri*fsTri) { tdivs1 = (int)(norm(side1)/fsTri); }
213                                 if(normNoSqrt(side2) > fsTri*fsTri) { tdivs2 = (int)(norm(side2)/fsTri); }
214                                 if(tdivs1>divs1) divs1=tdivs1;
215                                 if(tdivs2>divs2) divs2=tdivs2;
216                                 if(tdivs3>divs3) divs3=tdivs3;
217                         }
218                 } // */
219                 mTriangleDivs1[i] = divs1;
220                 mTriangleDivs2[i] = divs2;
221                 mTriangleDivs3[i] = divs3;
222         }
223 }
224
225
226 /******************************************************************************
227  * load model from .obj file
228  *****************************************************************************/
229
230 int ntlGeometryObjModel::loadBobjModel(string filename)
231 {
232         bool haveAniSets=false;
233         vector<ntlSetVec3f> aniverts;
234         vector<ntlSetVec3f> aninorms;
235         vector<double> anitimes;
236
237         const bool debugPrint=false;
238         const bool debugPrintFull=false;
239         gzFile gzf;
240         gzf = gzopen(filename.c_str(), "rb");
241         if (!gzf) {
242                 errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to open '"<< filename <<"'...\n", SIMWORLD_INITERROR );
243                 return 1;
244         }
245
246         int numVerts;
247         if(sizeof(numVerts)!=4) {  // paranoia check
248                 errMsg("Reading GZ_BOBJ"," Invalid int size, check compiler settings: int has to be 4 byte long"); 
249                 goto gzreaderror;
250         }
251         gzread(gzf, &numVerts, sizeof(numVerts) );
252         if(numVerts<0 || numVerts>1e9) {
253                 errMsg("Reading GZ_BOBJ"," invalid num vertices "<< numVerts);
254                 goto gzreaderror;
255         }
256         mVertices.clear();
257         mVertices.resize( numVerts );
258         for(int i=0; i<numVerts; i++) {
259                 float x[3];
260                 for(int j=0; j<3; j++) {
261                         gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); 
262                 }
263                 mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]);
264                 if(debugPrintFull) errMsg("FULLV"," "<<i<<" "<< mVertices[i] );
265         }
266         if(debugPrint) errMsg("NV"," "<<numVerts<<" "<< mVertices.size() );
267
268         // should be the same as Vertices.size
269         gzread(gzf, &numVerts, sizeof(numVerts) );
270         if(numVerts<0 || numVerts>1e9) {
271                 errMsg("Reading GZ_BOBJ","invalid num normals "<< numVerts);
272                 goto gzreaderror;
273         }
274         mNormals.clear();
275         mNormals.resize( numVerts );
276         for(int i=0; i<numVerts; i++) {
277                 float n[3];
278                 for(int j=0; j<3; j++) {
279                         gzread(gzf, &(n[j]), sizeof( (n[j]) ) ); 
280                 }
281                 mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]);
282                 if(debugPrintFull) errMsg("FULLN"," "<<i<<" "<< mNormals[i] );
283         }
284         if(debugPrint) errMsg("NN"," "<<numVerts<<" "<< mNormals.size() );
285
286         int numTris;
287         gzread(gzf, &numTris, sizeof(numTris) );
288         if(numTris<0 || numTris>1e9) {
289                 errMsg("Reading GZ_BOBJ","invalid num normals "<< numTris);
290                 goto gzreaderror;
291         }
292         mTriangles.resize( 3*numTris );
293         for(int i=0; i<numTris; i++) {
294                 int tri[3];
295                 for(int j=0; j<3; j++) {
296                         gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) ); 
297                 }
298                 mTriangles[3*i+0] = tri[0];
299                 mTriangles[3*i+1] = tri[1];
300                 mTriangles[3*i+2] = tri[2];
301         }
302         if(debugPrint) errMsg("NT"," "<<numTris<<" "<< mTriangles.size() );
303
304         debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 );
305
306         // try to load animated mesh
307         aniverts.clear();
308         aninorms.clear();
309         anitimes.clear();
310         while(1) {
311                 //ntlVec3Gfx check;
312                 float x[3];
313                 float frameTime=0.;
314                 int bytesRead = 0;
315                 int numNorms2=-1, numVerts2=-1;
316                 //for(int j=0; j<3; j++) {
317                         //x[j] = 0.;
318                         //bytesRead += gzread(gzf, &(x[j]), sizeof(float) ); 
319                 //}
320                 //check = ntlVec3Gfx(x[0],x[1],x[2]);
321                 //if(debugPrint) errMsg("ANI_NV1"," "<<check<<" "<<" bytes:"<<bytesRead );
322                 bytesRead += gzread(gzf, &frameTime, sizeof(frameTime) );
323                 //if(bytesRead!=3*sizeof(float)) {
324                 if(bytesRead!=sizeof(float)) {
325                         debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' no ani sets. ", 10 );
326                         if(anitimes.size()>0) {
327                                 // finally init channels and stop reading file
328                                 mcAniVerts = AnimChannel<ntlSetVec3f>(aniverts,anitimes);
329                                 mcAniNorms = AnimChannel<ntlSetVec3f>(aninorms,anitimes);
330                         }
331                         goto gzreaddone;
332                 }
333                 bytesRead += gzread(gzf, &numVerts2, sizeof(numVerts2) );
334                 haveAniSets=true;
335                 // continue to read new set
336                 vector<ntlVec3Gfx> vertset;
337                 vector<ntlVec3Gfx> normset;
338                 vertset.resize(numVerts);
339                 normset.resize(numVerts);
340                 //vertset[0] = check;
341                 if(debugPrintFull) errMsg("FUL1V"," "<<0<<" "<< vertset[0] );
342
343                 for(int i=0; i<numVerts; i++) { // start at one!
344                         for(int j=0; j<3; j++) {
345                                 bytesRead += gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); 
346                         }
347                         vertset[i] = ntlVec3Gfx(x[0],x[1],x[2]);
348                         if(debugPrintFull) errMsg("FUL2V"," "<<i<<" "<< vertset[i] );
349                 }
350                 if(debugPrint) errMsg("ANI_VV"," "<<numVerts<<" "<< vertset.size()<<" bytes:"<<bytesRead );
351
352                 bytesRead += gzread(gzf, &numNorms2, sizeof(numNorms2) );
353                 for(int i=0; i<numVerts; i++) {
354                         for(int j=0; j<3; j++) {
355                                 bytesRead += gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); 
356                         }
357                         normset[i] = ntlVec3Gfx(x[0],x[1],x[2]);
358                         if(debugPrintFull) errMsg("FUL2N"," "<<i<<" "<< normset[i] );
359                 }
360                 if(debugPrint) errMsg("ANI_NV"," "<<numVerts<<","<<numVerts2<<","<<numNorms2<<","<< normset.size()<<" bytes:"<<bytesRead );
361
362                 // set ok
363                 if(bytesRead== (int)( (numVerts*2*3+1) *sizeof(float)+2*sizeof(int) ) ) {
364                         if(aniverts.size()==0) {
365                                 // TODO, ignore first mesh?
366                                 double anitime = (double)(frameTime-1.); // start offset!? anitimes.size();
367                                 // get for current frame entry
368                                 if(mcAniTimes.getSize()>1)  anitime = mcAniTimes.get(anitime); 
369                                 anitime = anitime*mAniTimeScale+mAniTimeOffset;
370
371                                 anitimes.push_back( anitime );
372                                 aniverts.push_back( ntlSetVec3f(mVertices) );
373                                 aninorms.push_back( ntlSetVec3f(mNormals) );
374                                 if(debugPrint) errMsg("ANI_NV","new set "<<mVertices.size()<<","<< mNormals.size()<<" time:"<<anitime );
375                         }
376                         double anitime = (double)(frameTime); //anitimes.size();
377                         // get for current frame entry
378                         if(mcAniTimes.getSize()>1)  anitime = mcAniTimes.get(anitime); 
379                         anitime = anitime*mAniTimeScale+mAniTimeOffset;
380
381                         anitimes.push_back( anitime );
382                         aniverts.push_back( ntlSetVec3f(vertset) );
383                         aninorms.push_back( ntlSetVec3f(normset) );
384                         if(debugPrint) errMsg("ANI_NV","new set "<<vertset.size()<<","<< normset.size()<<" time:"<<anitime );
385                 } else {
386                         errMsg("ntlGeometryObjModel::loadBobjModel","Malformed ani set! Aborting... ("<<bytesRead<<") ");
387                         goto gzreaddone;
388                 }
389         } // anim sets */
390
391 gzreaddone:
392
393         if(haveAniSets) { 
394                 debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' ani sets loaded: "<< mcAniVerts.accessValues().size() <<","<<mcAniNorms.accessValues().size() <<" ", 1 );
395         }
396         gzclose( gzf );
397         return 0;
398
399 gzreaderror:
400         mTriangles.clear();
401         mVertices.clear();
402         mNormals.clear();
403         gzclose( gzf );
404         errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to load '"<< filename <<"', exiting...\n", SIMWORLD_INITERROR );
405         return 1;
406 }
407
408
409 /******************************************************************************
410  * 
411  *****************************************************************************/
412 void 
413 ntlGeometryObjModel::getTriangles(double t, vector<ntlTriangle> *triangles, 
414                                                                                                                         vector<ntlVec3Gfx> *vertices, 
415                                                                                                                         vector<ntlVec3Gfx> *normals, int objectId )
416 {
417         if(!mLoaded) { // invalid type...
418                 return;
419         }
420         if(mcAniVerts.getSize()>1) { mVertices = mcAniVerts.get(t).mVerts; }
421         if(mcAniNorms.getSize()>1) { mNormals  = mcAniNorms.get(t).mVerts; }
422
423         int startvert = vertices->size();
424         vertices->resize( vertices->size() + mVertices.size() );
425         normals->resize( normals->size() + mVertices.size() );
426         for(int i=0; i<(int)mVertices.size(); i++) {
427                 (*vertices)[startvert+i] = mVertices[i];
428                 (*normals)[startvert+i] = mNormals[i];
429         }
430
431         triangles->reserve(triangles->size() + mTriangles.size() );
432         for(int i=0; i<(int)mTriangles.size(); i+=3) {
433                 int trip[3];
434                 trip[0] = startvert+mTriangles[i+0];
435                 trip[1] = startvert+mTriangles[i+1];
436                 trip[2] = startvert+mTriangles[i+2];
437
438                 //sceneAddTriangle( 
439                                 //mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]], 
440                                 //mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]], 
441                                 //ntlVec3Gfx(0.0), 1 , triangles,vertices,normals ); /* normal unused */
442                 sceneAddTriangleNoVert( trip, ntlVec3Gfx(0.0), 1 , triangles ); /* normal unused */
443         }
444         objectId = -1; // remove warning
445         // bobj
446         return;
447 }
448
449
450
451
452