Cleanup: remove redundant doxygen \file argument
[blender.git] / intern / elbeem / intern / ntl_blenderdumper.cpp
1 /** \file \ingroup elbeem
2  */
3 /******************************************************************************
4  *
5  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
6  * Copyright 2003-2006 Nils Thuerey
7  *
8  * Replaces std. raytracer, and only dumps time dep. objects to disc
9  *
10  *****************************************************************************/
11
12 #include <fstream>
13 #include <sys/types.h>
14
15 #include "utilities.h"
16 #include "ntl_matrices.h"
17 #include "ntl_blenderdumper.h"
18 #include "ntl_world.h"
19 #include "solver_interface.h"
20 #include "globals.h"
21
22 #include <zlib.h>
23
24 #ifdef LBM_GZIP_OVERRIDE_H
25 #  include LBM_GZIP_OVERRIDE_H
26 #else
27 #  define LBM_GZIP_OPEN_FN(a, b) gzopen(a, b)
28 #endif
29
30 /******************************************************************************
31  * Constructor
32  *****************************************************************************/
33 ntlBlenderDumper::ntlBlenderDumper() : ntlWorld()
34 {
35         // same as normal constructor here
36 }
37 ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) :
38         ntlWorld(filename,commandlineMode)
39 {
40         // init world
41 }
42
43
44
45 /******************************************************************************
46  * Destructor
47  *****************************************************************************/
48 ntlBlenderDumper::~ntlBlenderDumper()
49 {
50         debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10);
51 }
52
53 /******************************************************************************
54  * Only dump time dep. objects to file
55  *****************************************************************************/
56 int ntlBlenderDumper::renderScene( void )
57 {
58         char nrStr[5];                                                          /* nr conversion */
59   ntlRenderGlobals *glob = mpGlob;
60   ntlScene *scene = mpGlob->getSimScene();
61         bool debugOut = false;
62         bool debugRender = false;
63 #if ELBEEM_PLUGIN==1
64         debugOut = false;
65 #endif // ELBEEM_PLUGIN==1
66
67         vector<string> gmName;   // gm names
68         vector<string> gmMat;    // materials for gm
69         int numGMs = 0;                                  // no. of .obj models created
70
71         if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Dumping geometry data", 1);
72   long startTime = getTime();
73         snprintf(nrStr, 5, "%04d", glob->getAniCount() );
74
75   // local scene vars
76   vector<ntlTriangle> Triangles;
77   vector<ntlVec3Gfx>  Vertices;
78   vector<ntlVec3Gfx>  VertNormals;
79
80         // check geo objects
81         int idCnt = 0;          // give IDs to objects
82         for (vector<ntlGeometryClass*>::iterator iter = scene->getGeoClasses()->begin();
83                         iter != scene->getGeoClasses()->end(); iter++) {
84                 if(!(*iter)->getVisible()) continue;
85                 int tid = (*iter)->getTypeId();
86
87                 if(tid & GEOCLASSTID_OBJECT) {
88                         // normal geom. objects -> ignore
89                 }
90                 if(tid & GEOCLASSTID_SHADER) {
91                         ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter);
92                         string outname = geoshad->getOutFilename();
93                         if(outname.length()<1) outname = mpGlob->getOutFilename();
94                         geoshad->notifyShaderOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname);
95
96                         for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
97                                         siter != geoshad->getObjectsEnd();
98                                         siter++) {
99                                 if(debugOut) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 8);
100
101                                 (*siter)->notifyOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname, this->mSimulationTime);
102                                 bool doDump = false;
103                                 bool isPreview = false;
104                                 // only dump final&preview surface meshes
105                                 if( (*siter)->getName().find( "final" ) != string::npos) {
106                                         doDump = true;
107                                 } else if( (*siter)->getName().find( "preview" ) != string::npos) {
108                                         doDump = true;
109                                         isPreview = true;
110                                 }
111                                 if(!doDump) continue;
112
113                                 // dont quit, some objects need notifyOfDump call
114                                 if((glob_mpactive) && (glob_mpindex>0)) {
115                                         continue; //return 0;
116                                 }
117                                 
118                                 // only dump geo shader objects
119                                 Triangles.clear();
120                                 Vertices.clear();
121                                 VertNormals.clear();
122                                 (*siter)->initialize( mpGlob );
123                                 (*siter)->getTriangles(this->mSimulationTime, &Triangles, &Vertices, &VertNormals, idCnt);
124                                 idCnt ++;
125                                 
126                                 // WARNING - this is dirty, but simobjs are the only geoshaders right now
127                                 SimulationObject *sim = (SimulationObject *)geoshad;
128                                 LbmSolverInterface *lbm = sim->getSolver();
129
130
131                                 // always dump mesh, even empty ones...
132
133                                 // dump to binary file
134                                 std::ostringstream boutfilename("");
135                                 //boutfilename << ecrpath.str() << outname <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj";
136                                 boutfilename << outname <<"_"<< (*siter)->getName() <<"_" << nrStr;
137                                 if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName() 
138                                                 <<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<<
139                                                 " to "<<boutfilename.str() , 7);
140                                 gzFile gzf;
141
142                                 // output velocities if desired
143                                 if((!isPreview) && (lbm->getDumpVelocities())) {
144                                         std::ostringstream bvelfilename;
145                                         bvelfilename << boutfilename.str();
146                                         bvelfilename << ".bvel.gz";
147                                         /* wraps gzopen */
148                                         gzf = LBM_GZIP_OPEN_FN(bvelfilename.str().c_str(), "wb9");
149                                         if(gzf) {
150                                                 int numVerts;
151                                                 if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
152                                                 numVerts = Vertices.size();
153                                                 gzwrite(gzf, &numVerts, sizeof(numVerts));
154                                                 for(size_t i=0; i<Vertices.size(); i++) {
155                                                         // returns smoothed velocity, scaled by frame time
156                                                         ntlVec3Gfx v = lbm->getVelocityAt( Vertices[i][0], Vertices[i][1], Vertices[i][2] );
157                                                         // translation not necessary, test rotation & scaling?
158                                                         for(int j=0; j<3; j++) {
159                                                                 float vertp = v[j];
160                                                                 //if(i<20) errMsg("ntlBlenderDumper","DUMP_VEL final "<<i<<" = "<<v);
161                                                                 gzwrite(gzf, &vertp, sizeof(vertp)); }
162                                                 }
163                                                 gzclose( gzf );
164                                         }
165                                 }
166
167                                 // compress all bobj's 
168                                 boutfilename << ".bobj.gz";
169                                 /* wraps gzopen */
170                                 gzf = LBM_GZIP_OPEN_FN(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes!
171                                 if (!gzf) {
172                                         errMsg("ntlBlenderDumper::renderScene","Unable to open output '" + boutfilename.str() + "' ");
173                                         return 1; }
174
175                                 // dont transform velocity output, this is handled in blender
176                                 // current transform matrix
177                                 ntlMatrix4x4<gfxReal> *trafo;
178                                 trafo = lbm->getDomainTrafo();
179                                 if(trafo) {
180                                         // transform into source space
181                                         for(size_t i=0; i<Vertices.size(); i++) {
182                                                 Vertices[i] = (*trafo) * Vertices[i];
183                                         }
184                                 }
185                                 // rotate vertnormals
186                                 ntlMatrix4x4<gfxReal> rottrafo;
187                                 rottrafo.initId();
188                                 if(lbm->getDomainTrafo()) {
189                                         // dont modifiy original!
190                                         rottrafo = *lbm->getDomainTrafo();
191                                         ntlVec3Gfx rTrans,rScale,rRot,rShear;
192                                         rottrafo.decompose(rTrans,rScale,rRot,rShear);
193                                         rottrafo.initRotationXYZ(rRot[0],rRot[1],rRot[2]);
194                                         // only rotate here...
195                                         for(size_t i=0; i<Vertices.size(); i++) {
196                                                 VertNormals[i] = rottrafo * VertNormals[i];
197                                                 normalize(VertNormals[i]); // remove scaling etc.
198                                         }
199                                 }
200
201                                 
202                                 // write to file
203                                 int numVerts;
204                                 if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
205                                 numVerts = Vertices.size();
206                                 gzwrite(gzf, &numVerts, sizeof(numVerts));
207                                 for(size_t i=0; i<Vertices.size(); i++) {
208                                         for(int j=0; j<3; j++) {
209                                                 float vertp = Vertices[i][j];
210                                                 gzwrite(gzf, &vertp, sizeof(vertp)); }
211                                 }
212
213                                 // should be the same as Vertices.size
214                                 if(VertNormals.size() != (size_t)numVerts) {
215                                         errMsg("ntlBlenderDumper::renderScene","Normals have to have same size as vertices!");
216                                         VertNormals.resize( Vertices.size() );
217                                 }
218                                 gzwrite(gzf, &numVerts, sizeof(numVerts));
219                                 for(size_t i=0; i<VertNormals.size(); i++) {
220                                         for(int j=0; j<3; j++) {
221                                                 float normp = VertNormals[i][j];
222                                                 gzwrite(gzf, &normp, sizeof(normp)); }
223                                 }
224
225                                 int numTris = Triangles.size();
226                                 gzwrite(gzf, &numTris, sizeof(numTris));
227                                 for(size_t i=0; i<Triangles.size(); i++) {
228                                         for(int j=0; j<3; j++) {
229                                                 int triIndex = Triangles[i].getPoints()[j];
230                                                 gzwrite(gzf, &triIndex, sizeof(triIndex)); }
231                                 }
232                                 gzclose( gzf );
233                                 debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY," Wrote: '"<<boutfilename.str()<<"' ", 2);
234                                 numGMs++;
235                         }
236                 }
237
238         }
239
240         // output ecr config file
241         if(numGMs>0) {
242                 if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Objects dumped: "<<numGMs, 10);
243         } else {
244                 if((glob_mpactive) && (glob_mpindex>0)) {
245                         // ok, nothing to do anyway...
246                 } else {
247                         errFatal("ntlBlenderDumper::renderScene","No objects to dump! Aborting...",SIMWORLD_INITERROR);
248                         return 1;
249                 }
250         }
251
252         // debug timing
253         long stopTime = getTime();
254         debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10);
255
256         // still render for preview...
257         if(debugRender) {
258                 debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1);
259                 ntlWorld::renderScene(); }
260         else {
261                 // next frame 
262                 glob->setAniCount( glob->getAniCount() +1 );
263         }
264
265         return 0;
266 }
267
268
269