Blender V2.61 - r43446

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