Exemplo n.º 1
0
/******************************************************************************
 *! dump particles if desired 
 *****************************************************************************/
void ParticleTracer::notifyOfDump(int dumptype, int frameNr,char *frameNrStr,string outfilename, double simtime) {
	debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr<<" dumpp"<<mDumpParts<<" t"<<simtime, 10); // DEBUG

	if(
			(dumptype==DUMP_FULLGEOMETRY)&&
			(mDumpParts>0)) {
		// dump to binary file
		std::ostringstream boutfilename("");
		boutfilename << outfilename <<"_particles_" << frameNrStr;
		if(glob_mpactive) {
			if(glob_mpindex>0) { boutfilename << "mp"<<glob_mpindex; }
		}
		boutfilename << ".gz";
		debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"B-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" #"<<frameNr , 7);
		//debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"B-Dumping: partgeodeb sim:"<<mSimStart<<","<<mSimEnd<<" geosize:"<<mStart<<","<<mEnd,2 );

		// output to zipped file
		gzFile gzf;
		gzf = gzopen(boutfilename.str().c_str(), "wb1");
		if(gzf) {
			int numParts;
			if(sizeof(numParts)!=4) { errMsg("ParticleTracer::notifyOfDump","Invalid int size"); return; }
			// only dump active particles
			numParts = 0;
			for(size_t i=0; i<mParts.size(); i++) {
				if(!mParts[i].getActive()) continue;
				numParts++;
			}
			gzwrite(gzf, &numParts, sizeof(numParts));
			for(size_t i=0; i<mParts.size(); i++) {
				if(!mParts[i].getActive()) { continue; }
				ParticleObject *p = &mParts[i];
				//int type = p->getType();  // export whole type info
				int type = p->getFlags(); // debug export whole type & status info
				ntlVec3Gfx pos = p->getPos();
				float size = p->getSize();

				if(type&PART_FLOAT) { // WARNING same handling for dump!
					// add one gridcell offset
					//pos[2] += 1.0; 
				} 
				// display as drop for now externally
				//else if(type&PART_TRACER) { type |= PART_DROP; }

				pos = (*mpTrafo) * pos;

				ntlVec3Gfx v = p->getVel();
				v[0] *= mpTrafo->value[0][0];
				v[1] *= mpTrafo->value[1][1];
				v[2] *= mpTrafo->value[2][2];
				// FIXME check: pos = (*mpTrafo) * pos;
				gzwrite(gzf, &type, sizeof(type)); 
				gzwrite(gzf, &size, sizeof(size)); 
				for(int j=0; j<3; j++) { gzwrite(gzf, &pos[j], sizeof(float)); }
				for(int j=0; j<3; j++) { gzwrite(gzf, &v[j], sizeof(float)); }
			}
			gzclose( gzf );
		}
	} // dump?
}
Exemplo n.º 2
0
/******************************************************************************
 * render a whole animation (visualization mode) 
 * this function is run in another thread, and communicates 
 * with the parent thread via a mutex 
 *****************************************************************************/
int ntlWorld::renderVisualization( bool multiThreaded ) 
{
#ifndef NOGUI
	if(getElbeemState() != SIMWORLD_INITED) { return 0; }

	if(multiThreaded) mThreadRunning = true;
	// TODO, check global state?
	while(!getStopRenderVisualization()) {

		if(mpSims->size() <= 0) {
			debMsgStd("ntlWorld::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1);
			stopSimulationThread();
			break;
		}

		// determine stepsize
		if(!mSingleStepDebug) {
			long startTime = getTime();
			advanceSims(mFrameCnt);
			mFrameCnt++;
			long stopTime = getTime();
			debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for t="<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<" ", 10);
		} else {
			double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep();
			singleStepSims(targetTime);

			// check paniced sims (normally done by advanceSims
			bool allPanic = true;
			for(size_t i=0;i<mpSims->size();i++) {
				if(!(*mpSims)[i]->getPanic()) allPanic = false;
			}
			if(allPanic) {
				warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" );
				setStopRenderVisualization( true );
			}
			if(! isSimworldOk() ) {
				warnMsg("ntlWorld::advanceSims","World state error... stopping" );
				setStopRenderVisualization( true );
			}
		}

		// save frame
		if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime );
		
		// for non-threaded check events
		if(!multiThreaded) {
			Fl::check();
      gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw();
		}

	}
	mThreadRunning = false;
	stopSimulationRestoreGui();
#else 
	multiThreaded = false; // remove warning
#endif
	return 0;
}
Exemplo n.º 3
0
// copy & remember settings for later use
void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) {
	mpElbeemSettings = new elbeemSimulationSettings;
	*mpElbeemSettings = *settings;

	mGeoInitId = settings->domainId+1;
	debMsgStd("SimulationObject",DM_MSG,"mGeoInitId="<<mGeoInitId<<", domainId="<<settings->domainId, 8);
}
Exemplo n.º 4
0
void elbeemCheckDebugEnv(void) {
	const char *strEnvName = "BLENDER_ELBEEMDEBUG";
	const char *strEnvName2 = "ELBEEM_DEBUGLEVEL";
	if(globalFirstEnvCheck) return;

	if(getenv(strEnvName)) {
		gDebugLevel = atoi(getenv(strEnvName));
		if(gDebugLevel>0) debMsgStd("performElbeemSimulation",DM_NOTIFY,"Using envvar '"<<strEnvName<<"'='"<<getenv(strEnvName)<<"', debugLevel set to: "<<gDebugLevel<<"\n", 1);
	}
	if(getenv(strEnvName2)) {
		gDebugLevel = atoi(getenv(strEnvName2));
		if(gDebugLevel>0) debMsgStd("performElbeemSimulation",DM_NOTIFY,"Using envvar '"<<strEnvName2<<"'='"<<getenv(strEnvName2)<<"', debugLevel set to: "<<gDebugLevel<<"\n", 1);
	}
	if(gDebugLevel< 0) gDebugLevel =  0;
	if(gDebugLevel>10) gDebugLevel =  0; // only use valid values
	globalFirstEnvCheck = 1;
}
Exemplo n.º 5
0
/******************************************************************************
 * Destructor
 *****************************************************************************/
SimulationObject::~SimulationObject()
{
	if(mpGiTree)         delete mpGiTree;
	if(mpElbeemSettings) delete mpElbeemSettings;
	if(mpLbm)            delete mpLbm;
  	if(mpParam)          delete mpParam;
	if(mpParts)          delete mpParts;
	debMsgStd("SimulationObject",DM_MSG,"El'Beem Done!\n",10);
}
Exemplo n.º 6
0
int ntlWorld::renderAnimation( void )
{
	// only single pic currently
	//debMsgStd("ntlWorld::renderAnimation : Warning only simulating...",1);
 	if(mpGlob->getAniFrames() < 0) {
		debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No frames to render... ",1);
		return 1;
	}

	if(mFirstSim<0) {
		debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No reference animation found...",1);
		return 1;
	} 

	mThreadRunning = true; // not threaded, but still use the same flags
	if(getElbeemState() == SIMWORLD_INITED) {
		renderScene();
	} else if(getElbeemState() == SIMWORLD_STOP) {
		// dont render now, just continue
		setElbeemState( SIMWORLD_INITED );
		mFrameCnt--; // counted one too many from last abort...
	} else {
		debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"Not properly inited, stopping...",1);
		return 1;
	}
	
	if(mpSims->size() <= 0) {
		debMsgStd("ntlWorld::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1);
		return 1;
	}

	bool simok = true;
	for( ; ((mFrameCnt<mpGlob->getAniFrames()) && (!getStopRenderVisualization() ) && (simok)); mFrameCnt++) {
		if(!advanceSims(mFrameCnt)) {
			renderScene();
		} // else means sim panicked, so dont render...
		else { simok=false; }
	}
	mThreadRunning = false;
	return 0;
}
Exemplo n.º 7
0
/******************************************************************************
 * Destructor
 *****************************************************************************/
ntlWorld::~ntlWorld()
{
	delete mpGlob->getRenderScene();
	delete mpGlob->getSimScene();
  
	delete mpGlob;
	
	
	// these get assigned to mpGlob but not freed there
	delete mpLightList;
	delete mpPropList; // materials
	delete mpSims;
  
#ifndef NOGUI
	if(mpOpenGLRenderer) delete mpOpenGLRenderer;
#endif // NOGUI
	debMsgStd("ntlWorld",DM_NOTIFY, "ntlWorld done", 10);
}
Exemplo n.º 8
0
/******************************************************************************
 * Standard constructor
 *****************************************************************************/
ParticleTracer::ParticleTracer() :
	ntlGeometryObject(),
	mParts(),
	//mTrailLength(1), mTrailInterval(1),mTrailIntervalCounter(0),
	mPartSize(0.01),
	mStart(-1.0), mEnd(1.0),
	mSimStart(-1.0), mSimEnd(1.0),
	mPartScale(0.1) , mPartHeadDist( 0.1 ), mPartTailDist( -0.1 ), mPartSegments( 4 ),
	mValueScale(0),
	mValueCutoffTop(0.0), mValueCutoffBottom(0.0),
	mDumpParts(0), //mDumpText(0), 
	mDumpTextFile(""), 
	mDumpTextInterval(0.), mDumpTextLastTime(0.), mDumpTextCount(0),
	mShowOnly(0), 
	mNumInitialParts(0), mpTrafo(NULL),
	mInitStart(-1.), mInitEnd(-1.),
	mPrevs(), mTrailTimeLast(0.), mTrailInterval(-1.), mTrailLength(0)
{
	debMsgStd("ParticleTracer::ParticleTracer",DM_MSG,"inited",10);
};
Exemplo n.º 9
0
/*! check status (e.g. stop/abort) from calling program, returns !=0 if sth. happened... */
int SimulationObject::checkCallerStatus(int status, int frame) {
	//return 0; // DEBUG
	int ret = 0;
	if((mpElbeemSettings)&&(mpElbeemSettings->runsimCallback)) {
		ret = (mpElbeemSettings->runsimCallback)(mpElbeemSettings->runsimUserData, status,frame);
		if(ret!=FLUIDSIM_CBRET_CONTINUE) {
			if(ret==FLUIDSIM_CBRET_STOP) {
				debMsgStd("SimulationObject::notifySolverOfDump",DM_NOTIFY,"Got stop signal from caller",1);
				setElbeemState( SIMWORLD_STOP );
			}
			else if(ret==FLUIDSIM_CBRET_ABORT) {
				errFatal("SimulationObject::notifySolverOfDump","Got abort signal from caller, aborting...", SIMWORLD_GENERICERROR );
				mPanic = 1;
			}
			else {
				errMsg("SimulationObject::notifySolverOfDump","Invalid callback return value: "<<ret<<", ignoring... ");
			}
		}
	}

	//debMsgStd("SimulationObject::checkCallerStatus",DM_MSG, "s="<<status<<",f="<<frame<<" "<<this->getName()<<" ret="<<ret);
	if(isSimworldOk()) return 0;
	return 1;
}
Exemplo n.º 10
0
ParticleTracer::~ParticleTracer() {
	debMsgStd("ParticleTracer::~ParticleTracer",DM_MSG,"destroyed",10);
	if(mpTrafo) delete mpTrafo;
}
Exemplo n.º 11
0
/******************************************************************************
 * Get triangles for rendering
 *****************************************************************************/
