Blender  V2.59
ntl_blenderdumper.cpp
Go to the documentation of this file.
00001 
00004 /******************************************************************************
00005  *
00006  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
00007  * Copyright 2003-2006 Nils Thuerey
00008  *
00009  * Replaces std. raytracer, and only dumps time dep. objects to disc
00010  *
00011  *****************************************************************************/
00012 
00013 #include <fstream>
00014 #include <sys/types.h>
00015 
00016 #include "utilities.h"
00017 #include "ntl_matrices.h"
00018 #include "ntl_blenderdumper.h"
00019 #include "ntl_world.h"
00020 #include "solver_interface.h"
00021 
00022 #include <zlib.h>
00023 
00024 
00025 
00026 /******************************************************************************
00027  * Constructor
00028  *****************************************************************************/
00029 ntlBlenderDumper::ntlBlenderDumper() : ntlWorld()
00030 {
00031         // same as normal constructor here
00032 }
00033 ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) :
00034         ntlWorld(filename,commandlineMode)
00035 {
00036         // init world
00037 }
00038 
00039 
00040 
00041 /******************************************************************************
00042  * Destructor
00043  *****************************************************************************/
00044 ntlBlenderDumper::~ntlBlenderDumper()
00045 {
00046         debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10);
00047 }
00048 
00049 // required globals
00050 extern bool glob_mpactive;
00051 extern int glob_mpnum, glob_mpindex;
00052 
00053 /******************************************************************************
00054  * Only dump time dep. objects to file
00055  *****************************************************************************/
00056 int ntlBlenderDumper::renderScene( void )
00057 {
00058         char nrStr[5];                                                          /* nr conversion */
00059   ntlRenderGlobals *glob = mpGlob;
00060   ntlScene *scene = mpGlob->getSimScene();
00061         bool debugOut = false;
00062         bool debugRender = false;
00063 #if ELBEEM_PLUGIN==1
00064         debugOut = false;
00065 #endif // ELBEEM_PLUGIN==1
00066 
00067         vector<string> gmName;   // gm names
00068         vector<string> gmMat;    // materials for gm
00069         int numGMs = 0;                                  // no. of .obj models created
00070 
00071         if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Dumping geometry data", 1);
00072   long startTime = getTime();
00073         snprintf(nrStr, 5, "%04d", glob->getAniCount() );
00074 
00075   // local scene vars
00076   vector<ntlTriangle> Triangles;
00077   vector<ntlVec3Gfx>  Vertices;
00078   vector<ntlVec3Gfx>  VertNormals;
00079 
00080         // check geo objects
00081         int idCnt = 0;          // give IDs to objects
00082         for (vector<ntlGeometryClass*>::iterator iter = scene->getGeoClasses()->begin();
00083                         iter != scene->getGeoClasses()->end(); iter++) {
00084                 if(!(*iter)->getVisible()) continue;
00085                 int tid = (*iter)->getTypeId();
00086 
00087                 if(tid & GEOCLASSTID_OBJECT) {
00088                         // normal geom. objects -> ignore
00089                 }
00090                 if(tid & GEOCLASSTID_SHADER) {
00091                         ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter);
00092                         string outname = geoshad->getOutFilename();
00093                         if(outname.length()<1) outname = mpGlob->getOutFilename();
00094                         geoshad->notifyShaderOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname);
00095 
00096                         for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
00097                                         siter != geoshad->getObjectsEnd();
00098                                         siter++) {
00099                                 if(debugOut) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 8);
00100 
00101                                 (*siter)->notifyOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname, this->mSimulationTime);
00102                                 bool doDump = false;
00103                                 bool isPreview = false;
00104                                 // only dump final&preview surface meshes
00105                                 if( (*siter)->getName().find( "final" ) != string::npos) {
00106                                         doDump = true;
00107                                 } else if( (*siter)->getName().find( "preview" ) != string::npos) {
00108                                         doDump = true;
00109                                         isPreview = true;
00110                                 }
00111                                 if(!doDump) continue;
00112 
00113                                 // dont quit, some objects need notifyOfDump call
00114                                 if((glob_mpactive) && (glob_mpindex>0)) {
00115                                         continue; //return 0;
00116                                 }
00117                                 
00118                                 // only dump geo shader objects
00119                                 Triangles.clear();
00120                                 Vertices.clear();
00121                                 VertNormals.clear();
00122                                 (*siter)->initialize( mpGlob );
00123                                 (*siter)->getTriangles(this->mSimulationTime, &Triangles, &Vertices, &VertNormals, idCnt);
00124                                 idCnt ++;
00125                                 
00126                                 // WARNING - this is dirty, but simobjs are the only geoshaders right now
00127                                 SimulationObject *sim = (SimulationObject *)geoshad;
00128                                 LbmSolverInterface *lbm = sim->getSolver();
00129 
00130 
00131                                 // always dump mesh, even empty ones...
00132 
00133                                 // dump to binary file
00134                                 std::ostringstream boutfilename("");
00135                                 //boutfilename << ecrpath.str() << outname <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj";
00136                                 boutfilename << outname <<"_"<< (*siter)->getName() <<"_" << nrStr;
00137                                 if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName() 
00138                                                 <<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<<
00139                                                 " to "<<boutfilename.str() , 7);
00140                                 gzFile gzf;
00141 
00142                                 // output velocities if desired
00143                                 if((!isPreview) && (lbm->getDumpVelocities())) {
00144                                         std::ostringstream bvelfilename;
00145                                         bvelfilename << boutfilename.str();
00146                                         bvelfilename << ".bvel.gz";
00147                                         gzf = gzopen(bvelfilename.str().c_str(), "wb9");
00148                                         if(gzf) {
00149                                                 int numVerts;
00150                                                 if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
00151                                                 numVerts = Vertices.size();
00152                                                 gzwrite(gzf, &numVerts, sizeof(numVerts));
00153                                                 for(size_t i=0; i<Vertices.size(); i++) {
00154                                                         // returns smoothed velocity, scaled by frame time
00155                                                         ntlVec3Gfx v = lbm->getVelocityAt( Vertices[i][0], Vertices[i][1], Vertices[i][2] );
00156                                                         // translation not necessary, test rotation & scaling?
00157                                                         for(int j=0; j<3; j++) {
00158                                                                 float vertp = v[j];
00159                                                                 //if(i<20) errMsg("ntlBlenderDumper","DUMP_VEL final "<<i<<" = "<<v);
00160                                                                 gzwrite(gzf, &vertp, sizeof(vertp)); }
00161                                                 }
00162                                                 gzclose( gzf );
00163                                         }
00164                                 }
00165 
00166                                 // compress all bobj's 
00167                                 boutfilename << ".bobj.gz";
00168                                 gzf = gzopen(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes!
00169                                 if (!gzf) {
00170                                         errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' ");
00171                                         return 1; }
00172 
00173                                 // dont transform velocity output, this is handled in blender
00174                                 // current transform matrix
00175                                 ntlMatrix4x4<gfxReal> *trafo;
00176                                 trafo = lbm->getDomainTrafo();
00177                                 if(trafo) {
00178                                         // transform into source space
00179                                         for(size_t i=0; i<Vertices.size(); i++) {
00180                                                 Vertices[i] = (*trafo) * Vertices[i];
00181                                         }
00182                                 }
00183                                 // rotate vertnormals
00184                                 ntlMatrix4x4<gfxReal> rottrafo;
00185                                 rottrafo.initId();
00186                                 if(lbm->getDomainTrafo()) {
00187                                         // dont modifiy original!
00188                                         rottrafo = *lbm->getDomainTrafo();
00189                                         ntlVec3Gfx rTrans,rScale,rRot,rShear;
00190                                         rottrafo.decompose(rTrans,rScale,rRot,rShear);
00191                                         rottrafo.initRotationXYZ(rRot[0],rRot[1],rRot[2]);
00192                                         // only rotate here...
00193                                         for(size_t i=0; i<Vertices.size(); i++) {
00194                                                 VertNormals[i] = rottrafo * VertNormals[i];
00195                                                 normalize(VertNormals[i]); // remove scaling etc.
00196                                         }
00197                                 }
00198 
00199                                 
00200                                 // write to file
00201                                 int numVerts;
00202                                 if(sizeof(numVerts)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
00203                                 numVerts = Vertices.size();
00204                                 gzwrite(gzf, &numVerts, sizeof(numVerts));
00205                                 for(size_t i=0; i<Vertices.size(); i++) {
00206                                         for(int j=0; j<3; j++) {
00207                                                 float vertp = Vertices[i][j];
00208                                                 gzwrite(gzf, &vertp, sizeof(vertp)); }
00209                                 }
00210 
00211                                 // should be the same as Vertices.size
00212                                 if(VertNormals.size() != (size_t)numVerts) {
00213                                         errMsg("ntlBlenderDumper::renderScene","Normals have to have same size as vertices!");
00214                                         VertNormals.resize( Vertices.size() );
00215                                 }
00216                                 gzwrite(gzf, &numVerts, sizeof(numVerts));
00217                                 for(size_t i=0; i<VertNormals.size(); i++) {
00218                                         for(int j=0; j<3; j++) {
00219                                                 float normp = VertNormals[i][j];
00220                                                 gzwrite(gzf, &normp, sizeof(normp)); }
00221                                 }
00222 
00223                                 int numTris = Triangles.size();
00224                                 gzwrite(gzf, &numTris, sizeof(numTris));
00225                                 for(size_t i=0; i<Triangles.size(); i++) {
00226                                         for(int j=0; j<3; j++) {
00227                                                 int triIndex = Triangles[i].getPoints()[j];
00228                                                 gzwrite(gzf, &triIndex, sizeof(triIndex)); }
00229                                 }
00230                                 gzclose( gzf );
00231                                 debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY," Wrote: '"<<boutfilename.str()<<"' ", 2);
00232                                 numGMs++;
00233                         }
00234                 }
00235 
00236         }
00237 
00238         // output ecr config file
00239         if(numGMs>0) {
00240                 if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Objects dumped: "<<numGMs, 10);
00241         } else {
00242                 if((glob_mpactive) && (glob_mpindex>0)) {
00243                         // ok, nothing to do anyway...
00244                 } else {
00245                         errFatal("ntlBlenderDumper::renderScene","No objects to dump! Aborting...",SIMWORLD_INITERROR);
00246                         return 1;
00247                 }
00248         }
00249 
00250         // debug timing
00251         long stopTime = getTime();
00252         debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10);
00253 
00254         // still render for preview...
00255         if(debugRender) {
00256                 debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1);
00257                 ntlWorld::renderScene(); }
00258         else {
00259                 // next frame 
00260                 glob->setAniCount( glob->getAniCount() +1 );
00261         }
00262 
00263         return 0;
00264 }
00265 
00266 
00267