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