void ParticleTracer::getTriangles(double time, vector<ntlTriangle> *triangles, 
													 vector<ntlVec3Gfx> *vertices, 
													 vector<ntlVec3Gfx> *normals, int objectId )
{
#ifdef ELBEEM_PLUGIN
	// suppress warnings...
	vertices = NULL; triangles = NULL;
	normals = NULL; objectId = 0;
	time = 0.;
#else // ELBEEM_PLUGIN
	int pcnt = 0;
	// currently not used in blender
	objectId = 0; // remove, deprecated
	if(mDumpParts>1) { 
		return; // only dump, no tri-gen
	}

	const bool debugParts = false;
	int tris = 0;
	int segments = mPartSegments;
	ntlVec3Gfx scale = ntlVec3Gfx( (mEnd[0]-mStart[0])/(mSimEnd[0]-mSimStart[0]), (mEnd[1]-mStart[1])/(mSimEnd[1]-mSimStart[1]), (mEnd[2]-mStart[2])/(mSimEnd[2]-mSimStart[2]));
	ntlVec3Gfx trans = mStart;
	time = 0.; // doesnt matter

	for(size_t t=0; t<mPrevs.size()+1; t++) {
		vector<ParticleObject> *dparts;
		if(t==0) {
			dparts = &mParts;
		} else {
			dparts = &mPrevs[t-1];
		}
		//errMsg("TRAILT","prevs"<<t<<"/"<<mPrevs.size()<<" parts:"<<dparts->size() );

	gfxReal partscale = mPartScale;
	if(t>1) { 
		partscale *= (gfxReal)(mPrevs.size()+1-t) / (gfxReal)(mPrevs.size()+1); 
	}
	gfxReal partNormSize = 0.01 * partscale;
	//for(size_t i=0; i<mParts.size(); i++) {
	for(size_t i=0; i<dparts->size(); i++) {
		ParticleObject *p = &( (*dparts)[i] ); //  mParts[i];

		if(mShowOnly!=10) {
			// 10=show only deleted
			if( p->getActive()==false ) continue;
		} else {
			if( p->getActive()==true ) continue;
		}
		int type = p->getType();
		if(mShowOnly>0) {
			switch(mShowOnly) {
			case 1: if(!(type&PART_BUBBLE)) continue; break;
			case 2: if(!(type&PART_DROP))   continue; break;
			case 3: if(!(type&PART_INTER))  continue; break;
			case 4: if(!(type&PART_FLOAT))  continue; break;
			case 5: if(!(type&PART_TRACER))  continue; break;
			}
		} else {
			// by default dont display inter
			if(type&PART_INTER) continue;
		}

		pcnt++;
		ntlVec3Gfx pnew = p->getPos();
		if(type&PART_FLOAT) { // WARNING same handling for dump!
			if(p->getStatus()&PART_IN) { pnew[2] += 0.8; } // offset for display
			// add one gridcell offset
			//pnew[2] += 1.0; 
		}
#if LBMDIM==2
		pnew[2] += 0.001; // DEBUG
		pnew[2] += 0.009; // DEBUG
#endif 

		ntlVec3Gfx pdir = p->getVel();
		gfxReal plen = normalize( pdir );
		if( plen < 1e-05) pdir = ntlVec3Gfx(-1.0 ,0.0 ,0.0);
		ntlVec3Gfx pos = (*mpTrafo) * pnew;
		gfxReal partsize = 0.0;
		if(debugParts) errMsg("DebugParts"," i"<<i<<" new"<<pnew<<" vel"<<pdir<<"   pos="<<pos );
		//if(i==0 &&(debugParts)) errMsg("DebugParts"," i"<<i<<" new"<<pnew[0]<<" pos="<<pos[0]<<" scale="<<scale[0]<<"  t="<<trans[0] );
		
		// value length scaling?
		if(mValueScale==1) {
			partsize = partscale * plen;
		} else if(mValueScale==2) {
			// cut off scaling
			if(plen > mValueCutoffTop) continue;
			if(plen < mValueCutoffBottom) continue;
			partsize = partscale * plen;
		} else {
			partsize = partscale; // no length scaling
		}
		//if(type&(PART_DROP|PART_BUBBLE)) 
		partsize *= p->getSize()/5.0;

		ntlVec3Gfx pstart( mPartHeadDist *partsize, 0.0, 0.0 );
		ntlVec3Gfx pend  ( mPartTailDist *partsize, 0.0, 0.0 );
		gfxReal phi = 0.0;
		gfxReal phiD = 2.0*M_PI / (gfxReal)segments;

		ntlMat4Gfx cvmat; 
		cvmat.initId();
		pdir *= -1.0;
		ntlVec3Gfx cv1 = pdir;
		ntlVec3Gfx cv2 = ntlVec3Gfx(pdir[1], -pdir[0], 0.0);
		ntlVec3Gfx cv3 = cross( cv1, cv2);
		//? for(int l=0; l<3; l++) { cvmat.value[l][0] = cv1[l]; cvmat.value[l][1] = cv2[l]; cvmat.value[l][2] = cv3[l]; }
		pstart = (cvmat * pstart);
		pend = (cvmat * pend);

		for(int s=0; s<segments; s++) {
			ntlVec3Gfx p1( 0.0 );
			ntlVec3Gfx p2( 0.0 );

			gfxReal radscale = partNormSize;
			radscale = (partsize+partNormSize)*0.5;
			p1[1] += cos(phi) * radscale;
			p1[2] += sin(phi) * radscale;
			p2[1] += cos(phi + phiD) * radscale;
			p2[2] += sin(phi + phiD) * radscale;
			ntlVec3Gfx n1 = ntlVec3Gfx( 0.0, cos(phi), sin(phi) );
			ntlVec3Gfx n2 = ntlVec3Gfx( 0.0, cos(phi + phiD), sin(phi + phiD) );
			ntlVec3Gfx ns = n1*0.5 + n2*0.5;

			p1 = (cvmat * p1);
			p2 = (cvmat * p2);

			sceneAddTriangle( pos+pstart, pos+p1, pos+p2, 
					ns,n1,n2, ntlVec3Gfx(0.0), 1, triangles,vertices,normals ); 
			sceneAddTriangle( pos+pend  , pos+p2, pos+p1, 
					ns,n2,n1, ntlVec3Gfx(0.0), 1, triangles,vertices,normals ); 

			phi += phiD;
			tris += 2;
		}
	}

	} // t

	debMsgStd("ParticleTracer::getTriangles",DM_MSG,"Dumped "<<pcnt<<"/"<<mParts.size()<<" parts, tris:"<<tris<<", showonly:"<<mShowOnly,10);
	return; // DEBUG

#endif // ELBEEM_PLUGIN
}
Exemplo n.º 12
0
void ParticleTracer::checkDumpTextPositions(double simtime) {
	// dfor partial & full dump
	if(mDumpTextInterval>0.) {
		debMsgStd("ParticleTracer::checkDumpTextPositions",DM_MSG,"t="<<simtime<<" last:"<<mDumpTextLastTime<<" inter:"<<mDumpTextInterval,7);
	}

	if((mDumpTextInterval>0.) && (simtime>mDumpTextLastTime+mDumpTextInterval)) {
		// dump to binary file
		std::ostringstream boutfilename("");
		if(mDumpTextFile.length()>1) {   
			boutfilename << mDumpTextFile <<  ".cpart2"; 
		} else {                           
			boutfilename << "_particles" <<  ".cpart2"; 
		}
		debMsgStd("ParticleTracer::checkDumpTextPositions",DM_MSG,"T-Dumping: "<< this->getName() <<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" " , 7);

		int numParts = 0;
		// only dump bubble particles
		for(size_t i=0; i<mParts.size(); i++) {
			//if(!mParts[i].getActive()) continue;
			//if(!(mParts[i].getType()&PART_BUBBLE)) continue;
			numParts++;
		}

		// output to text file
		//gzFile gzf;
		FILE *stf;
		if(mDumpTextCount==0) {
			//gzf = gzopen(boutfilename.str().c_str(), "w0");
			stf = fopen(boutfilename.str().c_str(), "w");

			fprintf( stf, "\n\n# cparts generated by elbeem \n# no. of parts \nN %d \n\n",numParts);
			// fixed time scale for now
			fprintf( stf, "T %f \n\n", 1.0);
		} else {
			//gzf = gzopen(boutfilename.str().c_str(), "a+0");
			stf = fopen(boutfilename.str().c_str(), "a+");
		}

		// add current set
		if(stf) {
			fprintf( stf, "\n\n# new set at frame %d,t%f,p%d --------------------------------- \n\n", mDumpTextCount, simtime, numParts );
			fprintf( stf, "S %f \n\n", simtime );
			
			for(size_t i=0; i<mParts.size(); i++) {
				ParticleObject *p = &mParts[i];
				ntlVec3Gfx pos = p->getPos();
				float size = p->getSize();
				float infl = 1.;
				//if(!mParts[i].getActive()) { size=0.; } // switch "off"
				if(!mParts[i].getActive()) { infl=0.; } // switch "off"
				if(!mParts[i].getInFluid()) { infl=0.; } // switch "off"
				if(mParts[i].getLifeTime()<0.) { infl=0.; } // not yet active...

				pos = (*mpTrafo) * pos;
				ntlVec3Gfx v = p->getVel();
				v[0] *= mpTrafo->value[0][0];
				v[1] *= mpTrafo->value[1][1];
				v[2] *= mpTrafo->value[2][2];
				
				fprintf( stf, "P %f %f %f \n", pos[0],pos[1],pos[2] );
				if(size!=1.0) fprintf( stf, "s %f \n", size );
				if(infl!=1.0) fprintf( stf, "i %f \n", infl );
				fprintf( stf, "\n" );
			}

			fprintf( stf, "# %d end  ", mDumpTextCount );
			//gzclose( gzf );
			fclose( stf );

			mDumpTextCount++;
		}

		mDumpTextLastTime += mDumpTextInterval;
	}

}
Exemplo n.º 13
0
/******************************************************************************
 * Destructor
 *****************************************************************************/
