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