Fix various warnings with clang build, and adjust cmake clang warnings flags
[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         for(size_t i=0; i<tris.size(); i++) {
219                 ntlVec3Gfx p0 = verts[ tris[i].getPoints()[0] ];
220                 ntlVec3Gfx p1 = verts[ tris[i].getPoints()[1] ];
221                 ntlVec3Gfx p2 = verts[ tris[i].getPoints()[2] ];
222                 ntlVec3Gfx side1 = p1 - p0;
223                 ntlVec3Gfx side2 = p2 - p0;
224                 ntlVec3Gfx side3 = p1 - p2;
225                 int divs1=0, divs2=0;
226                 if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
227                 if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
228
229                 // special handling
230                 // warning, requires objmodel triangle treatment (no verts dups)
231                 if(getMeshAnimated()) {
232                         vector<ntlSetVec3f> &sverts = mcAniVerts.accessValues();
233                         for(int s=0; s<(int)sverts.size(); s++) {
234                                 p0 = sverts[s].mVerts[ tris[i].getPoints()[0] ];
235                                 p1 = sverts[s].mVerts[ tris[i].getPoints()[1] ];
236                                 p2 = sverts[s].mVerts[ tris[i].getPoints()[2] ];
237                                 side1 = p1 - p0; side2 = p2 - p0; side3 = p1 - p2;
238                                 int tdivs1=0, tdivs2=0;
239                                 if(normNoSqrt(side1) > fsTri*fsTri) { tdivs1 = (int)(norm(side1)/fsTri); }
240                                 if(normNoSqrt(side2) > fsTri*fsTri) { tdivs2 = (int)(norm(side2)/fsTri); }
241                                 if(tdivs1>divs1) divs1=tdivs1;
242                                 if(tdivs2>divs2) divs2=tdivs2;
243                         }
244                 } // */
245                 mTriangleDivs1[i] = divs1;
246                 mTriangleDivs2[i] = divs2;
247         }
248 }
249
250
251 /******************************************************************************
252  * load model from .obj file
253  *****************************************************************************/
254
255 int ntlGeometryObjModel::loadBobjModel(string filename)
256 {
257         bool haveAniSets=false;
258         vector<ntlSetVec3f> aniverts;
259         vector<ntlSetVec3f> aninorms;
260         vector<double> anitimes;
261
262         const bool debugPrint=false;
263         const bool debugPrintFull=false;
264         gzFile gzf;
265         gzf = gzopen(filename.c_str(), "rb");
266         if (!gzf) {
267                 errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to open '"<< filename <<"'...\n", SIMWORLD_INITERROR );
268                 return 1;
269         }
270
271         int numVerts;
272         if(sizeof(numVerts)!=4) {  // paranoia check
273                 errMsg("Reading GZ_BOBJ"," Invalid int size, check compiler settings: int has to be 4 byte long"); 
274                 goto gzreaderror;
275         }
276         gzread(gzf, &numVerts, sizeof(numVerts) );
277         if(numVerts<0 || numVerts>1e9) {
278                 errMsg("Reading GZ_BOBJ"," invalid num vertices "<< numVerts);
279                 goto gzreaderror;
280         }
281         mVertices.clear();
282         mVertices.resize( numVerts );
283         for(int i=0; i<numVerts; i++) {
284                 float x[3];
285                 for(int j=0; j<3; j++) {
286                         gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); 
287                 }
288                 mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]);
289                 if(debugPrintFull) errMsg("FULLV"," "<<i<<" "<< mVertices[i] );
290         }
291         if(debugPrint) errMsg("NV"," "<<numVerts<<" "<< mVertices.size() );
292
293         // should be the same as Vertices.size
294         gzread(gzf, &numVerts, sizeof(numVerts) );
295         if(numVerts<0 || numVerts>1e9) {
296                 errMsg("Reading GZ_BOBJ","invalid num normals "<< numVerts);
297                 goto gzreaderror;
298         }
299         mNormals.clear();
300         mNormals.resize( numVerts );
301         for(int i=0; i<numVerts; i++) {
302                 float n[3];
303                 for(int j=0; j<3; j++) {
304                         gzread(gzf, &(n[j]), sizeof( (n[j]) ) ); 
305                 }
306                 mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]);
307                 if(debugPrintFull) errMsg("FULLN"," "<<i<<" "<< mNormals[i] );
308         }
309         if(debugPrint) errMsg("NN"," "<<numVerts<<" "<< mNormals.size() );
310
311         int numTris;
312         gzread(gzf, &numTris, sizeof(numTris) );
313         if(numTris<0 || numTris>1e9) {
314                 errMsg("Reading GZ_BOBJ","invalid num normals "<< numTris);
315                 goto gzreaderror;
316         }
317         mTriangles.resize( 3*numTris );
318         for(int i=0; i<numTris; i++) {
319                 int tri[3];
320                 for(int j=0; j<3; j++) {
321                         gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) ); 
322                 }
323                 mTriangles[3*i+0] = tri[0];
324                 mTriangles[3*i+1] = tri[1];
325                 mTriangles[3*i+2] = tri[2];
326         }
327         if(debugPrint) errMsg("NT"," "<<numTris<<" "<< mTriangles.size() );
328
329         debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 );
330
331         // try to load animated mesh
332         aniverts.clear();
333         aninorms.clear();
334         anitimes.clear();
335         while(1) {
336                 //ntlVec3Gfx check;
337                 float x[3];
338                 float frameTime=0.;
339                 int bytesRead = 0;
340                 int numNorms2=-1, numVerts2=-1;
341                 //for(int j=0; j<3; j++) {
342                         //x[j] = 0.;
343                         //bytesRead += gzread(gzf, &(x[j]), sizeof(float) ); 
344                 //}
345                 //check = ntlVec3Gfx(x[0],x[1],x[2]);
346                 //if(debugPrint) errMsg("ANI_NV1"," "<<check<<" "<<" bytes:"<<bytesRead );
347                 bytesRead += gzread(gzf, &frameTime, sizeof(frameTime) );
348                 //if(bytesRead!=3*sizeof(float)) {
349                 if(bytesRead!=sizeof(float)) {
350                         debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' end of gzfile. ", 10 );
351                         if(anitimes.size()>0) {
352                                 // finally init channels and stop reading file
353                                 mcAniVerts = AnimChannel<ntlSetVec3f>(aniverts,anitimes);
354                                 mcAniNorms = AnimChannel<ntlSetVec3f>(aninorms,anitimes);
355                         }
356                         goto gzreaddone;
357                 }
358                 bytesRead += gzread(gzf, &numVerts2, sizeof(numVerts2) );
359                 haveAniSets=true;
360                 // continue to read new set
361                 vector<ntlVec3Gfx> vertset;
362                 vector<ntlVec3Gfx> normset;
363                 vertset.resize(numVerts);
364                 normset.resize(numVerts);
365                 //vertset[0] = check;
366                 if(debugPrintFull) errMsg("FUL1V"," "<<0<<" "<< vertset[0] );
367
368                 for(int i=0; i<numVerts; i++) { // start at one!
369                         for(int j=0; j<3; j++) {
370                                 bytesRead += gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); 
371                         }
372                         vertset[i] = ntlVec3Gfx(x[0],x[1],x[2]);
373                         if(debugPrintFull) errMsg("FUL2V"," "<<i<<" "<< vertset[i] );
374                 }
375                 if(debugPrint) errMsg("ANI_VV"," "<<numVerts<<" "<< vertset.size()<<" bytes:"<<bytesRead );
376
377                 bytesRead += gzread(gzf, &numNorms2, sizeof(numNorms2) );
378                 for(int i=0; i<numVerts; i++) {
379                         for(int j=0; j<3; j++) {
380                                 bytesRead += gzread(gzf, &(x[j]), sizeof( (x[j]) ) ); 
381                         }
382                         normset[i] = ntlVec3Gfx(x[0],x[1],x[2]);
383                         if(debugPrintFull) errMsg("FUL2N"," "<<i<<" "<< normset[i] );
384                 }
385                 if(debugPrint) errMsg("ANI_NV"," "<<numVerts<<","<<numVerts2<<","<<numNorms2<<","<< normset.size()<<" bytes:"<<bytesRead );
386
387                 // set ok
388                 if(bytesRead== (int)( (numVerts*2*3+1) *sizeof(float)+2*sizeof(int) ) ) {
389                         if(aniverts.size()==0) {
390                                 // TODO, ignore first mesh?
391                                 double anitime = (double)(frameTime-1.); // start offset!? anitimes.size();
392                                 // get for current frame entry
393                                 if(mcAniTimes.getSize()>1)  anitime = mcAniTimes.get(anitime); 
394                                 anitime = anitime*mAniTimeScale+mAniTimeOffset;
395
396                                 anitimes.push_back( anitime );
397                                 aniverts.push_back( ntlSetVec3f(mVertices) );
398                                 aninorms.push_back( ntlSetVec3f(mNormals) );
399                                 if(debugPrint) errMsg("ANI_NV","new set "<<mVertices.size()<<","<< mNormals.size()<<" time:"<<anitime );
400                         }
401                         double anitime = (double)(frameTime); //anitimes.size();
402                         // get for current frame entry
403                         if(mcAniTimes.getSize()>1)  anitime = mcAniTimes.get(anitime); 
404                         anitime = anitime*mAniTimeScale+mAniTimeOffset;
405
406                         anitimes.push_back( anitime );
407                         aniverts.push_back( ntlSetVec3f(vertset) );
408                         aninorms.push_back( ntlSetVec3f(normset) );
409                         if(debugPrint) errMsg("ANI_NV","new set "<<vertset.size()<<","<< normset.size()<<" time:"<<anitime );
410                 } else {
411                         errMsg("ntlGeometryObjModel::loadBobjModel","Malformed ani set! Aborting... ("<<bytesRead<<") ");
412                         goto gzreaddone;
413                 }
414         } // anim sets */
415
416 gzreaddone:
417
418         if(haveAniSets) { 
419                 debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' ani sets loaded: "<< mcAniVerts.accessValues().size() <<","<<mcAniNorms.accessValues().size() <<" ", 1 );
420         }
421         gzclose( gzf );
422         return 0;
423
424 gzreaderror:
425         mTriangles.clear();
426         mVertices.clear();
427         mNormals.clear();
428         gzclose( gzf );
429         errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to load '"<< filename <<"', exiting...\n", SIMWORLD_INITERROR );
430         return 1;
431 }
432
433
434 /******************************************************************************
435  * 
436  *****************************************************************************/
437 void 
438 ntlGeometryObjModel::getTriangles(double t, vector<ntlTriangle> *triangles, 
439                                                                                                                         vector<ntlVec3Gfx> *vertices, 
440                                                                                                                         vector<ntlVec3Gfx> *normals, int objectId )
441 {
442         if(!mLoaded) { // invalid type...
443                 return;
444         }
445         if(mcAniVerts.getSize()>1) { mVertices = mcAniVerts.get(t).mVerts; }
446         if(mcAniNorms.getSize()>1) { mNormals  = mcAniNorms.get(t).mVerts; }
447
448         int startvert = vertices->size();
449         vertices->resize( vertices->size() + mVertices.size() );
450         normals->resize( normals->size() + mVertices.size() );
451         for(int i=0; i<(int)mVertices.size(); i++) {
452                 (*vertices)[startvert+i] = mVertices[i];
453                 (*normals)[startvert+i] = mNormals[i];
454         }
455
456         triangles->reserve(triangles->size() + mTriangles.size()/3 );
457         for(int i=0; i<(int)mTriangles.size(); i+=3) {
458                 int trip[3];
459                 trip[0] = startvert+mTriangles[i+0];
460                 trip[1] = startvert+mTriangles[i+1];
461                 trip[2] = startvert+mTriangles[i+2];
462
463                 //sceneAddTriangle( 
464                                 //mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]], 
465                                 //mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]], 
466                                 //ntlVec3Gfx(0.0), 1 , triangles,vertices,normals ); /* normal unused */
467                 sceneAddTriangleNoVert( trip, ntlVec3Gfx(0.0), 1 , triangles ); /* normal unused */
468         }
469         objectId = -1; // remove warning
470         // bobj
471         return;
472 }
473
474
475
476
477