ntlBlenderDumper::~ntlBlenderDumper()
{
    debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10);
}
Exemplo n.º 14
0
/******************************************************************************
 * advance simulations by time t 
 *****************************************************************************/
int ntlWorld::advanceSims(int framenum)
{
	bool done = false;
	bool allPanic = true;

	// stop/quit (abort), dont display/render
	if(!isSimworldOk()) { 
		return 1;
	}

	for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); }

	// time stopped? nothing else to do...
	if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ 
		done=true; allPanic=false; 

		/* DG: Need to check for user cancel here (fix for [#30298]) */
		(*mpSims)[mFirstSim]->checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0);
	}

	// Prevent bug [#29186] Object contribute to fluid sim animation start earlier than keyframe
	// Was: double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum); - DG
	double totalTime = 0.0, targetTime = 0.0;
	for(size_t i = 0; i < mSimFrameCnt; i++)
	{
		/* We need an intermediate array "mSimFrameValue" because
		otherwise if we don't start with starttime = 0, 
		the sim gets out of sync - DG */
		totalTime += (*mpSims)[mFirstSim]->getFrameTime(mSimFrameValue[i]);	
	}
	targetTime = totalTime + (*mpSims)[mFirstSim]->getFrameTime(framenum);

	int gstate = 0;
	myTime_t advsstart = getTime();

	// step all the sims, and check for panic
	debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic<<" gstate:"<<gstate, 10); // debug // timedebug
	while(!done) {
		double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getTimestep();
		singleStepSims(nextTargetTime);

		// check target times
		done = true;
		allPanic = false;
		
		if((*mpSims)[mFirstSim]->getTimestep() <1e-9 ) { 
			// safety check, avoid timesteps that are too small
			errMsg("ntlWorld::advanceSims","Invalid time step, causing panic! curr:"<<(*mpSims)[mFirstSim]->getCurrentTime()<<" next:"<<nextTargetTime<<", stept:"<< (*mpSims)[mFirstSim]->getTimestep() );
			allPanic = true; 
		} else {
			for(size_t i=0;i<mpSims->size();i++) {
				if(!(*mpSims)[i]->getVisible()) continue;
				if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!?
				debMsgStd("ntlWorld::advanceSims",DM_MSG, "Sim "<<i<<", currt:"<<(*mpSims)[i]->getCurrentTime()<<", nt:"<<nextTargetTime<<", panic:"<<(*mpSims)[i]->getPanic()<<", targett:"<<targetTime, 10); // debug // timedebug
			} 
		}
		if( (targetTime - (*mpSims)[mFirstSim]->getCurrentTime()) > LBM_TIME_EPSILON) done=false;
		if(allPanic) done = true;
	}

	if(allPanic) {
		warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" );
		setStopRenderVisualization( true );
		return 1;
	}

	myTime_t advsend = getTime();
	debMsgStd("ntlWorld::advanceSims",DM_MSG,"Overall steps so far took:"<< getTimeString(advsend-advsstart)<<" for sim time "<<targetTime, 4);

	// finish step
	for(size_t i=0;i<mpSims->size();i++) {
		SimulationObject *sim = (*mpSims)[i];
		if(!sim->getVisible()) continue;
		if(sim->getPanic()) continue;
		sim->prepareVisualization();
	}

	mSimFrameValue.push_back(framenum);
	mSimFrameCnt++;

	return 0;
}
Exemplo n.º 15
0
void ntlWorld::finishWorldInit()
{
	if(! isSimworldOk() ) return;

	// init the scene for the first time
  long sstartTime = getTime();

	// first init sim scene for geo setup
	mpGlob->getSimScene()->buildScene(0.0, true);
	if(! isSimworldOk() ) return;
	mpGlob->getRenderScene()->buildScene(0.0, true);
	if(! isSimworldOk() ) return;
	long sstopTime = getTime();
	debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10);

	// TODO check simulations, run first steps
	mFirstSim = -1;
	if(mpSims->size() > 0) {

		// use values from first simulation as master time scale
		long startTime = getTime();
		
		// remember first active sim
		for(size_t i=0;i<mpSims->size();i++) {
			if(!(*mpSims)[i]->getVisible()) continue;
			if((*mpSims)[i]->getPanic())    continue;

			// check largest timestep
			if(mFirstSim>=0) {
				if( (*mpSims)[i]->getTimestep() > (*mpSims)[mFirstSim]->getTimestep() ) {
					mFirstSim = i;
					debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim changed: "<<i ,10);
				}
			}
			// check any valid sim
			if(mFirstSim<0) {
				mFirstSim = i;
				debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim: "<<i ,10);
			}
		}

		if(mFirstSim>=0) {
			debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10);
			while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) {
			debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<<mSimulationTime ,10);
				advanceSims(-1);
			}
			long stopTime = getTime();

			mSimulationTime += (*mpSims)[mFirstSim]->getStartTime();
			debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start-sims:"<< getTimeString(stopTime-startTime) , 1);
#ifndef NOGUI
			guiResetSimulationTimeRange( mSimulationTime );
