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