#endif
		} else {
			if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1);
		}
	}

	if(! isSimworldOk() ) return;
	setElbeemState( SIMWORLD_INITED );
}
Exemplo n.º 16
0
void LbmControlData::parseControldataAttrList(AttributeList *attr) {
	// controlpart vars
	mSetForceStrength = attr->readFloat("tforcestrength", mSetForceStrength,"LbmControlData", "mSetForceStrength", false);
	//errMsg("tforcestrength set to "," "<<mSetForceStrength);
	mCpUpdateInterval = attr->readInt("controlparticle_updateinterval", mCpUpdateInterval,"LbmControlData","mCpUpdateInterval", false);
	// tracer output file
	mCpOutfile = attr->readString("controlparticle_outfile",mCpOutfile,"LbmControlData","mCpOutfile", false);
	if(getenv("ELBEEM_CPOUTFILE")) {
		string outfile(getenv("ELBEEM_CPOUTFILE"));
		mCpOutfile = outfile;
		debMsgStd("LbmControlData::parseAttrList",DM_NOTIFY,"Using envvar ELBEEM_CPOUTFILE to set mCpOutfile to "<<outfile<<","<<mCpOutfile,7);
	}

	for(int cpii=0; cpii<10; cpii++) {
		string suffix("");
		//if(cpii>0)
		{  suffix = string("0"); suffix[0]+=cpii; }
		LbmControlSet *cset;
		cset = new LbmControlSet();
		cset->initCparts();

		cset->mContrPartFile = attr->readString("controlparticle"+suffix+"_file",cset->mContrPartFile,"LbmControlData","cset->mContrPartFile", false);
		if((cpii==0) && (getenv("ELBEEM_CPINFILE")) ) {
			string infile(getenv("ELBEEM_CPINFILE"));
			cset->mContrPartFile = infile;
			debMsgStd("LbmControlData::parseAttrList",DM_NOTIFY,"Using envvar ELBEEM_CPINFILE to set mContrPartFile to "<<infile<<","<<cset->mContrPartFile,7);
		}

		LbmFloat cpvort=0.;
		cset->mcRadiusAtt =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_radiusatt", 0., "LbmControlData","mcRadiusAtt" );
		cset->mcRadiusVel =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_radiusvel", 0., "LbmControlData","mcRadiusVel" );
		cset->mcRadiusVel =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_radiusvel", 0., "LbmControlData","mcRadiusVel" );
		cset->mCparts->setRadiusAtt(cset->mcRadiusAtt.get(0.));
		cset->mCparts->setRadiusVel(cset->mcRadiusVel.get(0.));

		// WARNING currently only for first set
		//if(cpii==0) {
		cset->mcForceAtt  =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_attraction", 0. , "LbmControlData","cset->mcForceAtt", false);
		cset->mcForceVel  =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_velocity",   0. , "LbmControlData","mcForceVel", false);
		cset->mcForceMaxd =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_maxdist",    0. , "LbmControlData","mcForceMaxd", false);
		cset->mCparts->setInfluenceAttraction(cset->mcForceAtt.get(0.) );
		// warning - stores temprorarily, value converted to dt dep. factor
		cset->mCparts->setInfluenceVelocity(cset->mcForceVel.get(0.) , 0.01 ); // dummy dt
		cset->mCparts->setInfluenceMaxdist(cset->mcForceMaxd.get(0.) );
		cpvort =  attr->readFloat("controlparticle"+suffix+"_vorticity",   cpvort, "LbmControlData","cpvort", false);
		cset->mCparts->setInfluenceTangential(cpvort);
			
		cset->mcRadiusMind =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_radiusmin", cset->mcRadiusMind.get(0.), "LbmControlData","mcRadiusMind", false);
		cset->mcRadiusMaxd =  attr->readChannelSinglePrecFloat("controlparticle"+suffix+"_radiusmax", cset->mcRadiusMind.get(0.), "LbmControlData","mcRadiusMaxd", false);
		cset->mCparts->setRadiusMinMaxd(cset->mcRadiusMind.get(0.));
		cset->mCparts->setRadiusMaxd(cset->mcRadiusMaxd.get(0.));
		//}

		// now local...
		//LbmVec cpOffset(0.), cpScale(1.);
		LbmFloat cpTimescale = 1.;
		string cpMirroring("");

		//cset->mcCpOffset = attr->readChannelVec3f("controlparticle"+suffix+"_offset", ntlVec3f(0.),"LbmControlData","mcCpOffset", false);
		//cset->mcCpScale =  attr->readChannelVec3f("controlparticle"+suffix+"_scale",  ntlVec3f(1.), "LbmControlData","mcCpScale", false);
		cset->mcCpOffset = attr->readChannelVec3f("controlparticle"+suffix+"_offset", ntlVec3f(0.),"LbmControlData","mcCpOffset", false);
		cset->mcCpScale =  attr->readChannelVec3f("controlparticle"+suffix+"_scale",  ntlVec3f(1.), "LbmControlData","mcCpScale", false);
		cpTimescale =  attr->readFloat("controlparticle"+suffix+"_timescale",  cpTimescale, "LbmControlData","cpTimescale", false);
		cpMirroring =  attr->readString("controlparticle"+suffix+"_mirror",  cpMirroring, "LbmControlData","cpMirroring", false);

		LbmFloat cpsWidth = cset->mCparts->getCPSWith();
		cpsWidth =  attr->readFloat("controlparticle"+suffix+"_cpswidth",  cpsWidth, "LbmControlData","cpsWidth", false);
		LbmFloat cpsDt = cset->mCparts->getCPSTimestep();
		cpsDt =  attr->readFloat("controlparticle"+suffix+"_cpstimestep",  cpsDt, "LbmControlData","cpsDt", false);
		LbmFloat cpsTstart = cset->mCparts->getCPSTimeStart();
		cpsTstart =  attr->readFloat("controlparticle"+suffix+"_cpststart",  cpsTstart, "LbmControlData","cpsTstart", false);
		LbmFloat cpsTend = cset->mCparts->getCPSTimeEnd();
		cpsTend =  attr->readFloat("controlparticle"+suffix+"_cpstend",  cpsTend, "LbmControlData","cpsTend", false);
		LbmFloat cpsMvmfac = cset->mCparts->getCPSMvmWeightFac();
		cpsMvmfac =  attr->readFloat("controlparticle"+suffix+"_cpsmvmfac",  cpsMvmfac, "LbmControlData","cpsMvmfac", false);
		cset->mCparts->setCPSWith(cpsWidth);
		cset->mCparts->setCPSTimestep(cpsDt);
		cset->mCparts->setCPSTimeStart(cpsTstart);
		cset->mCparts->setCPSTimeEnd(cpsTend);
		cset->mCparts->setCPSMvmWeightFac(cpsMvmfac);

		cset->mCparts->setOffset( vec2L(cset->mcCpOffset.get(0.)) );
		cset->mCparts->setScale( vec2L(cset->mcCpScale.get(0.)) );
		cset->mCparts->setInitTimeScale( cpTimescale );
		cset->mCparts->setInitMirror( cpMirroring );

		int mDebugInit = 0;
		mDebugInit = attr->readInt("controlparticle"+suffix+"_debuginit", mDebugInit,"LbmControlData","mDebugInit", false);
		cset->mCparts->setDebugInit(mDebugInit);

		// motion particle settings
		LbmVec mcpOffset(0.), mcpScale(1.);
		LbmFloat mcpTimescale = 1.;
		string mcpMirroring("");

		cset->mCpmotionFile = attr->readString("cpmotion"+suffix+"_file",cset->mCpmotionFile,"LbmControlData","mCpmotionFile", false);
		mcpTimescale =  attr->readFloat("cpmotion"+suffix+"_timescale",  mcpTimescale, "LbmControlData","mcpTimescale", false);
		mcpMirroring =  attr->readString("cpmotion"+suffix+"_mirror",  mcpMirroring, "LbmControlData","mcpMirroring", false);
		mcpOffset = vec2L( attr->readVec3d("cpmotion"+suffix+"_offset", vec2P(mcpOffset),"LbmControlData","cpOffset", false) );
		mcpScale =  vec2L( attr->readVec3d("cpmotion"+suffix+"_scale",  vec2P(mcpScale), "LbmControlData","cpScale", false) );

		cset->mCpmotion->setOffset( vec2L(mcpOffset) );
		cset->mCpmotion->setScale( vec2L(mcpScale) );
		cset->mCpmotion->setInitTimeScale( mcpTimescale );
		cset->mCpmotion->setInitMirror( mcpMirroring );

		if(cset->mContrPartFile.length()>1) {
			errMsg("LbmControlData","Using control particle set "<<cpii<<" file:"<<cset->mContrPartFile<<" cpmfile:"<<cset->mCpmotionFile<<" mirr:'"<<cset->mCpmotion->getInitMirror()<<"' " );
			mCons.push_back( cset );
		} else {
			delete cset;
		}
	}

	// debug, testing - make sure theres at least an empty set
	if(mCons.size()<1) {
		mCons.push_back( new LbmControlSet() );
		mCons[0]->initCparts();
	}

	// take from first set
	for(int cpii=1; cpii<(int)mCons.size(); cpii++) {
		mCons[cpii]->mCparts->setRadiusMinMaxd( mCons[0]->mCparts->getRadiusMinMaxd() );
		mCons[cpii]->mCparts->setRadiusMaxd(    mCons[0]->mCparts->getRadiusMaxd() );
		mCons[cpii]->mCparts->setInfluenceAttraction( mCons[0]->mCparts->getInfluenceAttraction() );
		mCons[cpii]->mCparts->setInfluenceTangential( mCons[0]->mCparts->getInfluenceTangential() );
		mCons[cpii]->mCparts->setInfluenceVelocity( mCons[0]->mCparts->getInfluenceVelocity() , 0.01 ); // dummy dt
		mCons[cpii]->mCparts->setInfluenceMaxdist( mCons[0]->mCparts->getInfluenceMaxdist() );
	}
	
	// invert for usage in relax macro
	mDiffVelCon =  1.-attr->readFloat("cpdiffvelcon",  mDiffVelCon, "LbmControlData","mDiffVelCon", false);

	mDebugCpscale     =  attr->readFloat("cpdebug_cpscale",  mDebugCpscale, "LbmControlData","mDebugCpscale", false);
	mDebugMaxdScale   =  attr->readFloat("cpdebug_maxdscale",  mDebugMaxdScale, "LbmControlData","mDebugMaxdScale", false);
	mDebugAttScale    =  attr->readFloat("cpdebug_attscale",  mDebugAttScale, "LbmControlData","mDebugAttScale", false);
	mDebugVelScale    =  attr->readFloat("cpdebug_velscale",  mDebugVelScale, "LbmControlData","mDebugVelScale", false);
	mDebugCompavScale =  attr->readFloat("cpdebug_compavscale",  mDebugCompavScale, "LbmControlData","mDebugCompavScale", false);
	mDebugAvgVelScale =  attr->readFloat("cpdebug_avgvelsc",  mDebugAvgVelScale, "LbmControlData","mDebugAvgVelScale", false);
}
Exemplo n.º 17
0
void 
LbmFsgrSolver::initCpdata()
{
	// enable for cps via env. vars
	//if( (getenv("ELBEEM_CPINFILE")) || (getenv("ELBEEM_CPOUTFILE")) ){ mUseTestdata=1; }

	
	// manually switch on! if this is zero, nothing is done...
	mpControl->mSetForceStrength = this->mTForceStrength = 1.;
	mpControl->mCons.clear();
	
	// init all control fluid objects
	int numobjs = (int)(mpGiObjects->size());
	for(int o=0; o<numobjs; o++) {
		ntlGeometryObjModel *obj = (ntlGeometryObjModel *)(*mpGiObjects)[o];
		if(obj->getGeoInitType() & FGI_CONTROL) {
			// add new control set per object
			LbmControlSet *cset;

			cset = new LbmControlSet();
			cset->initCparts();
	
			// dont load any file
			cset->mContrPartFile = string("");

			cset->mcForceAtt = obj->getCpsAttrFStr();
			cset->mcRadiusAtt = obj->getCpsAttrFRad();
			cset->mcForceVel = obj->getCpsVelFStr();
			cset->mcRadiusVel = obj->getCpsVelFRad();

			cset->mCparts->setCPSTimeStart(obj->getCpsTimeStart());
			cset->mCparts->setCPSTimeEnd(obj->getCpsTimeEnd());
			
			if(obj->getCpsQuality() > LBM_EPSILON)
				cset->mCparts->setCPSWith(1.0 / obj->getCpsQuality());
			
			// this value can be left at 0.5:
			cset->mCparts->setCPSMvmWeightFac(0.5);

			mpControl->mCons.push_back( cset );
			mpControl->mCons[mpControl->mCons.size()-1]->mCparts->initFromObject(obj);
		}
	}
	
	// NT blender integration manual test setup
	if(0) {
		// manually switch on! if this is zero, nothing is done...
		mpControl->mSetForceStrength = this->mTForceStrength = 1.;
		mpControl->mCons.clear();

		// add new set
		LbmControlSet *cset;

		cset = new LbmControlSet();
		cset->initCparts();
		// dont load any file
		cset->mContrPartFile = string("");

		// set radii for attraction & velocity forces
		// set strength of the forces
		// don't set directly! but use channels: 
		// mcForceAtt, mcForceVel, mcForceMaxd, mcRadiusAtt, mcRadiusVel, mcRadiusMind, mcRadiusMaxd etc.

		// wrong: cset->mCparts->setInfluenceAttraction(1.15); cset->mCparts->setRadiusAtt(1.5);
		// right, e.g., to init some constant values:
		cset->mcForceAtt = AnimChannel<float>(0.2);
		cset->mcRadiusAtt = AnimChannel<float>(0.75);
		cset->mcForceVel = AnimChannel<float>(0.2);
		cset->mcRadiusVel = AnimChannel<float>(0.75);

		// this value can be left at 0.5:
		cset->mCparts->setCPSMvmWeightFac(0.5);

		mpControl->mCons.push_back( cset );

		// instead of reading from file (cset->mContrPartFile), manually init some particles
		mpControl->mCons[0]->mCparts->initBlenderTest();

		// other values that might be interesting to change:
		//cset->mCparts->setCPSTimestep(0.02);
		//cset->mCparts->setCPSTimeStart(0.);
		//cset->mCparts->setCPSTimeEnd(1.); 

		//mpControl->mDiffVelCon = 1.; // more rigid velocity control, 0 (default) allows more turbulence
	}

	// control particle -------------------------------------------------------------------------------------

	// init cppf stage, use set 0!
	if(mCppfStage>0) {
		if(mpControl->mCpOutfile.length()<1) mpControl->mCpOutfile = string("cpout"); // use getOutFilename !?
		char strbuf[100];
		const char *cpFormat = "_d%dcppf%d";

		// initial coarse stage, no input
		if(mCppfStage==1) {
		 	mpControl->mCons[0]->mContrPartFile = "";
		} else {
			// read from prev stage
			snprintf(strbuf,100, cpFormat  ,LBMDIM,mCppfStage-1);
			mpControl->mCons[0]->mContrPartFile = mpControl->mCpOutfile;
			mpControl->mCons[0]->mContrPartFile += strbuf;
			mpControl->mCons[0]->mContrPartFile += ".cpart2";
		}

		snprintf(strbuf,100, cpFormat  ,LBMDIM,mCppfStage);
		mpControl->mCpOutfile += strbuf;
	} // */
	
	for(int cpssi=0; cpssi<(int)mpControl->mCons.size(); cpssi++) {
		ControlParticles *cparts = mpControl->mCons[cpssi]->mCparts;
		ControlParticles *cpmotion = mpControl->mCons[cpssi]->mCpmotion;

		// now set with real dt
		cparts->setInfluenceVelocity( mpControl->mCons[cpssi]->mcForceVel.get(0.), mLevel[mMaxRefine].timestep);
		cparts->setCharLength( mLevel[mMaxRefine].nodeSize );
		cparts->setCharLength( mLevel[mMaxRefine].nodeSize );
		errMsg("LbmControlData","CppfStage "<<mCppfStage<<" in:"<<mpControl->mCons[cpssi]->mContrPartFile<<
				" out:"<<mpControl->mCpOutfile<<" cl:"<< cparts->getCharLength() );

		// control particle test init
		if(mpControl->mCons[cpssi]->mCpmotionFile.length()>=1) cpmotion->initFromTextFile(mpControl->mCons[cpssi]->mCpmotionFile);
		// not really necessary...
		//? cparts->setFluidSpacing( mLevel[mMaxRefine].nodeSize	); // use grid coords!?
		//? cparts->calculateKernelWeight();
		//? debMsgStd("LbmFsgrSolver::initCpdata",DM_MSG,"ControlParticles - motion inited: "<<cparts->getSize() ,10);

		// ensure both are on for env. var settings
		// when no particles, but outfile enabled, initialize
		const int lev = mMaxRefine;
		if((mpParticles) && (mpControl->mCpOutfile.length()>=1) && (cpssi==0)) {
			// check if auto num
			if( (mpParticles->getNumInitialParticles()<=1) && 
					(mpParticles->getNumParticles()<=1) ) { // initParticles done afterwards anyway
				int tracers = 0;
				const int workSet = mLevel[lev].setCurr;
				FSGR_FORIJK_BOUNDS(lev) { 
					if(RFLAG(lev,i,j,k, workSet)&(CFFluid)) tracers++;
				}
				if(LBMDIM==3) tracers /= 8;
				else          tracers /= 4;
				mpParticles->setNumInitialParticles(tracers);
				mpParticles->setDumpTextFile(mpControl->mCpOutfile);
				debMsgStd("LbmFsgrSolver::initCpdata",DM_MSG,"ControlParticles - set tracers #"<<tracers<<", actual #"<<mpParticles->getNumParticles() ,10);
			}
			if(mpParticles->getDumpTextInterval()<=0.) {
				mpParticles->setDumpTextInterval(mLevel[lev].timestep * mLevel[lev].lSizex);
				debMsgStd("LbmFsgrSolver::initCpdata",DM_MSG,"ControlParticles - dump delta t not set, using dti="<< mpParticles->getDumpTextInterval()<<", sim dt="<<mLevel[lev].timestep, 5 );
			}
			mpParticles->setDumpParts(true); // DEBUG? also dump as particle system
		}

		if(mpControl->mCons[cpssi]->mContrPartFile.length()>=1) cparts->initFromTextFile(mpControl->mCons[cpssi]->mContrPartFile);
		cparts->setFluidSpacing( mLevel[lev].nodeSize	); // use grid coords!?
		cparts->calculateKernelWeight();
		debMsgStd("LbmFsgrSolver::initCpdata",DM_MSG,"ControlParticles mCons"<<cpssi<<" - inited, parts:"<<cparts->getTotalSize()<<","<<cparts->getSize()<<" dt:"<<mpParam->getTimestep()<<" control time:"<<cparts->getControlTimStart()<<" to "<<cparts->getControlTimEnd() ,10);
	} // cpssi
Exemplo n.º 18
0
/******************************************************************************
 * Only dump time dep. objects to file
 *****************************************************************************/
int ntlBlenderDumper::renderScene( void )
{
    char nrStr[5];								/* nr conversion */
    ntlRenderGlobals *glob = mpGlob;
    ntlScene *scene = mpGlob->getSimScene();
    bool debugOut = false;
    bool debugRender = false;
#if ELBEEM_PLUGIN==1
    debugOut = false;
#endif // ELBEEM_PLUGIN==1

    vector<string> gmName; 	 // gm names
    vector<string> gmMat;    // materials for gm
    int numGMs = 0;					 // no. of .obj models created

    if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Dumping geometry data", 1);
    long startTime = getTime();
    snprintf(nrStr, 5, "%04d", glob->getAniCount() );

    // local scene vars
    vector<ntlTriangle> Triangles;
    vector<ntlVec3Gfx>  Vertices;
    vector<ntlVec3Gfx>  VertNormals;

    // check geo objects
    int idCnt = 0;          // give IDs to objects
    for (vector<ntlGeometryClass*>::iterator iter = scene->getGeoClasses()->begin();
            iter != scene->getGeoClasses()->end(); iter++) {
        if(!(*iter)->getVisible()) continue;
        int tid = (*iter)->getTypeId();

        if(tid & GEOCLASSTID_OBJECT) {
            // normal geom. objects -> ignore
        }
        if(tid & GEOCLASSTID_SHADER) {
            ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter);
            string outname = geoshad->getOutFilename();
            if(outname.length()<1) outname = mpGlob->getOutFilename();
            geoshad->notifyShaderOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname);

            for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
                    siter != geoshad->getObjectsEnd();
                    siter++) {
                if(debugOut) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 8);

                (*siter)->notifyOfDump(DUMP_FULLGEOMETRY, glob->getAniCount(),nrStr,outname, this->mSimulationTime);
                bool doDump = false;
                bool isPreview = false;
                // only dump final&preview surface meshes
                if( (*siter)->getName().find( "final" ) != string::npos) {
                    doDump = true;
                } else if( (*siter)->getName().find( "preview" ) != string::npos) {
                    doDump = true;
                    isPreview = true;
                }
                if(!doDump) continue;

                // dont quit, some objects need notifyOfDump call
                if((glob_mpactive) && (glob_mpindex>0)) {
                    continue; //return 0;
                }

                // only dump geo shader objects
                Triangles.clear();
                Vertices.clear();
                VertNormals.clear();
                (*siter)->initialize( mpGlob );
                (*siter)->getTriangles(this->mSimulationTime, &Triangles, &Vertices, &VertNormals, idCnt);
                idCnt ++;

                // WARNING - this is dirty, but simobjs are the only geoshaders right now
                SimulationObject *sim = (SimulationObject *)geoshad;
                LbmSolverInterface *lbm = sim->getSolver();


                // always dump mesh, even empty ones...

                // dump to binary file
                std::ostringstream boutfilename("");
                //boutfilename << ecrpath.str() << outname <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj";
                boutfilename << outname <<"_"<< (*siter)->getName() <<"_" << nrStr;
                if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName()
                                           <<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<<
                                           " to "<<boutfilename.str() , 7);
                gzFile gzf;

                // output velocities if desired
                if((!isPreview) && (lbm->getDumpVelocities())) {
                    std::ostringstream bvelfilename;
                    bvelfilename << boutfilename.str();
                    bvelfilename << ".bvel.gz";
                    gzf = gzopen(bvelfilename.str().c_str(), "wb9");
                    if(gzf) {
                        int numVerts;
                        if(sizeof(numVerts)!=4) {
                            errMsg("ntlBlenderDumper::renderScene","Invalid int size");
                            return 1;
                        }
                        numVerts = Vertices.size();
                        gzwrite(gzf, &numVerts, sizeof(numVerts));
                        for(size_t i=0; i<Vertices.size(); i++) {
                            // returns smoothed velocity, scaled by frame time
                            ntlVec3Gfx v = lbm->getVelocityAt( Vertices[i][0], Vertices[i][1], Vertices[i][2] );
                            // translation not necessary, test rotation & scaling?
                            for(int j=0; j<3; j++) {
                                float vertp = v[j];
                                //if(i<20) errMsg("ntlBlenderDumper","DUMP_VEL final "<<i<<" = "<<v);
                                gzwrite(gzf, &vertp, sizeof(vertp));
                            }
                        }
                        gzclose( gzf );
                    }
                }

                // compress all bobj's
                boutfilename << ".bobj.gz";
                gzf = gzopen(boutfilename.str().c_str(), "wb1"); // wb9 is slow for large meshes!
                if (!gzf) {
                    errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' ");
                    return 1;
                }

                // dont transform velocity output, this is handled in blender
                // current transform matrix
                ntlMatrix4x4<gfxReal> *trafo;
                trafo = lbm->getDomainTrafo();
                if(trafo) {
                    // transform into source space
                    for(size_t i=0; i<Vertices.size(); i++) {
                        Vertices[i] = (*trafo) * Vertices[i];
                    }
                }
                // rotate vertnormals
                ntlMatrix4x4<gfxReal> rottrafo;
                rottrafo.initId();
                if(lbm->getDomainTrafo()) {
                    // dont modifiy original!
                    rottrafo = *lbm->getDomainTrafo();
                    ntlVec3Gfx rTrans,rScale,rRot,rShear;
                    rottrafo.decompose(rTrans,rScale,rRot,rShear);
                    rottrafo.initRotationXYZ(rRot[0],rRot[1],rRot[2]);
                    // only rotate here...
                    for(size_t i=0; i<Vertices.size(); i++) {
                        VertNormals[i] = rottrafo * VertNormals[i];
                        normalize(VertNormals[i]); // remove scaling etc.
                    }
                }


                // write to file
                int numVerts;
                if(sizeof(numVerts)!=4) {
                    errMsg("ntlBlenderDumper::renderScene","Invalid int size");
                    return 1;
                }
                numVerts = Vertices.size();
                gzwrite(gzf, &numVerts, sizeof(numVerts));
                for(size_t i=0; i<Vertices.size(); i++) {
                    for(int j=0; j<3; j++) {
                        float vertp = Vertices[i][j];
                        gzwrite(gzf, &vertp, sizeof(vertp));
                    }
                }

                // should be the same as Vertices.size
                if(VertNormals.size() != (size_t)numVerts) {
                    errMsg("ntlBlenderDumper::renderScene","Normals have to have same size as vertices!");
                    VertNormals.resize( Vertices.size() );
                }
                gzwrite(gzf, &numVerts, sizeof(numVerts));
                for(size_t i=0; i<VertNormals.size(); i++) {
                    for(int j=0; j<3; j++) {
                        float normp = VertNormals[i][j];
                        gzwrite(gzf, &normp, sizeof(normp));
                    }
                }

                int numTris = Triangles.size();
                gzwrite(gzf, &numTris, sizeof(numTris));
                for(size_t i=0; i<Triangles.size(); i++) {
                    for(int j=0; j<3; j++) {
                        int triIndex = Triangles[i].getPoints()[j];
                        gzwrite(gzf, &triIndex, sizeof(triIndex));
                    }
                }
                gzclose( gzf );
                debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY," Wrote: '"<<boutfilename.str()<<"' ", 2);
                numGMs++;
            }
        }

    }

    // output ecr config file
    if(numGMs>0) {
        if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Objects dumped: "<<numGMs, 10);
    } else {
        if((glob_mpactive) && (glob_mpindex>0)) {
            // ok, nothing to do anyway...
        } else {
            errFatal("ntlBlenderDumper::renderScene","No objects to dump! Aborting...",SIMWORLD_INITERROR);
            return 1;
        }
    }

    // debug timing
    long stopTime = getTime();
    debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10);

    // still render for preview...
    if(debugRender) {
        debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1);
        ntlWorld::renderScene();
    }
    else {
        // next frame
        glob->setAniCount( glob->getAniCount() +1 );
    }

    return 0;
}
Exemplo n.º 19
0
int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
{
	if(! isSimworldOk() ) return 1;
	
	// already inited?
	if(mpLbm) return 0;
	
	mpGlob = glob;
	if(!getVisible()) {
		mpAttrs->setAllUsed();
		return 0;
	}


	mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false);
	//mDimension, mSolverType are deprecated
	string mSolverType(""); 
	mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false ); 

	mpLbm = createSolver(); 
  /* check lbm pointer */
	if(mpLbm == NULL) {
		errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR);
		return 2;
	}
	debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2);

	mpParts = new ParticleTracer();

	// for non-param simulations
	mpLbm->setParametrizer( mpParam );
	mpParam->setAttrList( getAttributeList() );
	// not needed.. done in solver_init: mpParam->setSize ... in solver_interface
	mpParam->parseAttrList();

	mpLbm->setAttrList( getAttributeList() );
	mpLbm->setSwsAttrList( getSwsAttributeList() );
	mpLbm->parseAttrList();
	mpParts->parseAttrList( getAttributeList() );

	if(! isSimworldOk() ) return 3;
	mpParts->setName( getName() + "_part" );
	mpParts->initialize( glob );
	if(! isSimworldOk() ) return 4;
	
	// init material settings
	string matMc("default");
	matMc = mpAttrs->readString("material_surf", matMc, "SimulationObject","matMc", false );
	mShowSurface   = mpAttrs->readInt("showsurface", mShowSurface, "SimulationObject","mShowSurface", false ); 
	mShowParticles = mpAttrs->readInt("showparticles", mShowParticles, "SimulationObject","mShowParticles", false ); 

	checkBoundingBox( mGeoStart, mGeoEnd, "SimulationObject::initializeSimulation" );
	mpLbm->setLbmInitId( mGeoInitId );
	mpLbm->setGeoStart( mGeoStart );
	mpLbm->setGeoEnd( mGeoEnd );
	mpLbm->setRenderGlobals( mpGlob );
	mpLbm->setName( getName() + "_lbm" );
	mpLbm->setParticleTracer( mpParts );
	if(mpElbeemSettings) {
		// set further settings from API struct init
		if(mpElbeemSettings->outputPath) this->mOutFilename = string(mpElbeemSettings->outputPath);
		mpLbm->initDomainTrafo( mpElbeemSettings->surfaceTrafo );
		mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing);
		mpLbm->setIsoSubdivs(mpElbeemSettings->surfaceSubdivs);
		mpLbm->setSizeX(mpElbeemSettings->resolutionxyz);
		mpLbm->setSizeY(mpElbeemSettings->resolutionxyz);
		mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz);
		mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz);
		mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine);
		mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles);
		// set initial particles
		mpParts->setNumInitialParticles(mpElbeemSettings->numTracerParticles);
		
		// surface generation flag
		mpLbm->setSurfGenSettings(mpElbeemSettings->mFsSurfGenSetting);

		string dinitType = string("no");
		if     (mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = string("part"); 
		else if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = string("free"); 
		else /*if(mpElbeemSettings->domainobsType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = string("no"); 
		mpLbm->setDomainBound(dinitType);
		mpLbm->setDomainPartSlip(mpElbeemSettings->domainobsPartslip);
		mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors);
		mpLbm->setFarFieldSize(mpElbeemSettings->farFieldSize);
		debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->domainobsPartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 );

		debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10);
	}

	if(! mpLbm->initializeSolverMemory()   )         { errMsg("SimulationObject::initialize","initializeSolverMemory failed"); mPanic=true; return 10; }
	if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverMemory status"); mPanic=true; return 11; } 
	if(! mpLbm->initializeSolverGrids()    )         { errMsg("SimulationObject::initialize","initializeSolverGrids  failed"); mPanic=true; return 12; }
	if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverGrids  status"); mPanic=true; return 13; } 
	if(! mpLbm->initializeSolverPostinit() )         { errMsg("SimulationObject::initialize","initializeSolverPostin failed"); mPanic=true; return 14; }
	if(checkCallerStatus(FLUIDSIM_CBSTATUS_STEP, 0)) { errMsg("SimulationObject::initialize","initializeSolverPostin status"); mPanic=true; return 15; } 

	// print cell type stats
	bool printStats = true;
	if(glob_mpnum>0) printStats=false; // skip in this case
	if(printStats) {
		const int jmax = sizeof(CellFlagType)*8;
		int totalCells = 0;
		int flagCount[jmax];
		for(int j=0; j<jmax ; j++) flagCount[j] = 0;
		int diffInits = 0;
		LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell();
		for(; mpLbm->noEndCell( cid );
					mpLbm->advanceCell( cid ) ) {
			int flag = mpLbm->getCellFlag(cid,0);
			int flag2 = mpLbm->getCellFlag(cid,1);
			if(flag != flag2) {
				diffInits++;
			}
			for(int j=0; j<jmax ; j++) {
				if( flag&(1<<j) ) flagCount[j]++;
			}
			totalCells++;
		}
		mpLbm->deleteCellIterator( &cid );

		char charNl = '\n';
		debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5);
		debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5);
		for(int j=0; j<jmax ; j++) {
			std::ostringstream out;
			if(flagCount[j]>0) {
				out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl;
				debugOutNnl(out.str(), 5);
			}
		}
		// compute dist. of empty/bnd - fluid - if
		// cfEmpty   = (1<<0), cfBnd  = (1<< 2), cfFluid   = (1<<10), cfInter   = (1<<11),
		if(1){
			std::ostringstream out;
			out.precision(2); out.width(4);
			int totNum = flagCount[1]+flagCount[2]+flagCount[7]+flagCount[8];
			double ebFrac = (double)(flagCount[1]+flagCount[2]) / totNum;
			double flFrac = (double)(flagCount[7]) / totNum;
			double ifFrac = (double)(flagCount[8]) / totNum;
			//???
			out<<"\tFractions: [empty/bnd - fluid - interface - ext. if]  =  [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl;

			if(diffInits > 0) {
				debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<"!" , 5);
			}
			debugOutNnl(out.str(), 5);
		}
	} // cellstats

	// might be modified by mpLbm
	//mpParts->setStart( mGeoStart );?  mpParts->setEnd( mGeoEnd );?
	mpParts->setStart( mpLbm->getGeoStart() );
	mpParts->setEnd(   mpLbm->getGeoEnd()   );
	mpParts->setCastShadows( false );
	mpParts->setReceiveShadows( false );
	mpParts->searchMaterial( glob->getMaterials() );

	// this has to be inited here - before, the values might be unknown
	IsoSurface *surf = mpLbm->getSurfaceGeoObj();
	if(surf) {
		surf->setName( "final" ); // final surface mesh 
		// warning - this might cause overwriting effects for multiple sims and geom dump...
		surf->setCastShadows( true );
		surf->setReceiveShadows( false );
		surf->searchMaterial( glob->getMaterials() );
		if(mShowSurface) mObjects.push_back( surf );
	}
	
#ifdef ELBEEM_PLUGIN
	mShowParticles=1; // for e.g. dumping
#endif // ELBEEM_PLUGIN
	if((mpLbm->getGenerateParticles()>0.0)||(mpParts->getNumInitialParticles()>0)) {
		mShowParticles=1;
		mpParts->setDumpParts(true);
	}
		//debMsgStd("SimulationObject::init",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mShowParticles, DEBUG!",1);
	//}  // DEBUG ENABLE!!!!!!!!!!
	if(mShowParticles) {
		mObjects.push_back(mpParts);
	}

	// add objects to display for debugging (e.g. levelset particles)
	vector<ntlGeometryObject *> debugObjs = mpLbm->getDebugObjects();
	for(size_t i=0;i<debugObjs.size(); i++) {
		debugObjs[i]->setCastShadows( false );
		debugObjs[i]->setReceiveShadows( false );
		debugObjs[i]->searchMaterial( glob->getMaterials() );
		mObjects.push_back( debugObjs[i] );
		debMsgStd("SimulationObject::init",DM_NOTIFY,"Added debug obj "<<debugObjs[i]->getName(), 10 );
	}
	return 0;
}
Exemplo n.º 20
0
/******************************************************************************
 * advance simulations by time t 
 *****************************************************************************/
int ntlWorld::advanceSims(int framenum)
{
	bool done = false;
	bool allPanic = true;

	// stop/quit, dont display/render
	if(getElbeemState()==SIMWORLD_STOP) { 
		return 1;
	}

	for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); }
	double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum);

	// time stopped? nothing else to do...
	if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){ 
		done=true; allPanic=false; 
	}

	int gstate = 0;
	myTime_t advsstart = getTime();

	// step all the sims, and check for panic
	debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic<<" gstate:"<<gstate, 10); // debug // timedebug
	while(!done) {
		double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getTimestep();
		singleStepSims(nextTargetTime);

		// check target times
		done = true;
		allPanic = false;
		
		if((*mpSims)[mFirstSim]->getTimestep() <1e-9 ) { 
			// safety check, avoid timesteps that are too small
			errMsg("ntlWorld::advanceSims","Invalid time step, causing panic! curr:"<<(*mpSims)[mFirstSim]->getCurrentTime()<<" next:"<<nextTargetTime<<", stept:"<< (*mpSims)[mFirstSim]->getTimestep() );
			allPanic = true; 
		} else {
			for(size_t i=0;i<mpSims->size();i++) {
				if(!(*mpSims)[i]->getVisible()) continue;
				if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!?
				debMsgStd("ntlWorld::advanceSims",DM_MSG, "Sim "<<i<<", currt:"<<(*mpSims)[i]->getCurrentTime()<<", nt:"<<nextTargetTime<<", panic:"<<(*mpSims)[i]->getPanic()<<", targett:"<<targetTime, 10); // debug // timedebug
			} 
		}
		if( (targetTime - (*mpSims)[mFirstSim]->getCurrentTime()) > LBM_TIME_EPSILON) done=false;
		if(allPanic) done = true;
	}

	if(allPanic) {
		warnMsg("ntlWorld::advanceSims","All sims panicked... stopping thread" );
		setStopRenderVisualization( true );
		return 1;
	}

	myTime_t advsend = getTime();
	debMsgStd("ntlWorld::advanceSims",DM_MSG,"Overall steps so far took:"<< getTimeString(advsend-advsstart)<<" for sim time "<<targetTime, 4);

	// finish step
	for(size_t i=0;i<mpSims->size();i++) {
		SimulationObject *sim = (*mpSims)[i];
		if(!sim->getVisible()) continue;
		if(sim->getPanic()) continue;
		sim->prepareVisualization();
	}

	return 0;
}
Exemplo n.º 21
0
/******************************************************************************
 * Render the current scene
 * uses the global variables from the parser
 *****************************************************************************/
int ntlWorld::renderScene( void )
{
#ifndef ELBEEM_PLUGIN
	char nrStr[5];														// nr conversion 
	std::ostringstream outfn_conv("");  			// converted ppm with other suffix 
  ntlRenderGlobals *glob;                  	// storage for global rendering parameters 
  myTime_t timeStart,totalStart,timeEnd; 		// measure user running time 
  myTime_t rendStart,rendEnd;            		// measure user rendering time 
  glob = mpGlob;

	// deactivate for all with index!=0 
	if((glob_mpactive)&&(glob_mpindex>0)) return(0);

	/* check if picture already exists... */
	if(!glob->getSingleFrameMode() ) {
		snprintf(nrStr, 5, "%04d", glob->getAniCount() );

		if(glob_mpactive) {
			outfn_conv  << glob->getOutFilename() <<"_"<<glob_mpindex<<"_" << nrStr << ".png"; /// DEBUG!
		} else {
			// ORG
			outfn_conv  << glob->getOutFilename() <<"_" << nrStr << ".png";
		}
		
		//if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) {
		if(mpGlob->getFrameSkip()) {
			struct stat statBuf;
			if(stat(outfn_conv.str().c_str(),&statBuf) == 0) {
				errorOut("ntlWorld::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame..."); 
				glob->setAniCount( glob->getAniCount() +1 );
				return(2);
			}
		} // RAY mode
	} else {
		// single frame rendering, overwrite if necessary...
		outfn_conv << glob->getSingleFrameFilename();
	}

  /* start program */
	timeStart = getTime();

	/* build scene geometry, calls buildScene(t,false) */
	glob->getRenderScene()->prepareScene(mSimulationTime);

  /* start program */
	totalStart = getTime();


	/* view parameters are currently not animated */
	/* calculate rays through projection plane */
	ntlVec3Gfx direction = glob->getLookat() - glob->getEye();
	/* calculate width of screen using perpendicular triangle diven by
	 * viewing direction and screen plane */
	gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI );

	/* calculate vector orthogonal to up and viewing direction */
	ntlVec3Gfx upVec = glob->getUpVec();
	ntlVec3Gfx rightVec( cross(upVec,direction) );
	normalize(rightVec);

	/* calculate screen plane up vector, perpendicular to viewdir and right vec */
	upVec = ntlVec3Gfx( cross(rightVec,direction) );
	normalize(upVec);

	/* check if vectors are valid */
	if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) {
		errMsg("ntlWorld::renderScene","Invalid viewpoint vectors! up="<<upVec<<" right="<<rightVec);
		return(1);
	}

	/* length from center to border of screen plane */
	rightVec *= (screenWidth*glob->getAspect() * -1.0);
	upVec *= (screenWidth * -1.0);

	/* screen traversal variables */
	ntlVec3Gfx screenPos;                          /* current position on virtual screen */
	int Xres = glob->getResX();                  /* X resolution */
	int Yres = glob->getResY();                  /* Y resolution */
	ntlVec3Gfx rightStep = (rightVec/(Xres/2.0));  /* one step right for a pixel */
	ntlVec3Gfx upStep    = (upVec/(Yres/2.0));     /* one step up for a pixel */
    

	/* anti alias init */
	char  showAAPic = 0;
	int   aaDepth = glob->getAADepth();
	int   aaLength;
	if(aaDepth>=0) aaLength = (2<<aaDepth);
	else           aaLength = 0;
	float aaSensRed   = 0.1;
	float aaSensGreen = 0.1;
	float aaSensBlue  = 0.1;
	int   aaArrayX = aaLength*Xres+1;
	int   aaArrayY = ( aaLength+1 );
	ntlColor *aaCol = new ntlColor[ aaArrayX*aaArrayY ];
	char  *aaUse = new char[ aaArrayX*aaArrayY ];

	/* picture storage */
	int picX = Xres;
	int picY = Yres;
	if(showAAPic) {
		picX = Xres *aaLength+1;
		picY = Yres *aaLength+1;
	}
	ntlColor *finalPic = new ntlColor[picX * picY];


	/* reset picture vars */
	for(int j=0;j<aaArrayY;j++) {
		for(int i=0;i<aaArrayX;i++) {
			aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0);
			aaUse[j*aaArrayX+i] = 0;
		}
	}
	for(int j=0;j<picY;j++) {
		for(int i=0;i<picX;i++) {
			finalPic[j*picX+i] = ntlColor(0.0, 0.0, 0.0);
		}
	}

	/* loop over all y lines in screen, from bottom to top because
	 * ppm format wants 0,0 top left */
	rendStart = getTime();
	glob->setCounterShades(0);
	glob->setCounterSceneInter(0);
	for (int scanline=Yres ; scanline > 0 ; --scanline) {
    
		debugOutInter( "ntlWorld::renderScene: Line "<<scanline<<
								 " ("<< ((Yres-scanline)*100/Yres) <<"%) ", 2, 2000 );
		screenPos = glob->getLookat() + upVec*((2.0*scanline-Yres)/Yres)
			- rightVec;

		/* loop over all pixels in line */
		for (int sx=0 ; sx < Xres ; ++sx) {

			if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) {
				// DEBUG!!!
				glob->setDebugOut(10);
			} else glob->setDebugOut(0);
			
			/* compute ray from eye through current pixel into scene... */
			ntlColor col;
			if(aaDepth<0) {
				ntlVec3Gfx dir(screenPos - glob->getEye());
				ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob );

				/* ...and trace it */
				col = the_ray.shade();
			} else {
				/* anti alias */
				int ai,aj;                   /* position in grid */
				int aOrg = sx*aaLength;      /* grid offset x */
				int currStep = aaLength;     /* step size */
				char colDiff = 1;            /* do colors still differ too much? */
				ntlColor minCol,maxCol;         /* minimum and maximum Color Values */
				minCol = ntlColor(1.0,1.0,1.0);
				maxCol = ntlColor(0.0,0.0,0.0);

				while((colDiff) && (currStep>0)) {
					colDiff = 0;
	    
					for(aj = 0;aj<=aaLength;aj+= currStep) {
						for(ai = 0;ai<=aaLength;ai+= currStep) {

							/* shade pixel if not done */
							if(aaUse[aj*aaArrayX +ai +aOrg] == 0) {
								aaUse[aj*aaArrayX +ai +aOrg] = 1;
								ntlVec3Gfx aaPos( screenPos +
																(rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) +
																(upStep    * (aj- aaLength/2)/(gfxReal)aaLength ) );

								ntlVec3Gfx dir(aaPos - glob->getEye());
								ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob );

								/* ...and trace it */
								ntlColor newCol= the_ray.shade();
								aaCol[aj*aaArrayX +ai +aOrg]= newCol;
							} /* not used? */

						}
					}

					/* check color differences */
					for(aj = 0;aj<aaLength;aj+= currStep) {
						for(ai = 0;ai<aaLength;ai+= currStep) {

							char thisColDiff = 0;
							if( 
								 (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - 
											 aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) ||
								 (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - 
											 aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) ||
								 (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - 
											 aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) {
								thisColDiff = 1;
							} else
								if( 
									 (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - 
												 aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) ||
									 (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - 
												 aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) ||
									 (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - 
												 aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) {
									thisColDiff = 1;
								} else
									if( 
										 (fabs(aaCol[aj*aaArrayX +ai +aOrg][0] - 
													 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) ||
										 (fabs(aaCol[aj*aaArrayX +ai +aOrg][1] - 
													 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) ||
										 (fabs(aaCol[aj*aaArrayX +ai +aOrg][2] - 
													 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) {
										thisColDiff = 1;
									} 

							//colDiff =1;
							if(thisColDiff) {
								/* set diff flag */
								colDiff = thisColDiff;
								for(int bj=aj;bj<=aj+currStep;bj++) {
									for(int bi=ai;bi<=ai+currStep;bi++) {
										if(aaUse[bj*aaArrayX +bi +aOrg]==2) {
											//if(showAAPic) 
											aaUse[bj*aaArrayX +bi +aOrg] = 0;
										}
									}
								}
							} else {
								/* set all values */
								ntlColor avgCol = (
																	 aaCol[(aj+0       )*aaArrayX +(ai+0       ) +aOrg] +
																	 aaCol[(aj+0       )*aaArrayX +(ai+currStep) +aOrg] +
																	 aaCol[(aj+currStep)*aaArrayX +(ai+0       ) +aOrg] +
																	 aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25;
								for(int bj=aj;bj<=aj+currStep;bj++) {
									for(int bi=ai;bi<=ai+currStep;bi++) {
										if(aaUse[bj*aaArrayX +bi +aOrg]==0) {
											aaCol[bj*aaArrayX +bi +aOrg] = avgCol; 
											aaUse[bj*aaArrayX +bi +aOrg] = 2;
										}
									}
								}
							} /* smaller values set */

						}
					}

					/* half step size */
					currStep /= 2;

				} /* repeat until diff not too big */

				/* get average color */
				gfxReal colNum = 0.0;
				col = ntlColor(0.0, 0.0, 0.0);
				for(aj = 0;aj<=aaLength;aj++) {
					for(ai = 0;ai<=aaLength;ai++) {
						col += aaCol[aj*aaArrayX +ai +aOrg];
						colNum += 1.0;
					}
				}
				col /= colNum;

			}

		  /* mark pixels with debugging */
			if( glob->getDebugOut() > 0) col = ntlColor(0,1,0);

			/* store pixel */
			if(!showAAPic) {
				finalPic[(scanline-1)*picX+sx] = col; 
			}
			screenPos +=  rightStep;

		} /* foreach x */

		/* init aa array */
		if(showAAPic) {
			for(int j=0;j<=aaArrayY-1;j++) {
				for(int i=0;i<=aaArrayX-1;i++) {
					if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0;
				}
			}
		}

		for(int i=0;i<aaArrayX;i++) {
			aaCol[(aaArrayY-1)*aaArrayX+i] = aaCol[0*aaArrayX+i];
			aaUse[(aaArrayY-1)*aaArrayX+i] = aaUse[0*aaArrayX+i];
		}
		for(int j=0;j<aaArrayY-1;j++) {
			for(int i=0;i<aaArrayX;i++) {
				aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0);
				aaUse[j*aaArrayX+i] = 0;
			}
		}

	} /* foreach y */
	rendEnd = getTime();


	/* write png file */
	{
		int w = picX;
		int h = picY;

		unsigned rowbytes = w*4;
		unsigned char *screenbuf, **rows;
		screenbuf = (unsigned char*)malloc( h*rowbytes );
		rows = (unsigned char**)malloc( h*sizeof(unsigned char*) );
		unsigned char *filler = screenbuf;

		// cutoff color values 0..1
		for(int j=0;j<h;j++) {
			for(int i=0;i<w;i++) {
				ntlColor col = finalPic[j*w+i];
				for (unsigned int cc=0; cc<3; cc++) {
					if(col[cc] <= 0.0) col[cc] = 0.0;
					if(col[cc] >= 1.0) col[cc] = 1.0;
				}
				*filler = (unsigned char)( col[0]*255.0 ); 
				filler++;
				*filler = (unsigned char)( col[1]*255.0 ); 
				filler++;
				*filler = (unsigned char)( col[2]*255.0 ); 
				filler++;
				*filler = (unsigned char)( 255.0 ); 
				filler++; // alpha channel
			}
		}

		for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ];
		writePng(outfn_conv.str().c_str(), rows, w, h);
	}


	// next frame 
	glob->setAniCount( glob->getAniCount() +1 );

	// done 
	timeEnd = getTime();

	char resout[1024];
	snprintf(resout,1024, "NTL Done %s, frame %d/%d (took %s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n", 
				 outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1),
				 getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(),
				 glob->getCounterShades(),
				 glob->getCounterSceneInter() );
	debMsgStd("ntlWorld::renderScene",DM_MSG, resout, 1 );

	/* clean stuff up */
	delete [] aaCol;
	delete [] aaUse;
	delete [] finalPic;
	glob->getRenderScene()->cleanupScene();

	if(mpGlob->getSingleFrameMode() ) {
		debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 );
		return 1;
	}
#endif // ELBEEM_PLUGIN
	return 0;
}
Exemplo n.º 22
0
ParticleTracer::~ParticleTracer() {
	debMsgStd("ParticleTracer::~ParticleTracer",DM_MSG,"destroyed",10);
}
Exemplo n.º 23
0
//ntlTree::ntlTree(int depth, int objnum, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, vector<ntlTriangle> *trilist) :
ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
  mStart(0.0), mEnd(0.0), mMaxDepth( depth ), mMaxListLength( objnum ), mpRoot( NULL) ,
  mpNodeStack( NULL), mpTBB( NULL ),
	mTriangleMask( 0xFFFF ),
  mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0)
{  
	// init scene data pointers
	mpVertices = scene->getVertexPointer();
	mpVertNormals = scene->getVertexNormalPointer();
	mpTriangles = scene->getTrianglePointer();
	mTriangleMask = triFlagMask;

  if(mpTriangles == NULL) {
    errFatal( "ntlTree Cons","no triangle list!\n",SIMWORLD_INITERROR);
    return;
  }
  if(mpTriangles->size() == 0) {
    warnMsg( "ntlTree::ntlTree","No triangles ("<< mpTriangles->size()  <<")!\n");
		mStart = mEnd = ntlVec3Gfx(0,0,0);
    return;
  }
  if(depth>=BSP_STACK_SIZE) {
    errFatal( "ntlTree::ntlTree","Depth to high ("<< mMaxDepth  <<")!\n", SIMWORLD_INITERROR );
    return;
  }

  /* check triangles (a bit inefficient, but we dont know which vertices belong
     to this tree), and generate bounding boxes */
	mppTriangles = new vector<ntlTriangle *>;
	int noOfTriangles = mpTriangles->size();
	mpTBB = new TriangleBBox[ noOfTriangles ];
	int bbCount = 0;
  mStart = mEnd = (*mpVertices)[ mpTriangles->front().getPoints()[0] ];
	//errMsg("TreeDebug","Start");
  for (vector<ntlTriangle>::iterator iter = mpTriangles->begin();
       iter != mpTriangles->end(); 
       iter++ ) {
		//errorOut(" d "<< convertFlags2String((int)(*iter).getFlags()) <<" "<< convertFlags2String( (int)mTriangleMask)<<" add? "<<( ((int)(*iter).getFlags() & (int)mTriangleMask) != 0 ) );
		// discard triangles that dont match mask
		if( ((int)(*iter).getFlags() & (int)mTriangleMask) == 0 ) {
			continue;
		}

		// test? TODO
		ntlVec3Gfx tnormal = (*mpVertNormals)[ (*iter).getPoints()[0] ]+
			(*mpVertNormals)[ (*iter).getPoints()[1] ]+
			(*mpVertNormals)[ (*iter).getPoints()[2] ];
		ntlVec3Gfx triangleNormal = (*iter).getNormal();
		if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) continue;
		if( equal(       tnormal, ntlVec3Gfx(0.0)) ) continue;
		// */

		ntlVec3Gfx bbs, bbe;
		//errMsg("TreeDebug","Triangle");
		for(int i=0;i<3;i++) {
			int index = (*iter).getPoints()[i];
			ntlVec3Gfx tp = (*mpVertices)[ index ];
			//errMsg("TreeDebug","  Point "<<i<<" = "<<tp<<" ");
			if(tp[0] < mStart[0]) mStart[0]= tp[0];
			if(tp[0] > mEnd[0])   mEnd[0]= tp[0];
			if(tp[1] < mStart[1]) mStart[1]= tp[1];
			if(tp[1] > mEnd[1])   mEnd[1]= tp[1];
			if(tp[2] < mStart[2]) mStart[2]= tp[2];
			if(tp[2] > mEnd[2])   mEnd[2]= tp[2];
			if(i==0) {
				bbs = bbe = tp; 
			} else {
				if( tp[0] < bbs[0] ) bbs[0] = tp[0];
				if( tp[0] > bbe[0] ) bbe[0] = tp[0];
				if( tp[1] < bbs[1] ) bbs[1] = tp[1];
				if( tp[1] > bbe[1] ) bbe[1] = tp[1];
				if( tp[2] < bbs[2] ) bbs[2] = tp[2];
				if( tp[2] > bbe[2] ) bbe[2] = tp[2];
			}
		}
		mppTriangles->push_back( &(*iter) );
		//errMsg("TreeDebug","Triangle "<<(*mpVertices)[(*iter).getPoints()[0]]<<" "<<(*mpVertices)[(*iter).getPoints()[1]]<<" "<<(*mpVertices)[(*iter).getPoints()[2]]<<" ");

		// add BB
		mpTBB[ bbCount ].start = bbs;
		mpTBB[ bbCount ].end = bbe;
		(*iter).setBBoxId( bbCount );
		bbCount++;
  }
	
	

  /* slighlty enlarge bounding tolerance for tree 
     to avoid problems with triangles paralell to slabs */
  mStart -= ntlVec3Gfx( getVecEpsilon() );
  mEnd   += ntlVec3Gfx( getVecEpsilon() );

  /* init root node and stack */
  mpNodeStack = new BSPStack;
  mpRoot = new BSPNode;
  mpRoot->min = mStart;
  mpRoot->max = mEnd;
  mpRoot->axis = AXIS_X;
  mpRoot->members = mppTriangles;
	mpRoot->child[0] = mpRoot->child[1] = NULL;
	mpRoot->cloneVec = 0;
	globalSortingPoints = mpVertices;
	mpTriDist = new char[ mppTriangles->size() ];
	mNumNodes = 1;
	mAbortSubdiv = 0;

  /* create tree */
  debugOutInter( "Generating BSP Tree...  (Nodes "<< mCurrentNodes <<
						", Depth "<<mCurrentDepth<< ") ", 2, 2000 );
  subdivide(mpRoot, 0, AXIS_X);
  debMsgStd("ntlTree::ntlTree",DM_MSG,"Generated Tree: Nodes "<< mCurrentNodes <<
							 ", Depth "<<mCurrentDepth<< " with "<<noOfTriangles<<" triangles", 2 );

	delete [] mpTriDist;
	delete [] mpTBB;
	mpTriDist = NULL;
	mpTBB = NULL;

	/* calculate some stats about tree */
	int noLeafs = 0;
	gfxReal avgDepth = 0.0;
	gfxReal triPerLeaf = 0.0;
	int totalTris = 0;
	
	calcStats(mpRoot,0, noLeafs, avgDepth, triPerLeaf, totalTris);
	avgDepth /= (gfxReal)noLeafs;
	triPerLeaf /= (gfxReal)noLeafs;
	debMsgStd("ntlTree::ntlTree",DM_MSG,"Tree ("<<doSort<<","<<chooseAxis<<") Stats: Leafs:"<<noLeafs<<", avgDepth:"<<avgDepth<<
			", triPerLeaf:"<<triPerLeaf<<", triDoubles:"<<mTriDoubles<<", totalTris:"<<totalTris
			<<" nodes:"<<mNumNodes
			//<<" T"<< (totalTris%3)  // 0=ich, 1=f, 2=a
			, 2 );

	if(mAbortSubdiv) {
		errMsg("ntlTree::ntlTree","Aborted... "<<mNumNodes);
  	deleteNode(mpRoot);
		mpRoot = NULL;
	}
}