Sorry for the big commit, but I've been fixing many of these

issues in parallel... So this commit contains: an update of
the solver (e.g. moving objects), integration of blender IPOs,
improved rendering (motion blur, smoothed normals) and a first particle
test. In more detail:

Solver update:
- Moving objects using a relatively simple model, and not yet fully optimized - ok
  for box falling into water, water in a moving glass might cause trouble. Simulation
  times are influenced by overall no. of triangles of the mesh, scaling meshes up a lot
  might also cause slowdowns.
- Additional obstacle settings: noslip (as before), free slip (move along wall freely)
  and part slip (mix of both).
- Obstacle settings also added for domain boundaries now, the six walls of the domain are
  obstacles after all as well
- Got rid of templates, should make compiling for e.g. macs more convenient,
  for linux there's not much difference. Finally got rid of parser (and some other code
  parts), the simulation now uses the internal API to transfer data.
- Some unnecessary file were removed, the GUI now needs 3 settings buttons...
  This should still be changed (maybe by adding a new panel for domain objects).

IPOs:
- Animated params: viscosity, time and gravity for domains. In contrast
  to normal time IPO for Blender objects, the fluidsim one scales the time
  step size - so a constant 1 has no effect, values towards 0 slow it down,
  larger ones speed the simulation up (-> longer time steps, more compuations).
  The viscosity IPO is also only a factor for the selected viscosity (again, 1=no effect).
- For objects that are enabled for fluidsim, a new IPO type shows up. Inflow
  objects can use the velocity channels to animate the inflow. Obstacles, in/outflow
  objects can be switched on (Active IPO>0) and off (<0) during the simulation.
- Movement, rotation and scaling of those 3 types is exported from the normal
  Blender channels (Loc,dLoc,etc.).

Particles:
- This is still experimental, so it might be deactivated for a
  release... It should at some point be used to model smaller splashes,
  depending on the the realworld size and the particle generation
  settings particles are generated during simulation (stored in _particles_X.gz
  files).
- These are loaded by enabling the particle field for an arbitrary object,
  which should be given a halo material. For each frame, similar to the mesh
  loading, the particle system them loads the simulated particle positions.
- For rendering, I "abused" the part->rt field - I couldnt find any use
  for it in the code and it seems to work fine. The fluidsim particles
  store their size there.

Rendering:
- The fluidims particles use scaled sizes and alpha values to give a more varied
  appearance. In convertblender.c fluidsim particle systems use the p->rt field
  to scale up the size and down the alpha of "smaller particles". Setting the
  influence fields in the fluidims settings to 0 gives equally sized particles
  with same alpha everywhere. Higher values cause larger differences.
- Smoothed normals: for unmodified fluid meshes (e.g. no subdivision) the normals
  computed by the solver are used. This is basically done by switching off the
  normal recalculation in convertblender.c (the function calc_fluidsimnormals
  handles other mesh inits instead of calc_vertexnormals).
  This could also be used to e.g. modify mesh normals in a modifier...
- Another change is that fluidsim meshes load the velocities computed
  during the simulation for image based motion blur. This is inited in
  load_fluidsimspeedvectors for the vector pass (they're loaded during the
  normal load in DerivedMesh readBobjgz). Generation and loading can be switched
  off in the settings. Vector pass currently loads the fluidism meshes 3 times,
  so this should still be optimized.

Examples:
- smoothed normals versus normals from subdividing once:
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_1smoothnorms.png
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_2subdivnorms.png
- fluidsim particles, size/alpha influence 0:
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_3particlesnorm.png
  size influence 1:
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_4particlessize.png
  size & alpha influence 1:
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/v060227_5particlesalpha.png
- the standard drop with motion blur and particles:
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/elbeemupdate_t2new.mpg
  (here's how it looks without
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/elbeemupdate_t1old.mpg)
- another inflow animation (moving, switched on/off) with a moving obstacle
  (and strong mblur :)
  http://www10.informatik.uni-erlangen.de/~sinithue/temp/elbeemupdate_t3ipos.mpg

Things still to fix:
- rotating & scaling domains causes wrong speed vectors
- get rid of SDL code for threading, use pthreads as well?
- update wiki documentation
- cool effects for rendering would be photon maps for caustics,
  and motion blur for particles :)
This commit is contained in:
2006-02-27 11:45:42 +00:00
parent b7ff45f914
commit 9a36e9b651
70 changed files with 8183 additions and 5503 deletions

View File

@@ -1,21 +1,9 @@
#!/usr/bin/python
import sys
import os
Import('env')
#if use_fluidsim=='false':
# # print "El'Beem Fluid Simulation Disabled..." # debug
# elbeem_env.Append (CPPPATH = user_options_dict['PNG_INCLUDE'])
# elbeem_env.Append (CPPPATH = user_options_dict['SDL_INCLUDE'])
# elbeem_env.Append(CPPDEFINES= 'ELBEEM_DUMMIES');
# # dummy interface build
# Sources = [
# "intern/utilities.cpp",
# "intern/blenderdummy.cpp"
# ]; # sources
import('env')
sources = env.Glob('intern/*.cpp')
sources.remove('intern'+os.sep+'blenderdummy.cpp')
defs = 'NOGUI ELBEEM_BLENDER=1'
if env['OURPLATFORM']=='win32-vc':

View File

@@ -53,7 +53,7 @@ void fluidsimBake(struct Object* ob);
/* read & write bobj / bobj.gz files (e.g. for fluid sim surface meshes) */
void writeBobjgz(char *filename, struct Object *ob);
struct Mesh* readBobjgz(char *filename, struct Mesh *orgmesh);
struct Mesh* readBobjgz(char *filename, struct Mesh *orgmesh, float* bbstart, float *bbsize);
/* create derived mesh for fluid sim objects */
// WARNING - currently implemented in DerivedMesh.c!
@@ -66,7 +66,7 @@ int performElbeemSimulation(char *cfgfilename);
/* init axis aligned BB for mesh object */
// implemented in source/blender/blenkernel/intern/DerivedMesh.c
void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] );
/*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh );
// implemented in intern/elbeem/utilities.cpp
/* set elbeem debug output level (0=off to 10=full on) */

View File

@@ -8,12 +8,17 @@
*****************************************************************************/
#include "attributes.h"
#include "ntl_matrices.h"
#include "elbeem.h"
#include <sstream>
//! output attribute values? on=1/off=0
#define DEBUG_ATTRIBUTES 0
//! output channel values? on=1/off=0
#define DEBUG_CHANNELS 0
/******************************************************************************
* attribute conversion functions
@@ -70,20 +75,19 @@ bool Attribute::initChannel(int elemSize) {
mValue = newvalue;
mChannelInited = elemSize;
print();
if(DEBUG_CHANNELS) print();
return true;
}
// get value as string
string Attribute::getAsString()
string Attribute::getAsString(bool debug)
{
if(mIsChannel) {
if(mIsChannel && (!debug)) {
errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string is a channel! Not allowed...");
print();
return string("");
}
if(mValue.size()!=1) {
//errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string has invalid value '"<< getCompleteString() <<"' ");
// for directories etc. , this might be valid! cutoff "..." first
string comp = getCompleteString();
if(comp.size()<2) return string("");
@@ -215,7 +219,7 @@ ntlVec3d Attribute::getAsVec3d()
}
// get value as 4x4 matrix
ntlMat4Gfx Attribute::getAsMat4Gfx()
void Attribute::getAsMat4Gfx(ntlMat4Gfx *mat)
{
bool success = true;
ntlMat4Gfx ret(0.0);
@@ -265,9 +269,10 @@ ntlMat4Gfx Attribute::getAsMat4Gfx()
#if ELBEEM_PLUGIN!=1
gElbeemState = -4; // parse error
#endif
return ntlMat4Gfx(0.0);
*mat = ntlMat4Gfx(0.0);
return;
}
return ret;
*mat = ret;
}
@@ -355,7 +360,7 @@ bool AttributeList::checkUnusedParams()
i != mAttrs.end(); i++) {
if((*i).second) {
if(!(*i).second->getUsed()) {
errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString() <<"' ");
errMsg("AttributeList::checkUnusedParams", "List "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString(true) <<"' ");
found = true;
}
}
@@ -409,7 +414,7 @@ string AttributeList::readString(string name, string defaultValue, string source
}
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
find(name)->setUsed(true);
return find(name)->getAsString();
return find(name)->getAsString(false);
}
ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed) {
if(!exists(name)) {
@@ -421,14 +426,16 @@ ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string sou
return find(name)->getAsVec3d();
}
ntlMat4Gfx AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed) {
void AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed, ntlMat4Gfx *mat) {
if(!exists(name)) {
if(needed) { errFatal("AttributeList::readInt","Required attribute '"<<name<<"' for "<< source <<" not set! ", SIMWORLD_INITERROR); }
return defaultValue;
*mat = defaultValue;
return;
}
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
find(name)->setUsed(true);
return find(name)->getAsMat4Gfx();
find(name)->getAsMat4Gfx( mat );
return;
}
// set that a parameter can be given, and will be ignored...
@@ -442,15 +449,39 @@ bool AttributeList::ignoreParameter(string name, string source) {
// read channels
AnimChannel<double> AttributeList::readChannelFloat(string name) {
if(!exists(name)) { return AnimChannel<double>(0.0); }
return find(name)->getChannelFloat();
AnimChannel<double> ret = find(name)->getChannelFloat();
find(name)->setUsed(true);
channelSimplifyd(ret);
return ret;
}
AnimChannel<int> AttributeList::readChannelInt(string name) {
if(!exists(name)) { return AnimChannel<int>(0); }
return find(name)->getChannelInt();
AnimChannel<int> ret = find(name)->getChannelInt();
find(name)->setUsed(true);
channelSimplifyi(ret);
return ret;
}
AnimChannel<ntlVec3d> AttributeList::readChannelVec3d(string name) {
if(!exists(name)) { return AnimChannel<ntlVec3d>(0.0); }
return find(name)->getChannelVec3d();
AnimChannel<ntlVec3d> ret = find(name)->getChannelVec3d();
find(name)->setUsed(true);
channelSimplifyVd(ret);
return ret;
}
AnimChannel<ntlVec3f> AttributeList::readChannelVec3f(string name) {
if(!exists(name)) { return AnimChannel<ntlVec3f>(0.0); }
AnimChannel<ntlVec3d> convert = find(name)->getChannelVec3d();
// convert to float
vector<ntlVec3f> vals;
for(size_t i=0; i<convert.accessValues().size(); i++) {
vals.push_back( vec2F(convert.accessValues()[i]) );
}
vector<double> times = convert.accessTimes();
AnimChannel<ntlVec3f> ret(vals, times);
find(name)->setUsed(true);
channelSimplifyVf(ret);
return ret;
}
/******************************************************************************
@@ -509,7 +540,6 @@ void AttributeList::print()
}
/******************************************************************************
* import attributes from other attribute list
*****************************************************************************/
@@ -526,5 +556,133 @@ void AttributeList::import(AttributeList *oal)
}
/******************************************************************************
* channel max finding
*****************************************************************************/
ntlVec3f channelFindMaxVf (AnimChannel<ntlVec3f> channel) {
ntlVec3f ret(0.0);
float maxLen = 0.0;
for(size_t i=0; i<channel.accessValues().size(); i++) {
float nlen = normNoSqrt(channel.accessValues()[i]);
if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
}
return ret;
}
ntlVec3d channelFindMaxVd (AnimChannel<ntlVec3d> channel) {
ntlVec3d ret(0.0);
float maxLen = 0.0;
for(size_t i=0; i<channel.accessValues().size(); i++) {
float nlen = normNoSqrt(channel.accessValues()[i]);
if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
}
return ret;
}
int channelFindMaxi (AnimChannel<float > channel) {
int ret = 0;
float maxLen = 0.0;
for(size_t i=0; i<channel.accessValues().size(); i++) {
float nlen = ABS(channel.accessValues()[i]);
if(nlen>maxLen) { ret= (int)channel.accessValues()[i]; maxLen=nlen; }
}
return ret;
}
float channelFindMaxf (AnimChannel<float > channel) {
float ret = 0.0;
float maxLen = 0.0;
for(size_t i=0; i<channel.accessValues().size(); i++) {
float nlen = ABS(channel.accessValues()[i]);
if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
}
return ret;
}
double channelFindMaxd (AnimChannel<double > channel) {
double ret = 0.0;
float maxLen = 0.0;
for(size_t i=0; i<channel.accessValues().size(); i++) {
float nlen = ABS(channel.accessValues()[i]);
if(nlen>maxLen) { ret=channel.accessValues()[i]; maxLen=nlen; }
}
return ret;
}
/******************************************************************************
// unoptimized channel simplification functions, use elbeem.cpp functions
// warning - currently only with single precision
*****************************************************************************/
template<class SCALAR>
static bool channelSimplifyScalarT(AnimChannel<SCALAR> &channel) {
int size = channel.getSize();
if(size<=1) return false;
float *nchannel = new float[2*size];
if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() );
// convert to array
for(size_t i=0; i<channel.accessValues().size(); i++) {
nchannel[i*2 + 0] = (float)channel.accessValues()[i];
nchannel[i*2 + 1] = (float)channel.accessTimes()[i];
}
bool ret = elbeemSimplifyChannelFloat(nchannel, &size);
if(ret) {
vector<SCALAR> vals;
vector<double> times;
for(int i=0; i<size; i++) {
vals.push_back( (SCALAR)(nchannel[i*2 + 0]) );
times.push_back( (double)(nchannel[i*2 + 1]) );
}
channel = AnimChannel<SCALAR>(vals, times);
if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() );
}
delete [] nchannel;
return ret;
}
bool channelSimplifyi (AnimChannel<int > &channel) { return channelSimplifyScalarT<int>(channel); }
bool channelSimplifyf (AnimChannel<float> &channel) { return channelSimplifyScalarT<float>(channel); }
bool channelSimplifyd (AnimChannel<double > &channel) { return channelSimplifyScalarT<double>(channel); }
template<class VEC>
static bool channelSimplifyVecT(AnimChannel<VEC> &channel) {
int size = channel.getSize();
if(size<=1) return false;
float *nchannel = new float[4*size];
if(DEBUG_CHANNELS) errMsg("channelSimplifyf","S" << channel.printChannel() );
// convert to array
for(size_t i=0; i<channel.accessValues().size(); i++) {
nchannel[i*4 + 0] = (float)channel.accessValues()[i][0];
nchannel[i*4 + 1] = (float)channel.accessValues()[i][1];
nchannel[i*4 + 2] = (float)channel.accessValues()[i][2];
nchannel[i*4 + 3] = (float)channel.accessTimes()[i];
}
bool ret = elbeemSimplifyChannelVec3(nchannel, &size);
if(ret) {
vector<VEC> vals;
vector<double> times;
for(int i=0; i<size; i++) {
vals.push_back( VEC(nchannel[i*4 + 0], nchannel[i*4 + 1], nchannel[i*4 + 2] ) );
times.push_back( (double)(nchannel[i*4 + 3]) );
}
channel = AnimChannel<VEC>(vals, times);
if(DEBUG_CHANNELS) errMsg("channelSimplifyf","C" << channel.printChannel() );
}
delete [] nchannel;
return ret;
}
bool channelSimplifyVf (AnimChannel<ntlVec3f> &channel) {
return channelSimplifyVecT<ntlVec3f>(channel);
}
bool channelSimplifyVd (AnimChannel<ntlVec3d> &channel) {
return channelSimplifyVecT<ntlVec3d>(channel);
}
template<class Scalar>
string AnimChannel<Scalar>::printChannel() {
std::ostringstream ostr;
ostr << " CHANNEL #"<< mValue.size() <<" = { ";
for(size_t i=0;i<mValue.size();i++) {
ostr <<"'"<< mValue[i]<<"' ";
ostr << "@"<<mTimes[i]<<"; ";
}
ostr << " } ";
return ostr.str();
} // */

View File

@@ -11,7 +11,7 @@
#ifndef NTL_ATTRIBUTES_H
#include "utilities.h"
#include "ntl_matrices.h"
template<class T> class ntlMatrix4x4;
//! An animated attribute channel
@@ -19,19 +19,24 @@ template<class Scalar>
class AnimChannel
{
public:
// default constructor
AnimChannel() :
mValue(), mTimes() { mInited = false; }
// null init constructor
AnimChannel(Scalar null) :
mValue(1), mTimes(1) { mValue[0]=null; mTimes[0]=0.0; };
mValue(1), mTimes(1) { mValue[0]=null; mTimes[0]=0.0; mInited = true; }
// proper init
AnimChannel(vector<Scalar> v, vector<double> t) :
mValue(v), mTimes(t) { };
mValue(v), mTimes(t) { mInited = true; }
// desctructor, nothing to do
~AnimChannel() { };
// get interpolated value at time t
Scalar get(double t) {
if(!mInited) { Scalar null; null=(Scalar)(0.0); return null; }
if(t<=mTimes[0]) { return mValue[0]; }
if(t>=mTimes[mTimes.size()-1]) { return mValue[mTimes.size()-1]; }
for(size_t i=0; i<mTimes.size()-1; i++) {
@@ -40,7 +45,7 @@ class AnimChannel
// interpolate
double d = mTimes[i+1]-mTimes[i];
double f = (t-mTimes[i])/d;
return mValue[i] * (1.0-f) + mValue[i+1] * f;
return (Scalar)(mValue[i] * (1.0-f) + mValue[i+1] * f);
}
}
// whats this...?
@@ -50,6 +55,7 @@ class AnimChannel
// get uninterpolated value at time t
Scalar getConstant(double t) {
//errMsg("DEBB","getc"<<t<<" ");
if(!mInited) { Scalar null; null=(Scalar)0.0; return null; }
if(t<=mTimes[0]) { return mValue[0]; }
if(t>=mTimes[mTimes.size()-1]) { return mValue[mTimes.size()-1]; }
for(size_t i=0; i<mTimes.size()-1; i++) {
@@ -69,14 +75,29 @@ class AnimChannel
mTimes.push_back(0.0);
}
//! debug function, prints channel as string
string printChannel();
//! valid init?
bool isInited() { return mInited; }
//! get number of entries (value and time sizes have to be equal)
int getSize() { return mValue.size(); };
//! raw access of value vector
vector<Scalar> &accessValues() { return mValue; }
//! raw access of time vector
vector<double> &accessTimes() { return mTimes; }
protected:
/*! inited at least once? */
bool mInited;
/*! anim channel attribute values */
vector<Scalar> mValue;
/*! anim channel attr times */
vector<double> mTimes;
};
//! A single attribute
class Attribute
{
@@ -106,7 +127,7 @@ class Attribute
bool getIsChannel() { return mIsChannel; }
//! get value as string
string getAsString();
string getAsString(bool debug=false);
//! get value as integer value
int getAsInt();
//! get value as boolean
@@ -116,13 +137,13 @@ class Attribute
//! get value as 3d vector
ntlVec3d getAsVec3d();
//! get value as 4x4 matrix
ntlMat4Gfx getAsMat4Gfx();
void getAsMat4Gfx(ntlMatrix4x4<gfxReal> *mat);
//! get channel as integer value
AnimChannel<int> getChannelInt();
//! get channel as double value
AnimChannel<double> getChannelFloat();
//! get channel as double value
//! get channel as double vector
AnimChannel<ntlVec3d> getChannelVec3d();
//! get the concatenated string of all value string
@@ -207,11 +228,12 @@ class AttributeList
double readFloat(string name, double defaultValue, string source,string target, bool needed);
string readString(string name, string defaultValue, string source,string target, bool needed);
ntlVec3d readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed);
ntlMat4Gfx readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed);
void readMat4Gfx(string name, ntlMatrix4x4<gfxReal> defaultValue, string source,string target, bool needed, ntlMatrix4x4<gfxReal> *mat);
//! read attributes channels (attribute should be inited before)
AnimChannel<int> readChannelInt(string name);
AnimChannel<double> readChannelFloat(string name);
AnimChannel<ntlVec3d> readChannelVec3d(string name);
AnimChannel<ntlVec3f> readChannelVec3f(string name);
//! set that a parameter can be given, and will be ignored...
bool ignoreParameter(string name, string source);
@@ -229,6 +251,19 @@ class AttributeList
};
ntlVec3f channelFindMaxVf (AnimChannel<ntlVec3f> channel);
ntlVec3d channelFindMaxVd (AnimChannel<ntlVec3d> channel);
int channelFindMaxi (AnimChannel<int > channel);
float channelFindMaxf (AnimChannel<float > channel);
double channelFindMaxd (AnimChannel<double > channel);
// unoptimized channel simplification functions, use elbeem.cpp functions
bool channelSimplifyVf (AnimChannel<ntlVec3f> &channel);
bool channelSimplifyVd (AnimChannel<ntlVec3d> &channel);
bool channelSimplifyi (AnimChannel<int > &channel);
bool channelSimplifyf (AnimChannel<float > &channel);
bool channelSimplifyd (AnimChannel<double > &channel);
#define NTL_ATTRIBUTES_H
#endif

View File

@@ -1,44 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2005 Nils Thuerey
*
* Blender call interface
*
*****************************************************************************/
#include "globals.h"
#include "utilities.h"
#include "ntl_blenderdumper.h"
#include <stdlib.h>
// ELBEEM_BLENDER always =1 here
extern "C" void elbeemCheckDebugEnv(void);
extern "C"
int performElbeemSimulation(char *cfgfilename) {
gElbeemState = SIMWORLD_INVALID;
strcpy(gElbeemErrorString,"[none]");
//if(gDebugLevel>0) {
elbeemCheckDebugEnv();
debMsgStd("performElbeemSimulation",DM_NOTIFY,"Running El'Beem from Blender with file '"<< cfgfilename <<"', debugLevel:"<<gDebugLevel<<" ...\n", 2);
//}
// load given file in command line mode
ntlBlenderDumper elbeem(cfgfilename, true);
if(SIMWORLD_OK()) {
gElbeemState = SIMWORLD_INITED;
myTime_t timestart = getTime();
elbeem.renderAnimation();
myTime_t timeend = getTime();
debMsgStd("performElbeemSimulation",DM_NOTIFY, "El'Beem simulation done, time: "<<((timeend-timestart)/(double)1000.0) <<" seconds.\n", 2 );
} else {
// signal there was an initialization problem
setGlobalBakeState( -2 );
}
return 1;
};

View File

@@ -1,19 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2005 Nils Thuerey
*
* Blender call for disabled fluidsim
*
*****************************************************************************/
#include <stdlib.h>
extern "C"
int performElbeemSimulation(char *cfgfilename) {
return 1;
};

File diff suppressed because it is too large Load Diff

View File

@@ -299,19 +299,17 @@
int yy_parse( void );
// local variables to access objects
#include "solver_interface.h"
#include "simulation_object.h"
#ifdef LBM_INCLUDE_TESTSOLVERS
#include "simulation_complbm.h"
#endif // LBM_INCLUDE_TESTSOLVERS
#include "parametrizer.h"
#include "ntl_renderglobals.h"
#include "ntl_scene.h"
#include "ntl_lightobject.h"
#include "ntl_material.h"
#include "ntl_world.h"
#include "ntl_ray.h"
#include "ntl_lighting.h"
#include "ntl_geometrymodel.h"
#include "globals.h"
/* global variables */
static map<string,AttributeList*> attrs; /* global attribute storage */
@@ -333,11 +331,11 @@
AttributeList *currentAttrib;
string currentAttrName, currentAttribAddName;
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
#include "ntl_geometrybox.h"
#include "ntl_geometrysphere.h"
ntlGeometryBox *currentGeometryBox;
#endif //ELBEEM_BLENDER
#endif //ELBEEM_PLUGIN
/* material init checks */
ntlMaterial *currentMaterial;
@@ -358,14 +356,14 @@
#endif
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 87 "src/cfgparser.yy"
#line 85 "src/cfgparser.yy"
typedef union YYSTYPE {
int intValue;
float floatValue;
char *charValue;
} YYSTYPE;
/* Line 190 of yacc.c. */
#line 369 "bld-std-gcc/src/cfgparser.cpp"
#line 367 "bld-std-gcc/src/cfgparser.cpp"
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
@@ -377,7 +375,7 @@ typedef union YYSTYPE {
/* Line 213 of yacc.c. */
#line 381 "bld-std-gcc/src/cfgparser.cpp"
#line 379 "bld-std-gcc/src/cfgparser.cpp"
#if ! defined (yyoverflow) || YYERROR_VERBOSE
@@ -609,21 +607,21 @@ static const short int yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const unsigned short int yyrline[] =
{
0, 146, 146, 147, 150, 151, 152, 153, 157, 160,
175, 176, 176, 179, 180, 181, 182, 184, 185, 186,
187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
197, 198, 199, 200, 202, 203, 204, 205, 210, 214,
219, 223, 229, 233, 237, 241, 245, 249, 253, 257,
261, 265, 269, 273, 277, 281, 285, 289, 294, 303,
314, 315, 318, 326, 327, 328, 329, 333, 338, 343,
348, 366, 365, 386, 387, 390, 399, 407, 412, 418,
430, 431, 432, 433, 434, 435, 436, 437, 438, 443,
448, 454, 460, 466, 471, 486, 502, 508, 518, 529,
530, 533, 538, 542, 543, 544, 545, 546, 547, 548,
549, 550, 551, 556, 561, 566, 571, 577, 582, 587,
592, 597, 602, 613, 613, 623, 623, 626, 626, 629,
630, 629, 637, 638, 637, 645, 648, 658, 661, 673,
675, 681, 692, 704
0, 144, 144, 145, 148, 149, 150, 151, 155, 158,
173, 174, 174, 177, 178, 179, 180, 182, 183, 184,
185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
195, 196, 197, 198, 200, 201, 202, 203, 208, 212,
217, 221, 227, 231, 235, 239, 243, 247, 251, 255,
259, 263, 267, 271, 275, 279, 283, 287, 292, 301,
312, 313, 316, 324, 325, 326, 327, 331, 336, 341,
346, 364, 363, 385, 386, 389, 398, 406, 411, 417,
429, 430, 431, 432, 433, 434, 435, 436, 437, 442,
447, 453, 459, 465, 470, 485, 501, 510, 520, 531,
532, 535, 540, 544, 545, 546, 547, 548, 549, 550,
551, 552, 553, 558, 563, 568, 573, 579, 584, 589,
594, 599, 604, 615, 615, 625, 625, 628, 628, 631,
632, 631, 639, 640, 639, 647, 650, 660, 663, 675,
677, 683, 694, 706
};
#endif
@@ -1583,12 +1581,12 @@ yyreduce:
switch (yyn)
{
case 8:
#line 157 "src/cfgparser.yy"
#line 155 "src/cfgparser.yy"
{ yy_debug = (yyvsp[0].intValue); }
break;
case 9:
#line 160 "src/cfgparser.yy"
#line 158 "src/cfgparser.yy"
{
int sdebug = (yyvsp[0].intValue);
if(sdebug<0) sdebug=0;
@@ -1598,114 +1596,114 @@ yyreduce:
break;
case 38:
#line 211 "src/cfgparser.yy"
#line 209 "src/cfgparser.yy"
{ reglob->setAniStart( (yyvsp[0].intValue) ); }
break;
case 39:
#line 215 "src/cfgparser.yy"
#line 213 "src/cfgparser.yy"
{ /*reglob->setAniFrameTime( $2 );*/ debMsgStd("cfgparser",DM_NOTIFY,"Deprecated setting aniframetime!",1); }
break;
case 40:
#line 220 "src/cfgparser.yy"
#line 218 "src/cfgparser.yy"
{ reglob->setAniFrames( ((yyvsp[0].intValue))-1 ); }
break;
case 41:
#line 224 "src/cfgparser.yy"
#line 222 "src/cfgparser.yy"
{ reglob->setFrameSkip( ((yyvsp[0].intValue)) ); }
break;
case 42:
#line 230 "src/cfgparser.yy"
#line 228 "src/cfgparser.yy"
{ reglob->setResX( (yyvsp[-1].intValue) ); reglob->setResY( (yyvsp[0].intValue)); }
break;
case 43:
#line 234 "src/cfgparser.yy"
#line 232 "src/cfgparser.yy"
{ reglob->setAADepth( (yyvsp[0].intValue) ); }
break;
case 44:
#line 238 "src/cfgparser.yy"
#line 236 "src/cfgparser.yy"
{ reglob->setEye( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); }
break;
case 45:
#line 242 "src/cfgparser.yy"
#line 240 "src/cfgparser.yy"
{ reglob->setLookat( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); }
break;
case 46:
#line 246 "src/cfgparser.yy"
#line 244 "src/cfgparser.yy"
{ reglob->setUpVec( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); }
break;
case 47:
#line 250 "src/cfgparser.yy"
#line 248 "src/cfgparser.yy"
{ reglob->setFovy( (yyvsp[0].floatValue) ); }
break;
case 48:
#line 254 "src/cfgparser.yy"
#line 252 "src/cfgparser.yy"
{ reglob->setAspect( (yyvsp[0].floatValue) ); }
break;
case 49:
#line 258 "src/cfgparser.yy"
#line 256 "src/cfgparser.yy"
{ reglob->setAmbientLight( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); }
break;
case 50:
#line 262 "src/cfgparser.yy"
#line 260 "src/cfgparser.yy"
{ reglob->setBackgroundCol( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); }
break;
case 51:
#line 266 "src/cfgparser.yy"
#line 264 "src/cfgparser.yy"
{ reglob->setOutFilename( (yyvsp[0].charValue) ); }
break;
case 52:
#line 270 "src/cfgparser.yy"
#line 268 "src/cfgparser.yy"
{ reglob->setTreeMaxDepth( (yyvsp[0].intValue) ); }
break;
case 53:
#line 274 "src/cfgparser.yy"
#line 272 "src/cfgparser.yy"
{ reglob->setTreeMaxTriangles( (yyvsp[0].intValue) ); }
break;
case 54:
#line 278 "src/cfgparser.yy"
#line 276 "src/cfgparser.yy"
{ reglob->setRayMaxDepth( (yyvsp[0].intValue) ); }
break;
case 55:
#line 282 "src/cfgparser.yy"
#line 280 "src/cfgparser.yy"
{ reglob->setDebugPixel( (yyvsp[-1].intValue), (yyvsp[0].intValue) ); }
break;
case 56:
#line 286 "src/cfgparser.yy"
#line 284 "src/cfgparser.yy"
{ reglob->setTestMode( (yyvsp[0].intValue) ); }
break;
case 57:
#line 290 "src/cfgparser.yy"
#line 288 "src/cfgparser.yy"
{ if(attrs[(yyvsp[0].charValue)] == NULL){ yyerror("OPENGL ATTRIBUTES: The attribute was not found!"); }
reglob->getOpenGlAttributes()->import( attrs[(yyvsp[0].charValue)] ); }
break;
case 58:
#line 295 "src/cfgparser.yy"
#line 293 "src/cfgparser.yy"
{ if(attrs[(yyvsp[0].charValue)] == NULL){ yyerror("BLENDER ATTRIBUTES: The attribute was not found!"); }
reglob->getBlenderAttributes()->import( attrs[(yyvsp[0].charValue)] ); }
break;
case 59:
#line 307 "src/cfgparser.yy"
#line 305 "src/cfgparser.yy"
{
/* reset light pointers */
currentLightOmni = NULL;
@@ -1713,7 +1711,7 @@ yyreduce:
break;
case 62:
#line 319 "src/cfgparser.yy"
#line 317 "src/cfgparser.yy"
{ currentLightOmni = new ntlLightObject( reglob );
currentLight = currentLightOmni;
reglob->getLightList()->push_back(currentLight);
@@ -1721,28 +1719,28 @@ yyreduce:
break;
case 67:
#line 333 "src/cfgparser.yy"
#line 331 "src/cfgparser.yy"
{
currentLight->setActive( (yyvsp[0].intValue) );
}
break;
case 68:
#line 338 "src/cfgparser.yy"
#line 336 "src/cfgparser.yy"
{
currentLight->setCastShadows( (yyvsp[0].intValue) );
}
break;
case 69:
#line 343 "src/cfgparser.yy"
#line 341 "src/cfgparser.yy"
{
currentLight->setColor( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) );
}
break;
case 70:
#line 348 "src/cfgparser.yy"
#line 346 "src/cfgparser.yy"
{
int init = 0;
if(currentLightOmni != NULL) {
@@ -1752,16 +1750,17 @@ yyreduce:
break;
case 71:
#line 366 "src/cfgparser.yy"
#line 364 "src/cfgparser.yy"
{
// geo classes have attributes...
reglob->getScene()->addGeoClass(currentGeoClass);
reglob->getRenderScene()->addGeoClass(currentGeoClass);
reglob->getSimScene()->addGeoClass(currentGeoClass);
currentAttrib = currentGeoClass->getAttributeList();
}
break;
case 72:
#line 372 "src/cfgparser.yy"
#line 371 "src/cfgparser.yy"
{
/* reset geometry object pointers */
currentGeoObj = NULL;
@@ -1769,39 +1768,39 @@ yyreduce:
currentGeometrySim = NULL;
currentGeometryModel = NULL;
currentAttrib = NULL;
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
currentGeometryBox = NULL;
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
}
break;
case 75:
#line 390 "src/cfgparser.yy"
#line 389 "src/cfgparser.yy"
{
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
currentGeometryBox = new ntlGeometryBox( );
currentGeoClass = currentGeometryBox;
currentGeoObj = (ntlGeometryObject*)( currentGeometryBox );
#else // ELBEEM_BLENDER
#else // ELBEEM_PLUGIN
yyerror("GEOTYPE_BOX : This object type is not supported in this version!");
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
}
break;
case 76:
#line 399 "src/cfgparser.yy"
#line 398 "src/cfgparser.yy"
{
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
currentGeoClass = new ntlGeometrySphere( );
currentGeoObj = (ntlGeometryObject*)( currentGeoClass );
#else // ELBEEM_BLENDER
#else // ELBEEM_PLUGIN
yyerror("GEOTYPE_SPHERE : This object type is not supported in this version!");
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
}
break;
case 77:
#line 407 "src/cfgparser.yy"
#line 406 "src/cfgparser.yy"
{
currentGeometryModel = new ntlGeometryObjModel( );
currentGeoClass = currentGeometryModel;
@@ -1810,7 +1809,7 @@ yyreduce:
break;
case 78:
#line 412 "src/cfgparser.yy"
#line 411 "src/cfgparser.yy"
{
currentGeometrySim = new SimulationObject();
currentGeoClass = currentGeometrySim;
@@ -1820,7 +1819,7 @@ yyreduce:
break;
case 79:
#line 418 "src/cfgparser.yy"
#line 417 "src/cfgparser.yy"
{
#ifdef LBM_INCLUDE_TESTSOLVERS
currentGeometrySim = new SimulationCompareLbm();
@@ -1833,14 +1832,14 @@ yyreduce:
break;
case 89:
#line 443 "src/cfgparser.yy"
#line 442 "src/cfgparser.yy"
{
currentGeoClass->setName( (yyvsp[0].charValue) );
}
break;
case 90:
#line 448 "src/cfgparser.yy"
#line 447 "src/cfgparser.yy"
{
if(currentGeoObj == NULL){ yyerror(" MATERIAL : This property can only be set for geometry objects!"); }
currentGeoObj->setMaterialName( (yyvsp[0].charValue) );
@@ -1848,7 +1847,7 @@ yyreduce:
break;
case 91:
#line 454 "src/cfgparser.yy"
#line 453 "src/cfgparser.yy"
{
if(currentGeoObj == NULL){ yyerror(" CAST_SHADOW : This property can only be set for geometry objects!"); }
currentGeoObj->setCastShadows( (yyvsp[0].intValue) );
@@ -1856,7 +1855,7 @@ yyreduce:
break;
case 92:
#line 460 "src/cfgparser.yy"
#line 459 "src/cfgparser.yy"
{
if(currentGeoObj == NULL){ yyerror(" RECEIVE_SHADOW : This property can only be set for geometry objects!"); }
currentGeoObj->setReceiveShadows( (yyvsp[0].intValue) );
@@ -1864,21 +1863,21 @@ yyreduce:
break;
case 93:
#line 466 "src/cfgparser.yy"
#line 465 "src/cfgparser.yy"
{
currentGeoClass->setVisible( (yyvsp[0].intValue) );
}
break;
case 94:
#line 471 "src/cfgparser.yy"
#line 470 "src/cfgparser.yy"
{
int init = 0;
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
if(currentGeometryBox != NULL){
currentGeometryBox->setStart( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; }
#else // ELBEEM_BLENDER
#endif // ELBEEM_BLENDER
#else // ELBEEM_PLUGIN
#endif // ELBEEM_PLUGIN
if(currentGeometrySim != NULL){
currentGeometrySim->setGeoStart( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; }
if(currentGeometryModel != NULL){
@@ -1888,14 +1887,14 @@ yyreduce:
break;
case 95:
#line 486 "src/cfgparser.yy"
#line 485 "src/cfgparser.yy"
{
int init = 0;
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
if(currentGeometryBox != NULL){
currentGeometryBox->setEnd( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; }
#else // ELBEEM_BLENDER
#endif // ELBEEM_BLENDER
#else // ELBEEM_PLUGIN
#endif // ELBEEM_PLUGIN
if(currentGeometrySim != NULL){
currentGeometrySim->setGeoEnd( ntlVec3Gfx((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) ); init=1; }
if(currentGeometryModel != NULL){
@@ -1905,20 +1904,23 @@ yyreduce:
break;
case 96:
#line 502 "src/cfgparser.yy"
#line 501 "src/cfgparser.yy"
{
if(attrs[(yyvsp[0].charValue)] == NULL){ yyerror("GEO ATTRIBUTES: The attribute was not found!"); }
currentGeoClass->getAttributeList()->import( attrs[(yyvsp[0].charValue)] );
else {
if(currentGeoClass->getAttributeList())
currentGeoClass->getAttributeList()->import( attrs[(yyvsp[0].charValue)] );
}
}
break;
case 97:
#line 510 "src/cfgparser.yy"
#line 512 "src/cfgparser.yy"
{ }
break;
case 98:
#line 522 "src/cfgparser.yy"
#line 524 "src/cfgparser.yy"
{
/* reset geometry object pointers */
currentMaterial = NULL;
@@ -1926,7 +1928,7 @@ yyreduce:
break;
case 101:
#line 534 "src/cfgparser.yy"
#line 536 "src/cfgparser.yy"
{ currentMaterial = new ntlMaterial( );
currentMaterial = currentMaterial;
reglob->getMaterials()->push_back(currentMaterial);
@@ -1934,34 +1936,34 @@ yyreduce:
break;
case 102:
#line 538 "src/cfgparser.yy"
#line 540 "src/cfgparser.yy"
{
yyerror("MATTYPE: Blinn NYI!"); }
break;
case 113:
#line 556 "src/cfgparser.yy"
#line 558 "src/cfgparser.yy"
{
currentMaterial->setName( (yyvsp[0].charValue) );
}
break;
case 114:
#line 561 "src/cfgparser.yy"
#line 563 "src/cfgparser.yy"
{
currentMaterial->setAmbientRefl( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) );
}
break;
case 115:
#line 566 "src/cfgparser.yy"
#line 568 "src/cfgparser.yy"
{
currentMaterial->setDiffuseRefl( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) );
}
break;
case 116:
#line 571 "src/cfgparser.yy"
#line 573 "src/cfgparser.yy"
{
currentMaterial->setSpecular( (yyvsp[-1].floatValue) );
currentMaterial->setSpecExponent( (yyvsp[0].floatValue) );
@@ -1969,56 +1971,56 @@ yyreduce:
break;
case 117:
#line 577 "src/cfgparser.yy"
#line 579 "src/cfgparser.yy"
{
currentMaterial->setMirror( (yyvsp[0].floatValue) );
}
break;
case 118:
#line 582 "src/cfgparser.yy"
#line 584 "src/cfgparser.yy"
{
currentMaterial->setTransparence( (yyvsp[0].floatValue) );
}
break;
case 119:
#line 587 "src/cfgparser.yy"
#line 589 "src/cfgparser.yy"
{
currentMaterial->setRefracIndex( (yyvsp[0].floatValue) );
}
break;
case 120:
#line 592 "src/cfgparser.yy"
#line 594 "src/cfgparser.yy"
{
currentMaterial->setTransAdditive( (yyvsp[0].floatValue) );
}
break;
case 121:
#line 597 "src/cfgparser.yy"
#line 599 "src/cfgparser.yy"
{
currentMaterial->setTransAttCol( ntlColor((yyvsp[-2].floatValue),(yyvsp[-1].floatValue),(yyvsp[0].floatValue)) );
}
break;
case 122:
#line 602 "src/cfgparser.yy"
#line 604 "src/cfgparser.yy"
{
currentMaterial->setFresnel( (yyvsp[0].intValue) );
}
break;
case 123:
#line 613 "src/cfgparser.yy"
#line 615 "src/cfgparser.yy"
{
currentAttrib = new AttributeList((yyvsp[-1].charValue));
currentAttrName = (yyvsp[-1].charValue); }
break;
case 124:
#line 616 "src/cfgparser.yy"
#line 618 "src/cfgparser.yy"
{ // store attribute
//std::cerr << " NEW ATTR " << currentAttrName << std::endl;
//currentAttrib->print();
@@ -2027,12 +2029,12 @@ yyreduce:
break;
case 129:
#line 629 "src/cfgparser.yy"
#line 631 "src/cfgparser.yy"
{ currentAttrValue.clear(); currentAttribAddName = (yyvsp[-1].charValue); }
break;
case 130:
#line 630 "src/cfgparser.yy"
#line 632 "src/cfgparser.yy"
{
currentAttrib->addAttr( currentAttribAddName, currentAttrValue, lineCount, true);
//std::cerr << " ADD ATTRCHANNEL " << currentAttribAddName << std::endl;
@@ -2041,12 +2043,12 @@ yyreduce:
break;
case 132:
#line 637 "src/cfgparser.yy"
#line 639 "src/cfgparser.yy"
{ currentAttrValue.clear(); currentAttribAddName = (yyvsp[-1].charValue); }
break;
case 133:
#line 638 "src/cfgparser.yy"
#line 640 "src/cfgparser.yy"
{
currentAttrib->addAttr( currentAttribAddName, currentAttrValue, lineCount, false);
//std::cerr << " ADD ATTRNORM " << currentAttribAddName << std::endl;
@@ -2055,21 +2057,21 @@ yyreduce:
break;
case 135:
#line 645 "src/cfgparser.yy"
#line 647 "src/cfgparser.yy"
{
//std::cerr << "LLL "<<$2<<std::endl; // ignore newline entries
if(strcmp((yyvsp[0].charValue),"\n")) currentAttrValue.push_back((yyvsp[0].charValue)); }
break;
case 136:
#line 648 "src/cfgparser.yy"
#line 650 "src/cfgparser.yy"
{
//std::cerr << "LRR "<<$1<<std::endl;
if(strcmp((yyvsp[0].charValue),"\n")) currentAttrValue.push_back((yyvsp[0].charValue)); }
break;
case 138:
#line 662 "src/cfgparser.yy"
#line 664 "src/cfgparser.yy"
{
if ( ((yyvsp[0].floatValue) < 0.0) || ((yyvsp[0].floatValue) > 1.0) ) {
yyerror("Value out of range (only 0 to 1 allowed)");
@@ -2081,17 +2083,17 @@ yyreduce:
break;
case 139:
#line 674 "src/cfgparser.yy"
#line 676 "src/cfgparser.yy"
{ (yyval.floatValue) = (yyvsp[0].floatValue); }
break;
case 140:
#line 676 "src/cfgparser.yy"
#line 678 "src/cfgparser.yy"
{ (yyval.floatValue) = (float) (yyvsp[0].intValue); /* conversion from integers */ }
break;
case 141:
#line 682 "src/cfgparser.yy"
#line 684 "src/cfgparser.yy"
{
if ( (yyvsp[0].intValue) <= 0 ) {
yy_error("Value out of range (has to be above zero)");
@@ -2103,7 +2105,7 @@ yyreduce:
break;
case 142:
#line 693 "src/cfgparser.yy"
#line 695 "src/cfgparser.yy"
{
//cout << " " << $1 << " ";
if ( (yyvsp[0].intValue) < 0 ) {
@@ -2116,7 +2118,7 @@ yyreduce:
break;
case 143:
#line 705 "src/cfgparser.yy"
#line 707 "src/cfgparser.yy"
{
if( ( (yyvsp[0].intValue) != 0 ) && ( (yyvsp[0].intValue) != 1 ) ) {
yy_error("Boolean value has to be 1|0, 'true'|'false' or 'on'|'off'!");
@@ -2130,7 +2132,7 @@ yyreduce:
}
/* Line 1037 of yacc.c. */
#line 2134 "bld-std-gcc/src/cfgparser.cpp"
#line 2136 "bld-std-gcc/src/cfgparser.cpp"
yyvsp -= yylen;
yyssp -= yylen;
@@ -2358,7 +2360,7 @@ yyreturn:
}
#line 713 "src/cfgparser.yy"
#line 715 "src/cfgparser.yy"
/*---------------------------------------------------------------------------*/

View File

@@ -244,7 +244,7 @@
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
#line 87 "src/cfgparser.yy"
#line 85 "src/cfgparser.yy"
typedef union YYSTYPE {
int intValue;
float floatValue;

View File

@@ -12,7 +12,7 @@
#include "ntl_blenderdumper.h"
extern "C" void elbeemCheckDebugEnv(void);
#include "ntl_scene.h"
#include "ntl_world.h"
#include "ntl_geometrymodel.h"
/*****************************************************************************/
@@ -29,15 +29,51 @@ int guiRoiMaxLev=6, guiRoiMinLev=0;
//! global raytracer pointer (=world)
ntlWorld *gpWorld = NULL;
//! debug output switch
bool myDebugOut = false;
//! global leave program / abort variable
bool gQuit = false;
// API
// reset elbeemSimulationSettings struct with defaults
extern "C"
void elbeemResetSettings(elbeemSimulationSettings *set) {
if(!set) return;
set->version = 2;
for(int i=0 ; i<3; i++) set->geoStart[i] = 0.0;
for(int i=0 ; i<3; i++) set->geoSize[i] = 1.0;
set->resolutionxyz = 64;
set->previewresxyz = 24;
set->realsize = 1.0;
set->viscosity = 0.000001;
for(int i=0 ; i<2; i++) set->gravity[i] = 0.0;
set->gravity[2] = -9.81;
set->animStart = 0;
set->aniFrameTime = 0.01;
set->noOfFrames = 10;
set->gstar = 0.005;
set->maxRefine = -1;
set->generateParticles = 1.0;
strcpy(set->outputPath,"./elbeemdata_");
set->channelSizeFrameTime=0;
set->channelFrameTime=NULL;
set->channelSizeViscosity=0;
set->channelViscosity=NULL;
set->channelSizeGravity=0;
set->channelGravity=NULL;
set->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP;
set->obstaclePartslip= 0.;
set->generateVertexVectors = 0;
set->surfaceSmoothing = 1.;
// init identity
for(int i=0; i<16; i++) set->surfaceTrafo[i] = 0.0;
for(int i=0; i<4; i++) set->surfaceTrafo[i*4+i] = 1.0;
}
// start fluidsim init
extern "C"
int elbeemInit(elbeemSimulationSettings *settings) {
gElbeemState = SIMWORLD_INVALID;
strcpy(gElbeemErrorString,"[none]");
@@ -51,10 +87,41 @@ int elbeemInit(elbeemSimulationSettings *settings) {
return 0;
}
// reset elbeemMesh struct with zeroes
extern "C"
void elbeemResetMesh(elbeemMesh *mesh) {
if(!mesh) return;
mesh->type = 0;
mesh->numVertices = 0;
mesh->vertices = NULL;
mesh->numTriangles = 0;
mesh->triangles = NULL;
mesh->channelSizeTranslation = 0;
mesh->channelTranslation = NULL;
mesh->channelSizeRotation = 0;
mesh->channelRotation = NULL;
mesh->channelSizeScale = 0;
mesh->channelScale = NULL;
mesh->channelSizeActive = 0;
mesh->channelActive = NULL;
mesh->channelSizeInitialVel = 0;
mesh->channelInitialVel = NULL;
mesh->localInivelCoords = 0;
mesh->obstacleType= FLUIDSIM_OBSTACLE_NOSLIP;
mesh->obstaclePartslip= 0.;
mesh->name = "[unnamed]";
}
// add mesh as fluidsim object
extern "C"
int elbeemAddMesh(elbeemMesh *mesh) {
int initType = -1;
switch(mesh->type) {
case OB_FLUIDSIM_OBSTACLE: initType = FGI_BNDNO; break;
case OB_FLUIDSIM_OBSTACLE:
if (mesh->obstacleType==FLUIDSIM_OBSTACLE_PARTSLIP) initType = FGI_BNDPART;
else if(mesh->obstacleType==FLUIDSIM_OBSTACLE_FREESLIP) initType = FGI_BNDFREE;
else /*if(mesh->obstacleType==FLUIDSIM_OBSTACLE_NOSLIP)*/ initType = FGI_BNDNO;
break;
case OB_FLUIDSIM_FLUID: initType = FGI_FLUID; break;
case OB_FLUIDSIM_INFLOW: initType = FGI_MBNDINFLOW; break;
case OB_FLUIDSIM_OUTFLOW: initType = FGI_MBNDOUTFLOW; break;
@@ -63,15 +130,30 @@ int elbeemAddMesh(elbeemMesh *mesh) {
if(initType<0) return 1;
ntlGeometryObjModel *obj = new ntlGeometryObjModel( );
gpWorld->getRenderGlobals()->getScene()->addGeoClass( obj );
gpWorld->getRenderGlobals()->getSimScene()->addGeoClass( obj );
obj->initModel(mesh->numVertices, mesh->vertices, mesh->numTriangles, mesh->triangles);
obj->setGeoInitId(true);
if(mesh->name) obj->setName(std::string(mesh->name));
else obj->setName(std::string("[unnamed]"));
obj->setGeoInitId(1);
obj->setGeoInitIntersect(true);
obj->setGeoInitType(initType);
obj->setInitialVelocity( ntlVec3Gfx(mesh->iniVelx, mesh->iniVely, mesh->iniVelz) );
obj->setGeoPartSlipValue(mesh->obstaclePartslip);
// use channel instead, obj->setInitialVelocity( ntlVec3Gfx(mesh->iniVelocity[0], mesh->iniVelocity[1], mesh->iniVelocity[2]) );
obj->initChannels(
mesh->channelSizeTranslation, mesh->channelTranslation,
mesh->channelSizeRotation, mesh->channelRotation,
mesh->channelSizeScale, mesh->channelScale,
mesh->channelSizeActive, mesh->channelActive,
mesh->channelSizeInitialVel, mesh->channelInitialVel
);
obj->setLocalCoordInivel( mesh->localInivelCoords );
debMsgStd("elbeemAddMesh",DM_MSG,"Added elbeem mesh: "<<obj->getName()<<" type="<<initType<<" "<<obj->getIsAnimated(), 9 );
return 0;
}
// do the actual simulation
extern "C"
int elbeemSimulate(void) {
if(!gpWorld) return 1;
@@ -82,7 +164,7 @@ int elbeemSimulate(void) {
myTime_t timestart = getTime();
gpWorld->renderAnimation();
myTime_t timeend = getTime();
debMsgStd("performElbeemSimulation",DM_NOTIFY, "El'Beem simulation done, time: "<<((timeend-timestart)/(double)1000.0) <<" seconds.\n", 2 );
debMsgStd("elbeemSimulate",DM_NOTIFY, "El'Beem simulation done, time: "<<getTimeString(timeend-timestart)<<".\n", 2 );
// ok, we're done...
delete gpWorld;
@@ -95,4 +177,121 @@ int elbeemSimulate(void) {
}
// global vector to flag values to remove
vector<int> gKeepVal;
#define SIMPLIFY_FLOAT_EPSILON (1e-6f)
#define SIMPLIFY_DOUBLE_EPSILON (1e-12f)
#define SFLOATEQ(x,y) (ABS((x)-(y)) < SIMPLIFY_FLOAT_EPSILON)
#define SDOUBLEEQ(x,y) (ABS((x)-(y)) < SIMPLIFY_DOUBLE_EPSILON)
#define SVECFLOATEQ(x,y) ( \
(ABS((x)[0]-(y)[0]) < SIMPLIFY_FLOAT_EPSILON) && \
(ABS((x)[1]-(y)[1]) < SIMPLIFY_FLOAT_EPSILON) && \
(ABS((x)[2]-(y)[2]) < SIMPLIFY_FLOAT_EPSILON) )
// helper function - simplify animation channels
extern "C"
int elbeemSimplifyChannelFloat(float *channel, int* size) {
bool changed = false;
int nsize = *size;
int orgsize = *size;
if(orgsize<1) return false;
gKeepVal.resize( orgsize );
for(int i=0; i<orgsize; i++) { gKeepVal[i] = true; }
const bool debugSF = false;
float last = channel[0 + 0];
for(int i=1; i<orgsize; i++) {
float curr = channel[2*i + 0];
bool remove = false;
if(SFLOATEQ(curr,last)) remove = true;
// dont remove if next value is different
if((remove)&&(i<orgsize-1)) {
float next = channel[2*(i+1)+0];
if(!SFLOATEQ(next,curr)) remove = false;
}
if(remove) {
changed = true;
gKeepVal[i] = false;
nsize--;
}
if(debugSF) errMsg("elbeemSimplifyChannelFloat","i"<<i<<"/"<<orgsize<<" v"<<channel[ (i*2) + 0 ]<<" t"<<channel[ (i*2) + 1 ]<<" nsize="<<nsize<<" r"<<remove );
last = curr;
}
if(changed) {
nsize = 1;
for(int i=1; i<orgsize; i++) {
if(gKeepVal[i]) {
channel[ (nsize*2) + 0 ] = channel[ (i*2) + 0 ];
channel[ (nsize*2) + 1 ] = channel[ (i*2) + 1 ];
nsize++;
}
}
*size = nsize;
}
if(debugSF) for(int i=1; i<nsize; i++) {
errMsg("elbeemSimplifyChannelFloat","n i"<<i<<"/"<<nsize<<" v"<<channel[ (i*2) + 0 ]<<" t"<<channel[ (i*2) + 1 ] );
}
return changed;
}
extern "C"
int elbeemSimplifyChannelVec3(float *channel, int* size) {
bool changed = false;
int nsize = *size;
int orgsize = *size;
if(orgsize<1) return false;
gKeepVal.resize( orgsize );
for(int i=0; i<orgsize; i++) { gKeepVal[i] = true; }
const bool debugVF = false;
ntlVec3f last( channel[0 + 0], channel[0 + 1], channel[0 + 2] );
for(int i=1; i<orgsize; i++) {
ntlVec3f curr( channel[4*i + 0], channel[4*i + 1], channel[4*i + 2]);
bool remove = false;
if(SVECFLOATEQ(curr,last)) remove = true;
// dont remove if next value is different
if((remove)&&(i<orgsize-1)) {
ntlVec3f next( channel[4*(i+1)+0], channel[4*(i+1)+1], channel[4*(i+1)+2]);
if(!SVECFLOATEQ(next,curr)) remove = false;
}
if(remove) {
changed = true;
gKeepVal[i] = false;
nsize--;
}
if(debugVF) errMsg("elbeemSimplifyChannelVec3","i"<<i<<"/"<<orgsize<<" v"<<
channel[ (i*4) + 0 ]<<","<< channel[ (i*4) + 1 ]<<","<< channel[ (i*4) + 2 ]<<
" t"<<channel[ (i*4) + 3 ]<<" nsize="<<nsize<<" r"<<remove );
last = curr;
}
if(changed) {
nsize = 1;
for(int i=1; i<orgsize; i++) {
if(gKeepVal[i]) {
for(int j=0; j<4; j++){ channel[ (nsize*4) + j ] = channel[ (i*4) + j ]; }
nsize++;
}
}
*size = nsize;
}
if(debugVF) for(int i=1; i<nsize; i++) {
errMsg("elbeemSimplifyChannelVec3","n i"<<i<<"/"<<nsize<<" v"<<
channel[ (i*4) + 0 ]<<","<< channel[ (i*4) + 1 ]<<","<< channel[ (i*4) + 2 ]<<
" t"<<channel[ (i*4) + 3 ] );
}
return changed;
}
#undef SIMPLIFY_FLOAT_EPSILON
#undef SIMPLIFY_DOUBLE_EPSILON
#undef SFLOATEQ
#undef SDOUBLEEQ

View File

@@ -11,21 +11,6 @@
#define ELBEEM_API_H
/*! fluid geometry init types */
#define FGI_FLAGSTART 16
#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0))
#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1))
#define FGI_BNDNO (1<<(FGI_FLAGSTART+ 2))
#define FGI_BNDFREE (1<<(FGI_FLAGSTART+ 3))
#define FGI_BNDPART (1<<(FGI_FLAGSTART+ 4))
#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5))
#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW )
/*! blender types for mesh->type */
//#define OB_FLUIDSIM_DOMAIN 2
#define OB_FLUIDSIM_FLUID 4
@@ -33,6 +18,10 @@
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
#define FLUIDSIM_OBSTACLE_NOSLIP 1
#define FLUIDSIM_OBSTACLE_PARTSLIP 2
#define FLUIDSIM_OBSTACLE_FREESLIP 3
// global settings for the simulation
typedef struct elbeemSimulationSettings {
@@ -51,16 +40,39 @@ typedef struct elbeemSimulationSettings {
/* fluid properties */
double viscosity;
/* gravity strength */
float gravx,gravy,gravz;
float gravity[3];
/* anim start end time */
float animStart, aniFrameTime;
/* no. of frames to simulate & output */
short noOfFrames;
/* g star param (LBM compressibility) */
float gstar;
/* activate refinement? */
short maxRefine;
/* amount of particles to generate (0=off) */
float generateParticles;
/* store output path, and file prefix for baked fluid surface */
char surfdataPath[160+80];
char outputPath[160+80];
/* channel for frame time, visc & gravity animations */
int channelSizeFrameTime;
float *channelFrameTime;
int channelSizeViscosity;
float *channelViscosity;
int channelSizeGravity;
float *channelGravity; // vector
/* boundary types and settings for domain walls */
short obstacleType;
float obstaclePartslip;
/* generate speed vectors for vertices (e.g. for image based motion blur)*/
short generateVertexVectors;
/* strength of surface smoothing */
float surfaceSmoothing;
/* global transformation to apply to fluidsim mesh */
float surfaceTrafo[4*4];
} elbeemSimulationSettings;
@@ -69,9 +81,6 @@ typedef struct elbeemMesh {
/* obstacle,fluid or inflow... */
short type;
/* initial velocity (for fluid/inflow) */
float iniVelx,iniVely,iniVelz;
/* vertices */
int numVertices;
float *vertices; // = float[][3];
@@ -79,13 +88,46 @@ typedef struct elbeemMesh {
/* triangles */
int numTriangles;
int *triangles; // = int[][3];
/* animation channels */
int channelSizeTranslation;
float *channelTranslation;
int channelSizeRotation;
float *channelRotation;
int channelSizeScale;
float *channelScale;
/* active channel */
int channelSizeActive;
float *channelActive;
/* initial velocity channel (e.g. for inflow) */
int channelSizeInitialVel;
float *channelInitialVel; // vector
/* use initial velocity in object coordinates? (e.g. for rotation) */
short localInivelCoords;
/* boundary types and settings */
short obstacleType;
float obstaclePartslip;
/* name of the mesh, mostly for debugging */
char *name;
} elbeemMesh;
// API functions
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// reset elbeemSimulationSettings struct with defaults
void elbeemResetSettings(struct elbeemSimulationSettings*);
// start fluidsim init
int elbeemInit(struct elbeemSimulationSettings*);
// reset elbeemMesh struct with zeroes
void elbeemResetMesh(struct elbeemMesh*);
// add mesh as fluidsim object
int elbeemAddMesh(struct elbeemMesh*);
@@ -93,5 +135,30 @@ int elbeemAddMesh(struct elbeemMesh*);
int elbeemSimulate(void);
// helper function - simplify animation channels
// returns if the channel and its size changed
int elbeemSimplifyChannelFloat(float *channel, int *size);
int elbeemSimplifyChannelVec3(float *channel, int *size);
#ifdef __cplusplus
}
#endif // __cplusplus
/******************************************************************************/
// internal defines, do not use for setting up simulation
/*! fluid geometry init types */
#define FGI_FLAGSTART 16
#define FGI_FLUID (1<<(FGI_FLAGSTART+ 0))
#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+ 1))
#define FGI_BNDNO (1<<(FGI_FLAGSTART+ 2))
#define FGI_BNDFREE (1<<(FGI_FLAGSTART+ 3))
#define FGI_BNDPART (1<<(FGI_FLAGSTART+ 4))
#define FGI_NO_BND (1<<(FGI_FLAGSTART+ 5))
#define FGI_MBNDINFLOW (1<<(FGI_FLAGSTART+ 6))
#define FGI_MBNDOUTFLOW (1<<(FGI_FLAGSTART+ 7))
#define FGI_ALLBOUNDS ( FGI_BNDNO | FGI_BNDFREE | FGI_BNDPART | FGI_MBNDINFLOW | FGI_MBNDOUTFLOW )
#endif // ELBEEM_API_H

View File

@@ -1,26 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2005 Nils Thuerey
*
* Global variables (unavoidable at times...)
* all defines in main.cpp
*
*****************************************************************************/
/*****************************************************************************/
//! user interface variables
// global raytracer pointer (=world)
class ntlWorld;
extern ntlWorld *gpWorld;
// debug output switch
extern bool myDebugOut;
// global leave program / abort variable
extern bool gQuit;

View File

@@ -9,7 +9,7 @@
#include "isosurface.h"
#include "mcubes_tables.h"
#include "ntl_scene.h"
#include "ntl_ray.h"
#include <algorithm>
#include <stdio.h>
@@ -20,23 +20,15 @@
#include <ieeefp.h>
#endif
/*
template class vector<IsoLevelVertex>;
template class vector<int>;
template class vector<unsigned int>;
template class vector<float>;
template class vector<ntlVec3Gfx>;
template class vector< vector<int> >;
*/
/******************************************************************************
* Constructor
*****************************************************************************/
IsoSurface::IsoSurface(double iso, double blend) :
IsoSurface::IsoSurface(double iso) :
ntlGeometryObject(),
mSizex(-1), mSizey(-1), mSizez(-1),
mpData(NULL),
mIsoValue( iso ),
mBlendVal( blend ),
mPoints(),
mpEdgeVerticesX(NULL), mpEdgeVerticesY(NULL), mpEdgeVerticesZ(NULL),
mIndices(),
@@ -44,7 +36,10 @@ IsoSurface::IsoSurface(double iso, double blend) :
mStart(0.0), mEnd(0.0), mDomainExtent(0.0),
mInitDone(false),
mSmoothSurface(0.0), mSmoothNormals(0.0),
mAcrossEdge(), mAdjacentFaces()
mAcrossEdge(), mAdjacentFaces(),
mCutoff(-1), // off by default
mFlagCnt(1),
mSCrad1(0.), mSCrad2(0.), mSCcenter(0.)
{
}
@@ -87,16 +82,6 @@ void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx e
// marching cubes are ready
mInitDone = true;
/*unsigned long int memCnt = (3*sizeof(int)*nodes + sizeof(float)*nodes);
double memd = memCnt;
char *sizeStr = "";
const double sfac = 1000.0;
if(memd>sfac){ memd /= sfac; sizeStr="KB"; }
if(memd>sfac){ memd /= sfac; sizeStr="MB"; }
if(memd>sfac){ memd /= sfac; sizeStr="GB"; }
if(memd>sfac){ memd /= sfac; sizeStr="TB"; }
debMsgStd("IsoSurface::initializeIsosurface",DM_MSG,"Inited "<<PRINT_VEC(setx,sety,setz)<<" alloced:"<< memd<<" "<<sizeStr<<"." ,10);*/
}
@@ -107,11 +92,10 @@ void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx e
*****************************************************************************/
IsoSurface::~IsoSurface( void )
{
if(mpData) delete [] mpData;
if(mpEdgeVerticesX) delete [] mpEdgeVerticesX;
if(mpEdgeVerticesY) delete [] mpEdgeVerticesY;
if(mpEdgeVerticesZ) delete [] mpEdgeVerticesZ;
}
@@ -132,10 +116,10 @@ void IsoSurface::triangulate( void )
return;
}
// get grid spacing
gsx = (mEnd[0]-mStart[0])/(double)(mSizex-1.0);
gsy = (mEnd[1]-mStart[1])/(double)(mSizey-1.0);
gsz = (mEnd[2]-mStart[2])/(double)(mSizez-1.0);
// get grid spacing (-2 to have same spacing as sim)
gsx = (mEnd[0]-mStart[0])/(double)(mSizex-2.0);
gsy = (mEnd[1]-mStart[1])/(double)(mSizey-2.0);
gsz = (mEnd[2]-mStart[2])/(double)(mSizez-2.0);
// clean up previous frame
mIndices.clear();
@@ -169,13 +153,13 @@ void IsoSurface::triangulate( void )
0,0,0,0, 1,1,1,1 };
// let the cubes march
pz = mStart[2]-gsz;
pz = mStart[2]-gsz*0.5;
for(int k=1;k<(mSizez-2);k++) {
pz += gsz;
py = mStart[1]-gsy;
py = mStart[1]-gsy*0.5;
for(int j=1;j<(mSizey-2);j++) {
py += gsy;
px = mStart[0]-gsx;
px = mStart[0]-gsx*0.5;
for(int i=1;i<(mSizex-2);i++) {
px += gsx;
int baseIn = ISOLEVEL_INDEX( i+0, j+0, k+0);
@@ -275,6 +259,12 @@ void IsoSurface::triangulate( void )
}
const int coAdd=2;
if(i<coAdd+mCutoff) continue;
if(j<coAdd+mCutoff) continue;
if((mCutoff>0) && (k<coAdd)) continue;
if(i>mSizex-2-coAdd-mCutoff) continue;
if(j>mSizey-2-coAdd-mCutoff) continue;
// Create the triangles...
for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) {
@@ -284,24 +274,20 @@ void IsoSurface::triangulate( void )
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] );
}
}
}
}//i
}// j
} // k
// precalculate normals using an approximation of the scalar field gradient
for(int ni=0;ni<(int)mPoints.size();ni++) {
// use triangle normals?, this seems better for File-IsoSurf
normalize( mPoints[ni].n );
}
//for(int i=0; i<mLoopSubdivs; i++) { subdivide(); }// DEBUG test
if(mSmoothSurface>0.0) { smoothSurface(mSmoothSurface); }
if(mSmoothSurface>0.0) { smoothSurface(mSmoothSurface, (mSmoothNormals<=0.0) ); }
if(mSmoothNormals>0.0) { smoothNormals(mSmoothNormals); }
myTime_t tritimeend = getTime();
debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< ((tritimeend-tritimestart)/(double)1000.0)<<"s, ss="<<mSmoothSurface<<" sm="<<mSmoothNormals , 10 );
debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<<mSmoothSurface<<","<<mSmoothNormals<<")" , 10 );
}
@@ -406,7 +392,6 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) {
/******************************************************************************
*
* Surface improvement
@@ -418,334 +403,109 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) {
*
*****************************************************************************/
// Subdivide a mesh allways loop
/*void IsoSurface::subdivide()
{
int i;
mAdjacentFaces.clear();
mAcrossEdge.clear();
//void TriMesh::need_adjacentfaces()
{
vector<int> numadjacentfaces(mPoints.size());
//errMsg("SUBDIV ADJFA1", " "<<mPoints.size()<<" - "<<numadjacentfaces.size() );
int i;
for (i = 0; i < (int)mIndices.size()/3; i++) {
numadjacentfaces[mIndices[i*3 + 0]]++;
numadjacentfaces[mIndices[i*3 + 1]]++;
numadjacentfaces[mIndices[i*3 + 2]]++;
}
mAdjacentFaces.resize(mPoints.size());
for (i = 0; i < (int)mPoints.size(); i++)
mAdjacentFaces[i].reserve(numadjacentfaces[i]);
for (i = 0; i < (int)mIndices.size()/3; i++) {
for (int j = 0; j < 3; j++)
mAdjacentFaces[mIndices[i*3 + j]].push_back(i);
}
}
// Find the face across each edge from each other face (-1 on boundary)
// If topology is bad, not necessarily what one would expect...
//void TriMesh::need_across_edge()
{
mAcrossEdge.resize(mIndices.size(), -1);
for (int i = 0; i < (int)mIndices.size()/3; i++) {
for (int j = 0; j < 3; j++) {
if (mAcrossEdge[i*3 + j] != -1)
continue;
int v1 = mIndices[i*3 + ((j+1)%3)];
int v2 = mIndices[i*3 + ((j+2)%3)];
const vector<int> &a1 = mAdjacentFaces[v1];
const vector<int> &a2 = mAdjacentFaces[v2];
for (int k1 = 0; k1 < (int)a1.size(); k1++) {
int other = a1[k1];
if (other == i)
continue;
vector<int>::const_iterator it =
std::find(a2.begin(), a2.end(), other);
if (it == a2.end())
continue;
//int ind = (faces[other].indexof(v1)+1)%3;
int ind = -1;
if( mIndices[other*3+0] == (unsigned int)v1 ) ind = 0;
else if( mIndices[other*3+1] == (unsigned int)v1 ) ind = 1;
else if( mIndices[other*3+2] == (unsigned int)v1 ) ind = 2;
ind = (ind+1)%3;
if ( (int)mIndices[other*3 + ((ind+1)%3)] != v2)
continue;
mAcrossEdge[i*3 + j] = other;
mAcrossEdge[other*3 + ind] = i;
break;
}
}
}
//errMsg("SUBDIV ACREDG", "Done.\n");
}
//errMsg("SUBDIV","start");
// Introduce new vertices
int nf = (int)mIndices.size() / 3;
//vector<TriMesh::Face> newverts(nf, TriMesh::Face(-1,-1,-1));
vector<int> newverts(nf*3); //, TriMesh::Face(-1,-1,-1));
for(int j=0; j<(int)newverts.size(); j++) newverts[j] = -1;
int old_nv = (int)mPoints.size();
mPoints.reserve(4 * old_nv);
vector<int> newvert_count(old_nv + 3*nf); // wichtig...?
//errMsg("NC", newvert_count.size() );
for (i = 0; i < nf; i++) {
for (int j = 0; j < 3; j++) {
int ae = mAcrossEdge[i*3 + j];
if (newverts[i*3 + j] == -1 && ae != -1) {
if (mAcrossEdge[ae*3 + 0] == i)
newverts[i*3 + j] = newverts[ae*3 + 0];
else if (mAcrossEdge[ae*3 + 1] == i)
newverts[i*3 + j] = newverts[ae*3 + 1];
else if (mAcrossEdge[ae*3 + 2] == i)
newverts[i*3 + j] = newverts[ae*3 + 2];
}
if (newverts[i*3 + j] == -1) {
IsoLevelVertex ilv;
ilv.v = ntlVec3Gfx(0.0);
ilv.n = ntlVec3Gfx(0.0);
mPoints.push_back(ilv);
newverts[i*3 + j] = (int)mPoints.size() - 1;
if (ae != -1) {
if (mAcrossEdge[ae*3 + 0] == i)
newverts[ae*3 + 0] = newverts[i*3 + j];
else if (mAcrossEdge[ae*3 + 1] == i)
newverts[ae*3 + 1] = newverts[i*3 + j];
else if (mAcrossEdge[ae*3 + 2] == i)
newverts[ae*3 + 2] = newverts[i*3 + j];
}
}
if(ae != -1) {
mPoints[newverts[i*3 + j]].v +=
mPoints[ mIndices[i*3 + ( j )] ].v * 0.25f + // j = 0,1,2?
mPoints[ mIndices[i*3 + ((j+1)%3)] ].v * 0.375f +
mPoints[ mIndices[i*3 + ((j+2)%3)] ].v * 0.375f;
#if RECALCNORMALS==0
mPoints[newverts[i*3 + j]].n +=
mPoints[ mIndices[i*3 + ( j )] ].n * 0.25f + // j = 0,1,2?
mPoints[ mIndices[i*3 + ((j+1)%3)] ].n * 0.375f +
mPoints[ mIndices[i*3 + ((j+2)%3)] ].n * 0.375f;
#endif // RECALCNORMALS==0
} else {
mPoints[newverts[i*3 + j]].v +=
mPoints[ mIndices[i*3 + ((j+1)%3)] ].v * 0.5f +
mPoints[ mIndices[i*3 + ((j+2)%3)] ].v * 0.5f ;
#if RECALCNORMALS==0
mPoints[newverts[i*3 + j]].n +=
mPoints[ mIndices[i*3 + ((j+1)%3)] ].n * 0.5f +
mPoints[ mIndices[i*3 + ((j+2)%3)] ].n * 0.5f ;
#endif // RECALCNORMALS==0
}
newvert_count[newverts[i*3 + j]]++;
}
}
for (i = old_nv; i < (int)mPoints.size(); i++) {
if (!newvert_count[i])
continue;
float scale = 1.0f / newvert_count[i];
mPoints[i].v *= scale;
#if RECALCNORMALS==0
//mPoints[i].n *= scale;
//normalize( mPoints[i].n );
#endif // RECALCNORMALS==0
}
// Update old vertices
for (i = 0; i < old_nv; i++) {
ntlVec3Gfx bdyavg(0.0), nbdyavg(0.0);
ntlVec3Gfx norm_bdyavg(0.0), norm_nbdyavg(0.0); // N
int nbdy = 0, nnbdy = 0;
int naf = (int)mAdjacentFaces[i].size();
if (!naf)
continue;
for (int j = 0; j < naf; j++) {
int af = mAdjacentFaces[i][j];
int afi = -1;
if( mIndices[af*3+0] == (unsigned int)i ) afi = 0;
else if( mIndices[af*3+1] == (unsigned int)i ) afi = 1;
else if( mIndices[af*3+2] == (unsigned int)i ) afi = 2;
int n1 = (afi+1) % 3;
int n2 = (afi+2) % 3;
if (mAcrossEdge[af*3 + n1] == -1) {
bdyavg += mPoints[newverts[af*3 + n1]].v;
#if RECALCNORMALS==0
//norm_bdyavg += mPoints[newverts[af*3 + n1]].n;
#endif // RECALCNORMALS==0
nbdy++;
} else {
nbdyavg += mPoints[newverts[af*3 + n1]].v;
#if RECALCNORMALS==0
//norm_nbdyavg += mPoints[newverts[af*3 + n1]].n;
#endif // RECALCNORMALS==0
nnbdy++;
}
if (mAcrossEdge[af*3 + n2] == -1) {
bdyavg += mPoints[newverts[af*3 + n2]].v;
#if RECALCNORMALS==0
//norm_bdyavg += mPoints[newverts[af*3 + n2]].n;
#endif // RECALCNORMALS==0
nbdy++;
} else {
nbdyavg += mPoints[newverts[af*3 + n2]].v;
#if RECALCNORMALS==0
//norm_nbdyavg += mPoints[newverts[af*3 + n2]].n;
#endif // RECALCNORMALS==0
nnbdy++;
}
}
float alpha;
ntlVec3Gfx newpt;
if (nbdy) {
newpt = bdyavg / (float) nbdy;
alpha = 0.5f;
} else if (nnbdy) {
newpt = nbdyavg / (float) nnbdy;
if (nnbdy == 6)
alpha = 1.05;
else if (nnbdy == 8)
alpha = 0.86;
else if (nnbdy == 10)
alpha = 0.7;
else
alpha = 0.6;
} else {
continue;
}
mPoints[i].v *= 1.0f - alpha;
mPoints[i].v += newpt * alpha;
#if RECALCNORMALS==0
//mPoints[i].n *= 1.0f - alpha;
//mPoints[i].n += newpt * alpha;
#endif // RECALCNORMALS==0
}
// Insert new faces
mIndices.reserve(4*nf);
for (i = 0; i < nf; i++) {
mIndices.push_back( mIndices[i*3 + 0]);
mIndices.push_back( newverts[i*3 + 2]);
mIndices.push_back( newverts[i*3 + 1]);
mIndices.push_back( mIndices[i*3 + 1]);
mIndices.push_back( newverts[i*3 + 0]);
mIndices.push_back( newverts[i*3 + 2]);
mIndices.push_back( mIndices[i*3 + 2]);
mIndices.push_back( newverts[i*3 + 1]);
mIndices.push_back( newverts[i*3 + 0]);
mIndices[i*3+0] = newverts[i*3+0];
mIndices[i*3+1] = newverts[i*3+1];
mIndices[i*3+2] = newverts[i*3+2];
}
// recalc normals
#if RECALCNORMALS==1
{
int nf = (int)mIndices.size()/3, nv = (int)mPoints.size(), i;
for (i = 0; i < nv; i++) {
mPoints[i].n = ntlVec3Gfx(0.0);
}
for (i = 0; i < nf; i++) {
const ntlVec3Gfx &p0 = mPoints[mIndices[i*3+0]].v;
const ntlVec3Gfx &p1 = mPoints[mIndices[i*3+1]].v;
const ntlVec3Gfx &p2 = mPoints[mIndices[i*3+2]].v;
ntlVec3Gfx a = p0-p1, b = p1-p2, c = p2-p0;
float l2a = normNoSqrt(a), l2b = normNoSqrt(b), l2c = normNoSqrt(c);
ntlVec3Gfx facenormal = cross(a, b);
mPoints[mIndices[i*3+0]].n += facenormal * (1.0f / (l2a * l2c));
mPoints[mIndices[i*3+1]].n += facenormal * (1.0f / (l2b * l2a));
mPoints[mIndices[i*3+2]].n += facenormal * (1.0f / (l2c * l2b));
}
for (i = 0; i < nv; i++) {
normalize(mPoints[i].n);
}
}
#else // RECALCNORMALS==1
for (i = 0; i < (int)mPoints.size(); i++) {
normalize(mPoints[i].n);
}
#endif // RECALCNORMALS==1
//errMsg("SUBDIV","done nv:"<<mPoints.size()<<" nf:"<<mIndices.size() );
}*/
void IsoSurface::setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc) {
mSCrad1 = radi1*radi1;
mSCrad2 = radi2*radi2;
mSCcenter = mscc;
}
// Diffuse a vector field at 1 vertex, weighted by
// a gaussian of width 1/sqrt(invsigma2)
void IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt)
bool IsoSurface::diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int src, float invsigma2, ntlVec3Gfx &flt)
{
if((neighbors[src].size()<1) || (pointareas[src]<=0.0)) return 0;
const ntlVec3Gfx srcp = mPoints[src].v;
const ntlVec3Gfx srcn = mPoints[src].n;
if(mSCrad1>0.0 && mSCrad2>0.0) {
ntlVec3Gfx dp = mSCcenter-srcp; dp[2] = 0.0; // only xy-plane
float rd = normNoSqrt(dp);
if(rd > mSCrad2) {
//errMsg("TRi","p"<<srcp<<" c"<<mSCcenter<<" rd:"<<rd<<" r1:"<<mSCrad1<<" r2:"<<mSCrad2<<" ");
//invsigma2 *= (rd*rd-mSCrad1);
//flt = ntlVec3Gfx(100); return 1;
return 0;
} else if(rd > mSCrad1) {
// optimize?
float org = 1.0/sqrt(invsigma2);
org *= (1.0- (rd-mSCrad1) / (mSCrad2-mSCrad1));
invsigma2 = 1.0/(org*org);
//flt = ntlVec3Gfx((rd-mSCrad1) / (mSCrad2-mSCrad1)); return 1;
//errMsg("TRi","p"<<srcp<<" rd:"<<rd<<" r1:"<<mSCrad1<<" r2:"<<mSCrad2<<" org:"<<org<<" is:"<<invsigma2);
//invsigma2 *= (rd*rd-mSCrad1);
//return 0;
} else {
}
}
flt = ntlVec3Gfx(0.0);
flt += *(field+pointerScale*v) *pointareas[v];
float sum_w = pointareas[v];
const ntlVec3Gfx &nv = mPoints[v].n;
flt += *(field+pointerScale*src) *pointareas[src];
float sum_w = pointareas[src];
//const ntlVec3Gfx &nv = mPoints[src].n;
unsigned &flag = flag_curr;
flag++;
flags[v] = flag;
vector<int> boundary = neighbors[v];
while (!boundary.empty()) {
const int bbn = boundary.back();
boundary.pop_back();
if (flags[bbn] == flag) continue;
int flag = mFlagCnt;
mFlagCnt++;
flags[src] = flag;
//vector<int> mDboundary = neighbors[src];
mDboundary = neighbors[src];
while (!mDboundary.empty()) {
const int bbn = mDboundary.back();
mDboundary.pop_back();
if(flags[bbn]==flag) continue;
flags[bbn] = flag;
// gaussian weight of width 1/sqrt(invsigma2)
const float d2 = invsigma2 * normNoSqrt(mPoints[bbn].v - mPoints[v].v);
if(d2 >= 9.0f) continue; // 25 also possible , slower
//float w = (d2 >= 9.0f) ? 0.0f : exp(-0.5f*d2);
float w = exp(-0.5f*d2);
if(dot(nv, mPoints[bbn].n) <= 0.0f) continue; // faster than before d2 calc?
// normal check
const float nvdot = dot(srcn, mPoints[bbn].n); // faster than before d2 calc?
if(nvdot <= 0.0f) continue; // faster than before d2 calc?
// gaussian weight of width 1/sqrt(invsigma2)
const float d2 = invsigma2 * normNoSqrt(mPoints[bbn].v - srcp);
if(d2 >= 9.0f) continue; // 25 also possible , slower
//if(dot(srcn, mPoints[bbn].n) <= 0.0f) continue; // faster than before d2 calc?
//float w = (d2 >= 9.0f) ? 0.0f : exp(-0.5f*d2);
//float w = expf(-0.5f*d2);
#if 0
float w=1.0;
// Downweight things pointing in different directions
w *= dot(nv , mPoints[bbn].n);
w *= nvdot; //dot(srcn , mPoints[bbn].n);
// Surface area "belonging" to each point
w *= pointareas[bbn];
// Accumulate weight times field at neighbor
flt += *(field+pointerScale*bbn)*w;
sum_w += w;
for (int i = 0; i < (int)neighbors[bbn].size(); i++) {
int nn = neighbors[bbn][i];
// */
#else
// more aggressive smoothing with: float w=1.0;
float w=nvdot * pointareas[bbn];
// Accumulate weight times field at neighbor
flt += *(field+pointerScale*bbn)*w;
sum_w += w;
#endif
// */
for(int i = 0; i < (int)neighbors[bbn].size(); i++) {
const int nn = neighbors[bbn][i];
if (flags[nn] == flag) continue;
boundary.push_back(nn);
mDboundary.push_back(nn);
}
}
flt /= sum_w;
return 1;
}
void IsoSurface::smoothSurface(float sigma)
// REF
// TestData::getTriangles message: Time for surface generation:3.75s, S(0.0390625,0.1171875)
// ntlWorld::ntlWorld message: Time for start-sims:0s
// TestData::getTriangles message: Time for surface generation:3.69s, S(0.0390625,0.1171875)
void IsoSurface::smoothSurface(float sigma, bool normSmooth)
{
int nv = mPoints.size();
if ((int)flags.size() != nv) flags.resize(nv);
int nf = mIndices.size()/3;
{ // need neighbors
vector<int> numneighbors(mPoints.size());
int i;
for (i = 0; i < (int)mIndices.size()/3; i++) {
@@ -845,10 +605,11 @@ void IsoSurface::smoothSurface(float sigma)
vector<ntlVec3Gfx> dflt(nv);
for (int i = 0; i < nv; i++) {
diffuseVertexField( &mPoints[0].v, 2,
i, invsigma2, dflt[i]);
// Just keep the displacement
dflt[i] -= mPoints[i].v;
if(diffuseVertexField( &mPoints[0].v, 2,
i, invsigma2, dflt[i])) {
// Just keep the displacement
dflt[i] -= mPoints[i].v;
} else { dflt[i] = 0.0; } //?mPoints[i].v; }
}
// Slightly better small-neighborhood approximation
@@ -869,8 +630,9 @@ void IsoSurface::smoothSurface(float sigma)
// Filter displacement field
vector<ntlVec3Gfx> dflt2(nv);
for (int i = 0; i < nv; i++) {
diffuseVertexField( &dflt[0], 1,
i, invsigma2, dflt2[i]);
if(diffuseVertexField( &dflt[0], 1,
i, invsigma2, dflt2[i])) { }
else { /*mPoints[i].v=0.0;*/ dflt2[i] = 0.0; }//dflt2[i]; }
}
// Update vertex positions
@@ -881,10 +643,13 @@ void IsoSurface::smoothSurface(float sigma)
// when normals smoothing off, this cleans up quite well
// costs ca. 50% additional time though
float nsFac = 1.5f;
{ float ninvsigma2 = 1.0f / (nsFac*nsFac*sigma*sigma);
if(normSmooth) { float ninvsigma2 = 1.0f / (nsFac*nsFac*sigma*sigma);
for (int i = 0; i < nv; i++) {
diffuseVertexField( &mPoints[0].n, 2, i, ninvsigma2, dflt[i]);
normalize(dflt[i]);
if( diffuseVertexField( &mPoints[0].n, 2, i, ninvsigma2, dflt[i]) ) {
normalize(dflt[i]);
} else {
dflt[i] = mPoints[i].n;
}
}
for (int i = 0; i < nv; i++) {
mPoints[i].n = dflt[i];
@@ -896,7 +661,9 @@ void IsoSurface::smoothSurface(float sigma)
void IsoSurface::smoothNormals(float sigma)
{
{ // need neighbor
// reuse from smoothSurface
if(neighbors.size() != mPoints.size()) {
// need neighbor
vector<int> numneighbors(mPoints.size());
int i;
for (i = 0; i < (int)mIndices.size()/3; i++) {
@@ -998,13 +765,13 @@ void IsoSurface::smoothNormals(float sigma)
vector<ntlVec3Gfx> nflt(nv);
for (int i = 0; i < nv; i++) {
diffuseVertexField( &mPoints[0].n, 2, i, invsigma2, nflt[i]);
normalize(nflt[i]);
if(diffuseVertexField( &mPoints[0].n, 2, i, invsigma2, nflt[i])) {
normalize(nflt[i]);
} else { nflt[i]=mPoints[i].n; }
}
for (int i = 0; i < nv; i++) {
mPoints[i].n = nflt[i];
}
// copy back
for (int i = 0; i < nv; i++) { mPoints[i].n = nflt[i]; }
//errMsg("SMNRMLS","done v:"<<sigma); // DEBUG
}

View File

@@ -40,9 +40,9 @@ class IsoSurface :
public:
/*! Constructor */
IsoSurface(double iso, double blend);
IsoSurface(double iso);
/*! Destructor */
~IsoSurface();
virtual ~IsoSurface();
/*! Init ararys etc. */
virtual void initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx extent);
@@ -63,9 +63,6 @@ class IsoSurface :
//! Level of the iso surface
double mIsoValue;
//! blending distance for marching cubes
double mBlendVal;
//! Store all the triangles vertices
vector<IsoLevelVertex> mPoints;
@@ -96,8 +93,12 @@ class IsoSurface :
vector<int> mAcrossEdge;
vector< vector<int> > mAdjacentFaces;
vector<unsigned> flags;
unsigned flag_curr;
//! cutoff border area
int mCutoff;
//! trimesh vars
vector<int> flags;
int mFlagCnt;
vector<ntlVec3Gfx> cornerareas;
vector<float> pointareas;
vector< vector<int> > neighbors;
@@ -116,6 +117,8 @@ class IsoSurface :
//! set loop subdiv num
inline void setSmoothSurface(float set) { mSmoothSurface = set; };
inline void setSmoothNormals(float set) { mSmoothNormals = set; };
inline float getSmoothSurface() { return mSmoothSurface; }
inline float getSmoothNormals() { return mSmoothNormals; }
// geometry object functions
virtual void getTriangles( vector<ntlTriangle> *triangles,
@@ -155,6 +158,8 @@ class IsoSurface :
return mpData + ISOLEVEL_INDEX(ii+1,jj+1,kk+1);
#endif
}
//! set cut off border
inline void setCutoff(int set) { mCutoff = set; };
//! OpenGL viz "interface"
unsigned int getIsoVertexCount() {
@@ -170,15 +175,20 @@ class IsoSurface :
return &(mIndices[0]);
}
// surface smoothing functions
void setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc);
void smoothSurface(float val, bool smoothNorm);
void smoothNormals(float val);
protected:
//! computer normal
//! compute normal
inline ntlVec3Gfx getNormal(int i, int j,int k);
void subdivide();
void smoothSurface(float val);
void smoothNormals(float val);
void diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt);
//! smoothing helper function
bool diffuseVertexField(ntlVec3Gfx *field, int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt);
vector<int> mDboundary;
float mSCrad1, mSCrad2;
ntlVec3Gfx mSCcenter;
};

View File

@@ -14,7 +14,8 @@
#include "utilities.h"
#include "ntl_matrices.h"
#include "ntl_blenderdumper.h"
#include "ntl_scene.h"
#include "ntl_world.h"
#include "solver_interface.h"
#include <zlib.h>
@@ -31,17 +32,15 @@ ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) :
AttributeList *pAttrs = glob->getBlenderAttributes();
mpTrafo = new ntlMat4Gfx(0.0);
mpTrafo->initId();
(*mpTrafo) = pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false );
pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false, mpTrafo );
}
ntlBlenderDumper::ntlBlenderDumper(elbeemSimulationSettings *settings) :
ntlWorld(settings), mpTrafo(NULL)
{
// same as normal constructor here
ntlRenderGlobals *glob = mpGlob;
AttributeList *pAttrs = glob->getBlenderAttributes();
mpTrafo = new ntlMat4Gfx(0.0);
mpTrafo->initId();
(*mpTrafo) = pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false );
mpTrafo->initArrayCheck(settings->surfaceTrafo);
//errMsg("ntlBlenderDumper","mpTrafo inited: "<<(*mpTrafo) );
}
@@ -52,6 +51,7 @@ ntlBlenderDumper::ntlBlenderDumper(elbeemSimulationSettings *settings) :
ntlBlenderDumper::~ntlBlenderDumper()
{
delete mpTrafo;
debMsgStd("ntlBlenderDumper",DM_NOTIFY, "ntlBlenderDumper done", 10);
}
/******************************************************************************
@@ -61,11 +61,11 @@ int ntlBlenderDumper::renderScene( void )
{
char nrStr[5]; /* nr conversion */
ntlRenderGlobals *glob = mpGlob;
ntlScene *scene = mpGlob->getScene();
ntlScene *scene = mpGlob->getSimScene();
bool debugOut = true;
#if ELBEEM_BLENDER==1
#if ELBEEM_PLUGIN==1
debugOut = false;
#endif // ELBEEM_BLENDER==1
#endif // ELBEEM_PLUGIN==1
// output path
/*std::ostringstream ecrpath("");
@@ -91,6 +91,7 @@ int ntlBlenderDumper::renderScene( void )
vector<ntlTriangle> Triangles;
vector<ntlVec3Gfx> Vertices;
vector<ntlVec3Gfx> VertNormals;
errMsg("ntlBlenderDumper","mpTrafo : "<<(*mpTrafo) );
/* init geometry array, first all standard objects */
int idCnt = 0; // give IDs to objects
@@ -106,80 +107,117 @@ int ntlBlenderDumper::renderScene( void )
if(tid & GEOCLASSTID_SHADER) {
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter);
hideObjs.push_back( (*iter)->getName() );
geoshad->notifyShaderOfDump(glob->getAniCount(),nrStr,glob->getOutFilename());
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(glob->getAniCount(),nrStr,glob->getOutFilename());
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;
// only dump geo shader objects
Triangles.clear();
Vertices.clear();
VertNormals.clear();
(*siter)->initialize( mpGlob );
//int vstart = mVertNormals.size()-1;
(*siter)->getTriangles(&Triangles, &Vertices, &VertNormals, idCnt);
idCnt ++;
// always dump mesh, even empty ones...
//if(Vertices.size() <= 0) continue;
//if(Triangles.size() <= 0) continue;
for(size_t i=0; i<Vertices.size(); i++) {
Vertices[i] = (*mpTrafo) * Vertices[i];
}
// dump to binary file
std::ostringstream boutfilename("");
//boutfilename << ecrpath.str() << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj";
boutfilename << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".bobj";
boutfilename << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr;
if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName()
<<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<<
" to "<<boutfilename.str() , 7);
bool isPreview = false;
if( (*siter)->getName().find( "preview" ) != string::npos) {
isPreview = true;
}
boutfilename << ".gz";
// compress all bobj's except for preview ones...
gzFile gzf;
if(isPreview) {
gzf = gzopen(boutfilename.str().c_str(), "wb1");
} else {
gzf = gzopen(boutfilename.str().c_str(), "wb9");
// output velocities if desired
// WARNING - this is dirty, but simobjs are the only geoshaders right now
SimulationObject *sim = (SimulationObject *)geoshad;
LbmSolverInterface *lbm = sim->getSolver();
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?
//? v = (*mpTrafo) * v;
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";
//if(isPreview) { } else { }
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; }
int wri;
float wrf;
if(sizeof(wri)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
wri = Vertices.size();
gzwrite(gzf, &wri, sizeof(wri));
// transform into source space
for(size_t i=0; i<Vertices.size(); i++) {
Vertices[i] = (*mpTrafo) * Vertices[i];
}
// 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++) {
wrf = Vertices[i][j];
gzwrite(gzf, &wrf, sizeof(wrf)); }
float vertp = Vertices[i][j];
gzwrite(gzf, &vertp, sizeof(vertp)); }
}
// should be the same as Vertices.size
wri = VertNormals.size();
gzwrite(gzf, &wri, sizeof(wri));
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++) {
wrf = VertNormals[i][j];
gzwrite(gzf, &wrf, sizeof(wrf)); }
float normp = VertNormals[i][j];
gzwrite(gzf, &normp, sizeof(normp)); }
}
wri = Triangles.size();
gzwrite(gzf, &wri, sizeof(wri));
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++) {
wri = Triangles[i].getPoints()[j];
gzwrite(gzf, &wri, sizeof(wri)); }
int triIndex = Triangles[i].getPoints()[j];
gzwrite(gzf, &triIndex, sizeof(triIndex)); }
}
gzclose( gzf );
debMsgDirect(" Wrote: '"<<boutfilename.str()<<"'. ");
debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY," Wrote: '"<<boutfilename.str()<<"' ", 2);
numGMs++;
}
}
@@ -200,6 +238,7 @@ int ntlBlenderDumper::renderScene( void )
debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10);
// still render for preview...
debugOut = false; // DEBUG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if(debugOut) {
debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1);
ntlWorld::renderScene(); }

View File

@@ -9,7 +9,6 @@
#include "ntl_bsptree.h"
#include "ntl_scene.h"
#include "utilities.h"
#include <algorithm>
@@ -146,7 +145,7 @@ 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)
mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0)
{
// init scene data pointers
mpVertices = scene->getVertexPointer();
@@ -175,11 +174,12 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
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
//errorOut(" d "<<(int)(*iter).getFlags() <<" "<< (int)mTriangleMask );
if( ((int)(*iter).getFlags() & (int)mTriangleMask) == 0 ) {
continue;
}
@@ -194,9 +194,11 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
// */
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];
@@ -241,6 +243,8 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
mpRoot->cloneVec = 0;
globalSortingPoints = mpVertices;
mpTriDist = new char[ mppTriangles->size() ];
mNumNodes = 1;
mAbortSubdiv = 0;
/* create tree */
debugOutInter( "Generating BSP Tree... (Nodes "<< mCurrentNodes <<
@@ -265,9 +269,15 @@ ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
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;
}
}
/******************************************************************************
@@ -295,6 +305,7 @@ void ntlTree::subdivide(BSPNode *node, int depth, int axis)
if( ( (int)node->members->size() > mMaxListLength) &&
(depth < mMaxDepth )
&& (node->cloneVec<10)
&& (!mAbortSubdiv)
) {
gfxReal planeDiv = 0.499999; // position of plane division
@@ -339,6 +350,9 @@ void ntlTree::subdivide(BSPNode *node, int depth, int axis)
node->child[i]->members = NULL;
nextAxis = (axis+1)%3;
node->child[i]->axis = nextAxis;
mNumNodes++;
// abort when using 256MB only for tree...
if(mNumNodes*sizeof(BSPNode)> 1024*1024*512) mAbortSubdiv = 1;
/* current division plane */
if(!i) {
@@ -489,6 +503,7 @@ void ntlTree::intersect(const ntlRay &ray, gfxReal &distance,
ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist);
if((maxdist < 0.0) ||
(!mpRoot) ||
(mindist == GFX_REAL_MAX) ||
(maxdist == GFX_REAL_MAX) ) {
distance = -1.0;
@@ -681,6 +696,7 @@ void ntlTree::intersectX(const ntlRay &ray, gfxReal &distance,
ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist); // +X
if((maxdist < 0.0) ||
(!mpRoot) ||
(mindist == GFX_REAL_MAX) ||
(maxdist == GFX_REAL_MAX) ) {
distance = -1.0;

View File

@@ -6,14 +6,11 @@
* Tree container for fast triangle intersects
*
*****************************************************************************/
#ifndef NTL_TREE_HH
#define NTL_TREE_HH
#ifndef NTL_TREE_H
#define NTL_TREE_H
#include "ntl_vector3dim.h"
#include "ntl_ray.h"
#include "ntl_triangle.h"
#define AXIS_X 0
@@ -29,6 +26,8 @@ class BSPNode;
class BSPStackElement;
class BSPStack;
class TriangleBBox;
class ntlScene;
class ntlTriangle;
//! Class for a bsp tree for triangles
@@ -85,6 +84,9 @@ class ntlTree
//! root node pointer
BSPNode *mpRoot;
//! count no. of node
int mNumNodes;
int mAbortSubdiv;
//! stack for the node pointers
BSPStack *mpNodeStack;

View File

@@ -28,6 +28,7 @@ class ntlGeometryClass
//! Default constructor
inline ntlGeometryClass() :
mVisible( 1 ), mName( "[ObjNameUndef]" ),
mObjectId(-1),
mpAttrs( NULL )
{
mpAttrs = new AttributeList("objAttrs");
@@ -62,6 +63,10 @@ class ntlGeometryClass
virtual inline ntlVec3Gfx *getBBStart() { return NULL; }
virtual inline ntlVec3Gfx *getBBEnd() { return NULL; }
/*! Set/get the object id*/
inline void setObjectId(int set) { mObjectId=set; }
inline int getObjectId() const { return mObjectId; }
/*! GUI - this function is called for selected objects to display debugging information with OpenGL */
virtual void drawDebugDisplay() { /* do nothing by default */ }
/*! GUI - this function is called for selected objects to display interactive information with OpenGL */
@@ -79,6 +84,9 @@ class ntlGeometryClass
/*! Name of this object */
string mName;
/*! global scene object id */
int mObjectId;
/*! configuration attributes */
AttributeList *mpAttrs;

View File

@@ -9,7 +9,7 @@
#include "ntl_geometrymodel.h"
#include "ntl_ray.h"
#include "ntl_scene.h"
#include "ntl_world.h"
#include "zlib.h"
#ifdef WIN32
@@ -46,6 +46,13 @@ ntlGeometryObjModel::~ntlGeometryObjModel()
/*****************************************************************************/
void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob)
{
// perhaps the model is already inited from initModel below?
if(mLoaded==1) {
// init default material
searchMaterial( glob->getMaterials() );
return;
}
ntlGeometryObject::initialize(glob);
mFilename = mpAttrs->readString("filename", mFilename,"ntlGeometryObjModel", "mFilename", true);
@@ -73,9 +80,117 @@ void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob)
}
}
/******************************************************************************
* init model from given vertex and triangle arrays
*****************************************************************************/
int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles)
{
mVertices.clear();
mVertices.resize( numVertices );
mNormals.resize( numVertices );
for(int i=0; i<numVertices; i++) {
mVertices[i] = ntlVec3Gfx(vertices[i*3+0],vertices[i*3+1],vertices[i*3+2]);
mNormals[i] = ntlVec3Gfx(1.0); // unused, set to !=0.0
}
mTriangles.clear();
mTriangles.resize( 3*numTriangles );
for(int i=0; i<numTriangles; i++) {
mTriangles[3*i+0] = triangles[i*3+0];
mTriangles[3*i+1] = triangles[i*3+1];
mTriangles[3*i+2] = triangles[i*3+2];
}
// inited, no need to parse attribs etc.
mLoaded = 1;
return 0;
}
/******************************************************************************
* load model from .obj file
*****************************************************************************/
int ntlGeometryObjModel::loadBobjModel(string filename)
{
const bool debugPrint=false;
gzFile gzf;
gzf = gzopen(filename.c_str(), "rb");
if (!gzf) {
errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to open '"<< filename <<"'...\n", SIMWORLD_INITERROR );
return 1;
}
int numVerts;
if(sizeof(numVerts)!=4) { // paranoia check
errMsg("Reading GZ_BOBJ"," Invalid int size, check compiler settings: int has to be 4 byte long");
goto gzreaderror;
}
gzread(gzf, &numVerts, sizeof(numVerts) );
if(numVerts<0 || numVerts>1e9) {
errMsg("Reading GZ_BOBJ"," invalid num vertices "<< numVerts);
goto gzreaderror;
}
mVertices.clear();
mVertices.resize( numVerts );
for(int i=0; i<numVerts; i++) {
float x[3];
for(int j=0; j<3; j++) {
gzread(gzf, &(x[j]), sizeof( (x[j]) ) );
}
mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]);
}
if(debugPrint) errMsg("NV"," "<<numVerts<<" "<< mVertices.size() );
// should be the same as Vertices.size
gzread(gzf, &numVerts, sizeof(numVerts) );
if(numVerts<0 || numVerts>1e9) {
errMsg("Reading GZ_BOBJ","invalid num normals "<< numVerts);
goto gzreaderror;
}
mNormals.clear();
mNormals.resize( numVerts );
for(int i=0; i<numVerts; i++) {
float n[3];
for(int j=0; j<3; j++) {
gzread(gzf, &(n[j]), sizeof( (n[j]) ) );
}
mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]);
}
if(debugPrint) errMsg("NN"," "<<numVerts<<" "<< mNormals.size() );
int numTris;
gzread(gzf, &numTris, sizeof(numTris) );
if(numTris<0 || numTris>1e9) {
errMsg("Reading GZ_BOBJ","invalid num normals "<< numTris);
goto gzreaderror;
}
mTriangles.resize( 3*numTris );
for(int i=0; i<numTris; i++) {
int tri[3];
for(int j=0; j<3; j++) {
gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) );
}
mTriangles[3*i+0] = tri[0];
mTriangles[3*i+1] = tri[1];
mTriangles[3*i+2] = tri[2];
}
if(debugPrint) errMsg("NT"," "<<numTris<<" "<< mTriangles.size() );
debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 );
gzclose( gzf );
return 0;
gzreaderror:
mTriangles.clear();
mVertices.clear();
mNormals.clear();
gzclose( gzf );
errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to load '"<< filename <<"', exiting...\n", SIMWORLD_INITERROR );
return 1;
}
/* defines */
#define T(x) model->triangles[(x)]
/******************************************************************************
*
@@ -94,129 +209,18 @@ ntlGeometryObjModel::getTriangles( vector<ntlTriangle> *triangles,
trip[0] = mTriangles[i+0];
trip[1] = mTriangles[i+1];
trip[2] = mTriangles[i+2];
sceneAddTriangle(
mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]],
mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]],
ntlVec3Gfx(0.0), 1 ); /* normal unused */
ntlVec3Gfx(0.0), 1 , triangles,vertices,normals ); /* normal unused */
}
objectId = -1; // remove warning
// bobj
return;
}
/******************************************************************************
* load model from .obj file
*****************************************************************************/
int ntlGeometryObjModel::loadBobjModel(string filename)
{
const bool debugPrint=false;
gzFile gzf;
gzf = gzopen(filename.c_str(), "rb");
if (!gzf) {
errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to open '"<< filename <<"'...\n", SIMWORLD_INITERROR );
return 1;
}
int wri;
int gotbytes = -1;
gotbytes = gzread(gzf, &wri, sizeof(wri) );
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ"," Invalid readNV size "<< wri); goto gzreaderror; }
if(sizeof(wri)!=4) { // paranoia check
errMsg("Reading GZ_BOBJ"," Invalid int size "<< wri);
goto gzreaderror;
}
if(wri<0 || wri>1e9) {
errMsg("Reading GZ_BOBJ"," invalid num vertices "<< wri);
goto gzreaderror;
}
mVertices.clear();
mVertices.resize( wri );
for(int i=0; i<wri; i++) {
float x[3];
for(int j=0; j<3; j++) {
gotbytes = gzread(gzf, &(x[j]), sizeof( (x[j]) ) );
if(gotbytes != sizeof(float)){ errMsg("Reading GZ_BOBJ"," Invalid readV size "<< wri); goto gzreaderror; } // CHECK
}
mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]);
}
if(debugPrint) errMsg("NV"," "<<wri<<" "<< mVertices.size() );
// should be the same as Vertices.size
gotbytes = gzread(gzf, &wri, sizeof(wri) );
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readNN size "<< wri); goto gzreaderror; }
if(wri<0 || wri>1e9) {
errMsg("Reading GZ_BOBJ","invalid num normals "<< wri);
goto gzreaderror;
}
mNormals.clear();
mNormals.resize( wri );
for(int i=0; i<wri; i++) {
float n[3];
for(int j=0; j<3; j++) {
gotbytes = gzread(gzf, &(n[j]), sizeof( (n[j]) ) );
if(gotbytes != sizeof(float)){ errMsg("Reading GZ_BOBJ","Invalid readN size "<< wri); goto gzreaderror; }
}
mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]);
}
if(debugPrint) errMsg("NN"," "<<wri<<" "<< mNormals.size() );
gotbytes = gzread(gzf, &wri, sizeof(wri) );
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readNT size "<< wri); goto gzreaderror; }
if(wri<0 || wri>1e9) {
errMsg("Reading GZ_BOBJ","invalid num normals "<< wri);
goto gzreaderror;
}
mTriangles.resize( 3*wri );
for(int i=0; i<wri; i++) {
int tri[3];
for(int j=0; j<3; j++) {
gotbytes = gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) );
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readT size "<< wri); goto gzreaderror; }
}
mTriangles[3*i+0] = tri[0];
mTriangles[3*i+1] = tri[1];
mTriangles[3*i+2] = tri[2];
}
if(debugPrint) errMsg("NT"," "<<wri<<" "<< mTriangles.size() );
debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 );
gzclose( gzf );
return 0;
gzreaderror:
mTriangles.clear();
mVertices.clear();
mNormals.clear();
gzclose( gzf );
errFatal("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to load '"<< filename <<"', exiting...\n", SIMWORLD_INITERROR );
return 1;
}
/******************************************************************************
* init model from given vertex and triangle arrays
*****************************************************************************/
int ntlGeometryObjModel::initModel(int numVertices, float *vertices, int numTriangles, int *triangles)
{
mVertices.clear();
mVertices.resize( numVertices );
for(int i=0; i<numVertices; i++) {
//mVertices[i] = ntlVec3Gfx(vertices[i][0],vertices[i][1],vertices[i][2]);
mVertices[i] = ntlVec3Gfx(vertices[i*3+0],vertices[i*3+1],vertices[i*3+2]);
}
mTriangles.clear();
mTriangles.resize( 3*numTriangles );
for(int i=0; i<numTriangles; i++) {
mTriangles[3*i+0] = triangles[i*3+0];
mTriangles[3*i+1] = triangles[i*3+1];
mTriangles[3*i+2] = triangles[i*3+2];
}
return 0;
}

View File

@@ -10,7 +10,8 @@
#include "ntl_geometryobject.h"
#include "ntl_renderglobals.h"
#include "ntl_world.h"
#include "ntl_matrices.h"
// for FGI
#include "elbeem.h"
@@ -21,13 +22,23 @@
/* Default constructor */
/*****************************************************************************/
ntlGeometryObject::ntlGeometryObject() :
mpMaterial( NULL ),
mIsInitialized(false), mpMaterial( NULL ),
mMaterialName( "default" ),
mCastShadows( 1 ),
mReceiveShadows( 1 ),
mGeoInitId( -1 ), mGeoInitType( 0 ),
mInitialVelocity(0.0),
mGeoInitIntersect(false)
mInitialVelocity(0.0), mcInitialVelocity(0.0), mLocalCoordInivel(false),
mGeoInitIntersect(false),
mGeoPartSlipValue(0.0),
mOnlyThinInit(false),
mInitialPos(0.),
mcTrans(0.), mcRot(0.), mcScale(1.),
mIsAnimated(false),
mMovPoints(), mMovNormals(),
mHaveCachedMov(false),
mCachedMovPoints(), mCachedMovNormals(),
mMovPntsInited(-100.0), mMaxMovPnt(-1),
mcGeoActive(1.)
{
};
@@ -60,6 +71,11 @@ static int initStringTypes[GEOINIT_STRINGS] = {
void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
{
//debugOut("ntlGeometryObject::initialize: '"<<getName()<<"' ", 10);
// initialize only once...
if(mIsInitialized) return;
// init material, always necessary
searchMaterial( glob->getMaterials() );
mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"ntlGeometryObject", "mGeoInitId", false);
mGeoInitIntersect = mpAttrs->readInt("geoinit_intersect", mGeoInitIntersect,"ntlGeometryObject", "mGeoInitIntersect", false);
@@ -74,7 +90,7 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
}
if(!gotit) {
errFatal("ntlGeometryObject::initialize","Unkown 'geoinittype' value: '"<< ginitStr <<"' ", SIMWORLD_INITERROR);
errFatal("ntlGeometryObject::initialize","Obj '"<<mName<<"', Unkown 'geoinittype' value: '"<< ginitStr <<"' ", SIMWORLD_INITERROR);
return;
}
}
@@ -84,32 +100,77 @@ void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
// disable geo init again...
mGeoInitId = -1;
}
mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false));
mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false));
if(getAttributeList()->exists("initial_velocity") || (!mcInitialVelocity.isInited()) ) {
mcInitialVelocity = mpAttrs->readChannelVec3f("initial_velocity");
}
// always use channel
if(!mcInitialVelocity.isInited()) { mcInitialVelocity = AnimChannel<ntlVec3Gfx>(mInitialVelocity); }
mLocalCoordInivel = mpAttrs->readBool("geoinit_localinivel", mLocalCoordInivel,"ntlGeometryObject", "mLocalCoordInivel", false);
mGeoPartSlipValue = mpAttrs->readFloat("geoinit_partslip", mGeoPartSlipValue,"ntlGeometryObject", "mGeoPartSlipValue", false);
debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': gid="<<mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<<
" gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug
mOnlyThinInit = mpAttrs->readBool("geoinit_onlythin", mOnlyThinInit,"ntlGeometryObject", "mOnlyThinInit", false);
// override cfg types
mVisible = mpAttrs->readBool("visible", mVisible,"ntlGeometryObject", "mVisible", false);
mReceiveShadows = mpAttrs->readBool("recv_shad", mReceiveShadows,"ntlGeometryObject", "mReceiveShadows", false);
mCastShadows = mpAttrs->readBool("cast_shad", mCastShadows,"ntlGeometryObject", "mCastShadows", false);
// init material
searchMaterial( glob->getMaterials() );
// read mesh animation channels
ntlVec3d translation(0.0);
translation = mpAttrs->readVec3d("translation", translation,"ntlGeometryObject", "translation", false);
if(getAttributeList()->exists("translation") || (!mcTrans.isInited()) ) {
mcTrans = mpAttrs->readChannelVec3f("translation");
}
ntlVec3d rotation(0.0);
rotation = mpAttrs->readVec3d("rotation", rotation,"ntlGeometryObject", "rotation", false);
if(getAttributeList()->exists("rotation") || (!mcRot.isInited()) ) {
mcRot = mpAttrs->readChannelVec3f("rotation");
}
ntlVec3d scale(1.0);
scale = mpAttrs->readVec3d("scale", scale,"ntlGeometryObject", "scale", false);
if(getAttributeList()->exists("scale") || (!mcScale.isInited()) ) {
mcScale = mpAttrs->readChannelVec3f("scale");
}
float geoactive=1.;
geoactive = mpAttrs->readFloat("geoactive", geoactive,"ntlGeometryObject", "geoactive", false);
if(getAttributeList()->exists("geoactive") || (!mcGeoActive.isInited()) ) {
mcGeoActive = mpAttrs->readChannelFloat("geoactive");
}
// always use channel
if(!mcGeoActive.isInited()) { mcGeoActive = AnimChannel<double>(geoactive); }
if( (mcTrans.accessValues().size()>1) // VALIDATE
|| (mcRot.accessValues().size()>1)
|| (mcScale.accessValues().size()>1)
|| (mcGeoActive.accessValues().size()>1)
|| (mcInitialVelocity.accessValues().size()>1)
) {
mIsAnimated = true;
}
mIsInitialized = true;
debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': visible="<<this->mVisible<<" gid="<<mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<<
" gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug
}
/*! notify object that dump is in progress (e.g. for particles) */
// default action - do nothing...
void ntlGeometryObject::notifyOfDump(int frameNr,char *frameNrStr,string outfilename) {
bool debugOut=false;
if(debugOut) debMsgStd("ntlGeometryObject::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr<<","<<frameNr<<" to "<<outfilename, 10); // DEBUG
}
/*****************************************************************************/
/* Search the material for this object from the material list */
/*****************************************************************************/
void ntlGeometryObject::searchMaterial(vector<ntlMaterial *> *mat)
{
//errorOut("my: "<<mMaterialName); // DEBUG
/* search the list... */
int i=0;
for (vector<ntlMaterial*>::iterator iter = mat->begin();
iter != mat->end(); iter++) {
//if(strcmp(mMaterialName, (*iter)->getName()) == 0) { // DEBUG
if( mMaterialName == (*iter)->getName() ) {
//warnMsg("ntlGeometryObject::searchMaterial","for obj '"<<getName()<<"' found - '"<<(*iter)->getName()<<"' "<<i); // DEBUG
mpMaterial = (*iter);
@@ -118,8 +179,385 @@ void ntlGeometryObject::searchMaterial(vector<ntlMaterial *> *mat)
i++;
}
errFatal("ntlGeometryObject::searchMaterial","Unknown material '"<<mMaterialName<<"' ! ", SIMWORLD_INITERROR);
mpMaterial = new ntlMaterial();
return;
}
/******************************************************************************
* static add triangle function
*****************************************************************************/
void ntlGeometryObject::sceneAddTriangle(
ntlVec3Gfx p1,ntlVec3Gfx p2,ntlVec3Gfx p3,
ntlVec3Gfx pn1,ntlVec3Gfx pn2,ntlVec3Gfx pn3,
ntlVec3Gfx trin, bool smooth,
vector<ntlTriangle> *triangles,
vector<ntlVec3Gfx> *vertices,
vector<ntlVec3Gfx> *normals) {
ntlTriangle tri;
int tempVert;
if(normals->size() != vertices->size()) {
errFatal("ntlGeometryObject::sceneAddTriangle","For '"<<this->mName<<"': Vertices and normals sizes to not match!!!",SIMWORLD_GENERICERROR);
} else {
vertices->push_back( p1 );
normals->push_back( pn1 );
tempVert = normals->size()-1;
tri.getPoints()[0] = tempVert;
vertices->push_back( p2 );
normals->push_back( pn2 );
tempVert = normals->size()-1;
tri.getPoints()[1] = tempVert;
vertices->push_back( p3 );
normals->push_back( pn3 );
tempVert = normals->size()-1;
tri.getPoints()[2] = tempVert;
/* init flags from ntl_ray.h */
int flag = 0;
if(getVisible()){ flag |= TRI_GEOMETRY; }
if(getCastShadows() ) {
flag |= TRI_CASTSHADOWS; }
if( (getMaterial()->getMirror()>0.0) ||
(getMaterial()->getTransparence()>0.0) ||
(getMaterial()->getFresnel()>0.0) ) {
flag |= TRI_MAKECAUSTICS; }
else {
flag |= TRI_NOCAUSTICS; }
/* init geo init id */
int geoiId = getGeoInitId();
if((geoiId > 0) && (!mOnlyThinInit) && (!mIsAnimated)) {
flag |= (1<< (geoiId+4));
flag |= mGeoInitType;
}
/*errMsg("ntlScene::addTriangle","DEBUG flag="<<convertFlags2String(flag) ); */
tri.setFlags( flag );
/* triangle normal missing */
tri.setNormal( trin );
tri.setSmoothNormals( smooth );
tri.setObjectId( this->mObjectId );
triangles->push_back( tri );
} /* normals check*/
}
/******************************************************************************/
/* Init channels from float arrays (for elbeem API) */
/******************************************************************************/
#define ADD_CHANNEL_VEC(dst,nvals,val) \
vals.clear(); time.clear(); elbeemSimplifyChannelVec3(val,&nvals); \
for(int i=0; i<(nvals); i++) { \
vals.push_back(ntlVec3Gfx((val)[i*4+0], (val)[i*4+1],(val)[i*4+2] )); \
time.push_back( (val)[i*4+3] ); \
} \
(dst) = AnimChannel< ntlVec3Gfx >(vals,time);
#define ADD_CHANNEL_FLOAT(dst,nvals,val) \
valsd.clear(); time.clear(); elbeemSimplifyChannelFloat(val,&nvals); \
for(int i=0; i<(nvals); i++) { \
valsd.push_back( (val)[i*2+0] ); \
time.push_back( (val)[i*2+1] ); \
} \
(dst) = AnimChannel< double >(valsd,time);
void ntlGeometryObject::initChannels(
int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale,
int nAct, float *act, int nIvel, float *ivel
) {
const bool debugInitc=true;
if(debugInitc) { debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"nt:"<<nTrans<<" nr:"<<nRot<<" ns:"<<nScale, 10);
debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"na:"<<nAct<<" niv:"<<nIvel<<" ", 10); }
vector<ntlVec3Gfx> vals;
vector<double> valsd;
vector<double> time;
if((trans)&&(nTrans>0)) { ADD_CHANNEL_VEC(mcTrans, nTrans, trans); }
if((rot)&&(nRot>0)) { ADD_CHANNEL_VEC(mcRot, nRot, rot); }
if((scale)&&(nScale>0)) { ADD_CHANNEL_VEC(mcScale, nScale, scale); }
if((act)&&(nAct>0)) { ADD_CHANNEL_FLOAT(mcGeoActive, nAct, act); }
if((ivel)&&(nIvel>0)) { ADD_CHANNEL_VEC(mcInitialVelocity, nIvel, ivel); }
if( (mcTrans.accessValues().size()>1) // VALIDATE
|| (mcRot.accessValues().size()>1)
|| (mcScale.accessValues().size()>1)
|| (mcGeoActive.accessValues().size()>1)
|| (mcInitialVelocity.accessValues().size()>1)
) {
mIsAnimated = true;
}
if(debugInitc) {
debMsgStd("ntlGeometryObject::initChannels",DM_MSG,getName()<<
" nt:"<<mcTrans.accessValues().size()<<" nr:"<<mcRot.accessValues().size()<<
" ns:"<<mcScale.accessValues().size()<<" isAnim:"<<mIsAnimated, 10); }
if(debugInitc) {
std::ostringstream ostr;
ostr << "trans: ";
for(size_t i=0; i<mcTrans.accessValues().size(); i++) {
ostr<<" "<<mcTrans.accessValues()[i]<<"@"<<mcTrans.accessTimes()[i]<<" ";
} ostr<<"; ";
ostr<<"rot: ";
for(size_t i=0; i<mcRot.accessValues().size(); i++) {
ostr<<" "<<mcRot.accessValues()[i]<<"@"<<mcRot.accessTimes()[i]<<" ";
} ostr<<"; ";
ostr<<"scale: ";
for(size_t i=0; i<mcScale.accessValues().size(); i++) {
ostr<<" "<<mcScale.accessValues()[i]<<"@"<<mcScale.accessTimes()[i]<<" ";
} ostr<<"; ";
ostr<<"act: ";
for(size_t i=0; i<mcGeoActive.accessValues().size(); i++) {
ostr<<" "<<mcGeoActive.accessValues()[i]<<"@"<<mcGeoActive.accessTimes()[i]<<" ";
} ostr<<"; ";
ostr<<"ivel: ";
for(size_t i=0; i<mcInitialVelocity.accessValues().size(); i++) {
ostr<<" "<<mcInitialVelocity.accessValues()[i]<<"@"<<mcInitialVelocity.accessTimes()[i]<<" ";
} ostr<<"; ";
debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"Inited "<<ostr.str(),10);
}
}
#undef ADD_CHANNEL
/*****************************************************************************/
/* apply object translation at time t*/
/*****************************************************************************/
void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts, vector<ntlVec3Gfx> *norms, int vstart, int vend, int forceTrafo) {
if( (mcTrans.accessValues().size()>1) // VALIDATE
|| (mcRot.accessValues().size()>1)
|| (mcScale.accessValues().size()>1)
|| (forceTrafo)
|| (!mHaveCachedMov)
) {
// transformation is animated, continue
ntlVec3Gfx pos = mcTrans.get(t);
ntlVec3Gfx scale = mcScale.get(t);
ntlVec3Gfx rot = mcRot.get(t);
ntlMat4Gfx rotMat;
rotMat.initRotationXYZ(rot[0],rot[1],rot[2]);
pos += mInitialPos;
//errMsg("ntlGeometryObject::applyTransformation","obj="<<getName()<<" t"<<pos<<" r"<<rot<<" s"<<scale);
for(int i=vstart; i<vend; i++) {
(*verts)[i] *= scale;
(*verts)[i] = rotMat * (*verts)[i];
(*verts)[i] += pos;
}
if(norms) {
for(int i=vstart; i<vend; i++) {
(*norms)[i] = rotMat * (*norms)[i];
}
}
} else {
// not animated, cached points were already returned
errMsg ("ntlGeometryObject::applyTransformation","Object "<<getName()<<" used cached points ");
}
}
/*! Prepare points for moving objects */
void ntlGeometryObject::initMovingPoints(gfxReal featureSize) {
if(mMovPntsInited==featureSize) return;
const bool debugMoinit=false;
vector<ntlTriangle> triangles;
vector<ntlVec3Gfx> vertices;
vector<ntlVec3Gfx> normals;
int objectId = 1;
this->getTriangles(&triangles,&vertices,&normals,objectId);
mMovPoints.clear(); //= vertices;
mMovNormals.clear(); //= normals;
if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" has v:"<<vertices.size()<<" t:"<<triangles.size() );
// no points?
if(vertices.size()<1) {
mMaxMovPnt=-1;
return;
}
ntlVec3f maxscale = channelFindMaxVf(mcScale);
float maxpart = ABS(maxscale[0]);
if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
float scaleFac = 1.0/(maxpart);
// TODO - better reinit from time to time?
const gfxReal fsTri = featureSize*0.5 *scaleFac;
if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","maxscale:"<<maxpart<<" featureSize:"<<featureSize<<" fsTri:"<<fsTri );
// debug: count points to init
if(debugMoinit) {
errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" estimating...");
int countp=vertices.size()*2;
for(size_t i=0; i<triangles.size(); i++) {
ntlVec3Gfx p0 = vertices[ triangles[i].getPoints()[0] ];
ntlVec3Gfx side1 = vertices[ triangles[i].getPoints()[1] ] - p0;
ntlVec3Gfx side2 = vertices[ triangles[i].getPoints()[2] ] - p0;
int divs1=0, divs2=0;
if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
errMsg("ntlGeometryObject::initMovingPoints","tri:"<<i<<" p:"<<p0<<" s1:"<<side1<<" s2:"<<side2<<" -> "<<divs1<<","<<divs2 );
if(divs1+divs2 > 0) {
for(int u=0; u<=divs1; u++) {
for(int v=0; v<=divs2; v++) {
const gfxReal uf = (gfxReal)(u+0.25) / (gfxReal)(divs1+0.0);
const gfxReal vf = (gfxReal)(v+0.25) / (gfxReal)(divs2+0.0);
if(uf+vf>1.0) continue;
countp+=2;
}
}
}
}
errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" requires:"<<countp*2);
}
bool discardInflowBack = false;
if( (mGeoInitType==FGI_MBNDINFLOW) && (mcInitialVelocity.accessValues().size()<1) ) discardInflowBack = true;
discardInflowBack = false; // DEBUG disable for now
// init std points
for(size_t i=0; i<vertices.size(); i++) {
ntlVec3Gfx p = vertices[ i ];
ntlVec3Gfx n = normals[ i ];
// discard inflow backsides
//if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) {
if(discardInflowBack) { //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) {
if(dot(mInitialVelocity,n)<0.0) continue;
}
mMovPoints.push_back(p);
mMovNormals.push_back(n);
}
// init points & refine...
for(size_t i=0; i<triangles.size(); i++) {
ntlVec3Gfx p0 = vertices[ triangles[i].getPoints()[0] ];
ntlVec3Gfx side1 = vertices[ triangles[i].getPoints()[1] ] - p0;
ntlVec3Gfx side2 = vertices[ triangles[i].getPoints()[2] ] - p0;
int divs1=0, divs2=0;
if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
/* if( (i!=6) &&
(i!=6) ) { divs1=divs2=0; } // DEBUG */
if(divs1+divs2 > 0) {
for(int u=0; u<=divs1; u++) {
for(int v=0; v<=divs2; v++) {
const gfxReal uf = (gfxReal)(u+0.25) / (gfxReal)(divs1+0.0);
const gfxReal vf = (gfxReal)(v+0.25) / (gfxReal)(divs2+0.0);
if(uf+vf>1.0) continue;
ntlVec3Gfx p = vertices[ triangles[i].getPoints()[0] ] * (1.0-uf-vf)+
vertices[ triangles[i].getPoints()[1] ]*uf +
vertices[ triangles[i].getPoints()[2] ]*vf;
ntlVec3Gfx n = normals[ triangles[i].getPoints()[0] ] * (1.0-uf-vf)+
normals[ triangles[i].getPoints()[1] ]*uf +
normals[ triangles[i].getPoints()[2] ]*vf;
normalize(n);
//if(mGeoInitType==FGI_MBNDINFLOW) {
// discard inflow backsides
if(discardInflowBack) { //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) {
if(dot(mInitialVelocity,n)<0.0) continue;
}
mMovPoints.push_back(p);
mMovNormals.push_back(n);
}
}
}
}
// duplicate insides
size_t mpsize = mMovPoints.size();
for(size_t i=0; i<mpsize; i++) {
//normalize(normals[i]);
//errMsg("TTAT"," moved:"<<(mMovPoints[i] - mMovPoints[i]*featureSize)<<" org"<<mMovPoints[i]<<" norm"<<mMovPoints[i]<<" fs"<<featureSize);
mMovPoints.push_back(mMovPoints[i] - mMovNormals[i]*0.5*featureSize);
mMovNormals.push_back(mMovNormals[i]);
}
// find max point
mMaxMovPnt = 0;
gfxReal dist = normNoSqrt(mMovPoints[0]);
for(size_t i=0; i<mpsize; i++) {
if(normNoSqrt(mMovPoints[i])>dist) {
mMaxMovPnt = i;
dist = normNoSqrt(mMovPoints[0]);
}
}
if( (mcTrans.accessValues().size()>1) // VALIDATE
|| (mcRot.accessValues().size()>1)
|| (mcScale.accessValues().size()>1)
) {
// also do trafo...
} else {
mCachedMovPoints = mMovPoints;
mCachedMovNormals = mMovNormals;
applyTransformation(0., &mCachedMovPoints, &mCachedMovNormals, 0, mCachedMovPoints.size(), true);
mHaveCachedMov = true;
debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" cached points ", 7);
}
mMovPntsInited = featureSize;
debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" inited v:"<<vertices.size()<<"->"<<mMovPoints.size() , 5);
}
/*! Prepare points for moving objects */
void ntlGeometryObject::getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms) {
if(mHaveCachedMov) {
ret = mCachedMovPoints;
if(norms) { *norms = mCachedMovNormals; }
errMsg ("ntlGeometryObject::getMovingPoints","Object "<<getName()<<" used cached points ");
return;
}
ret = mMovPoints;
if(norms) { *norms = mMovNormals; }
}
/*! Calculate max. velocity on object from t1 to t2 */
ntlVec3Gfx ntlGeometryObject::calculateMaxVel(double t1, double t2) {
ntlVec3Gfx vel(0.);
if(mMaxMovPnt<0) return vel;
vector<ntlVec3Gfx> verts1,verts2;
verts1.push_back(mMovPoints[mMaxMovPnt]);
verts2 = verts1;
applyTransformation(t1,&verts1,NULL, 0,verts1.size(), true);
applyTransformation(t2,&verts2,NULL, 0,verts2.size(), true);
vel = (verts2[0]-verts1[0]); // /(t2-t1);
errMsg("ntlGeometryObject::calculateMaxVel","t1="<<t1<<" t2="<<t2<<" p1="<<verts1[0]<<" p2="<<verts2[0]<<" v="<<vel);
return vel;
}
/*! get translation at time t*/
ntlVec3Gfx ntlGeometryObject::getTranslation(double t) {
ntlVec3Gfx pos = mcTrans.get(t);
return pos;
}
/*! get active flag time t*/
float ntlGeometryObject::getGeoActive(double t) {
//float act = mcGeoActive.getConstant(t);
float act = mcGeoActive.get(t); // if <= 0.0 -> off
return act;
}
void ntlGeometryObject::setInitialVelocity(ntlVec3Gfx set) {
mInitialVelocity=set;
mcInitialVelocity = AnimChannel<ntlVec3Gfx>(set);
}
ntlVec3Gfx ntlGeometryObject::getInitialVelocity(double t) {
ntlVec3Gfx v = mcInitialVelocity.get(t); //return mInitialVelocity;
if(!mLocalCoordInivel) return v;
ntlVec3Gfx rot = mcRot.get(t);
ntlMat4Gfx rotMat;
rotMat.initRotationXYZ(rot[0],rot[1],rot[2]);
v = rotMat * v;
return v;
}

View File

@@ -7,13 +7,14 @@
* all other geometry objects are derived from this one
*
*****************************************************************************/
#ifndef NTL_GEOMETRYOBJECT_HH
#ifndef NTL_GEOMETRYOBJECT_H
#define NTL_GEOMETRYOBJECT_H
#include "ntl_geometryclass.h"
#include "ntl_material.h"
#include "ntl_triangle.h"
class ntlRay;
#include "ntl_lighting.h"
#include "ntl_ray.h"
class ntlRenderGlobals;
class ntlTriangle;
class ntlGeometryObject : public ntlGeometryClass
@@ -28,13 +29,16 @@ class ntlGeometryObject : public ntlGeometryClass
//! Return type id
virtual int getTypeId() { return GEOCLASSTID_OBJECT; }
/*! Init attributes etc. of this object */
virtual void initialize(ntlRenderGlobals *glob);
/*! Get the triangles from this object */
virtual void getTriangles( vector<ntlTriangle> *triangles,
vector<ntlVec3Gfx> *vertices,
vector<ntlVec3Gfx> *normals, int objectId ) = 0;
/*! Init attributes etc. of this object */
virtual void initialize(ntlRenderGlobals *glob);
/*! notify object that dump is in progress (e.g. for particles) */
virtual void notifyOfDump(int frameNr,char *frameNrStr,string outfilename);
/*! Search the material for this object from the material list */
void searchMaterial(vector<ntlMaterial *> *mat);
@@ -68,20 +72,64 @@ class ntlGeometryObject : public ntlGeometryClass
/*! Returns the geo init typ */
inline int getGeoInitType() const { return mGeoInitType; }
/*! Set/get the cast initial veocity attribute */
inline void setInitialVelocity(ntlVec3Gfx set) { mInitialVelocity=set; }
inline ntlVec3Gfx getInitialVelocity() const { return mInitialVelocity; }
/*! Set/get the intersect init flag */
inline bool getGeoInitIntersect() const { return mGeoInitIntersect; }
inline void setGeoInitIntersect(bool set) { mGeoInitIntersect=set; }
/*! Set/get the part slip value*/
inline bool getGeoPartSlipValue() const { return mGeoPartSlipValue; }
inline float getGeoPartSlipValue() const { return mGeoPartSlipValue; }
inline void setGeoPartSlipValue(float set) { mGeoPartSlipValue=set; }
/*! Set/get the part slip value*/
inline bool getOnlyThinInit() const { return mOnlyThinInit; }
inline void setOnlyThinInit(float set) { mOnlyThinInit=set; }
/*! Set/get the cast initial veocity attribute */
void setInitialVelocity(ntlVec3Gfx set);
ntlVec3Gfx getInitialVelocity(double t);
/*! Set/get the local inivel coords flag */
inline bool getLocalCoordInivel() const { return mLocalCoordInivel; }
inline void setLocalCoordInivel(bool set) { mLocalCoordInivel=set; }
/*! Init channels from float arrays (for elbeem API) */
void initChannels(
int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale,
int nAct, float *act, int nIvel, float *ivel
);
/*! is the object animated? */
inline bool getIsAnimated() const { return mIsAnimated; }
/*! apply object translation at time t*/
void applyTransformation(double t, vector<ntlVec3Gfx> *verts, vector<ntlVec3Gfx> *norms, int vstart, int vend, int forceTrafo);
/*! Prepare points for moving objects */
void initMovingPoints(gfxReal featureSize);
/*! Prepare points for moving objects (copy into ret) */
void getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms = NULL);
/*! Calculate max. velocity on object from t1 to t2 */
ntlVec3Gfx calculateMaxVel(double t1, double t2);
/*! get translation at time t*/
ntlVec3Gfx getTranslation(double t);
/*! get active flag time t*/
float getGeoActive(double t);
/*! add triangle to scene and init flags */
// helper function for getTriangles
void sceneAddTriangle(
ntlVec3Gfx p1,ntlVec3Gfx p2,ntlVec3Gfx p3,
ntlVec3Gfx pn1,ntlVec3Gfx pn2,ntlVec3Gfx pn3,
ntlVec3Gfx trin, bool smooth,
vector<ntlTriangle> *triangles,
vector<ntlVec3Gfx> *vertices,
vector<ntlVec3Gfx> *vertNormals);
protected:
/* initialized for scene? */
bool mIsInitialized;
/*! Point to a property object describing the surface of this object */
ntlMaterial *mpMaterial;
@@ -100,15 +148,41 @@ class ntlGeometryObject : public ntlGeometryClass
int mGeoInitType;
/*! initial velocity for fluid objects */
ntlVec3Gfx mInitialVelocity;
AnimChannel<ntlVec3Gfx> mcInitialVelocity;
/*! use object local inflow? */
bool mLocalCoordInivel;
/*! perform more accurate intersecting geo init for this object? */
bool mGeoInitIntersect;
/*! part slip bc value */
float mGeoPartSlipValue;
/*! only init as thin object, dont fill? */
bool mOnlyThinInit;
/*! initial offset for rot/scale */
ntlVec3Gfx mInitialPos;
/*! animated channels for postition, rotation and scale */
AnimChannel<ntlVec3Gfx> mcTrans, mcRot, mcScale;
/*! easy check for animation */
bool mIsAnimated;
/*! moving point/normal storage */
vector<ntlVec3Gfx> mMovPoints;
vector<ntlVec3Gfx> mMovNormals;
/*! cached points for non moving objects/timeslots */
bool mHaveCachedMov;
vector<ntlVec3Gfx> mCachedMovPoints;
vector<ntlVec3Gfx> mCachedMovNormals;
/*! inited? */
float mMovPntsInited;
/*! point with max. distance from center */
int mMaxMovPnt;
/*! animated channels for in/outflow on/off */
AnimChannel<double> mcGeoActive;
public:
};
#define NTL_GEOMETRYOBJECT_HH
#endif

View File

@@ -39,6 +39,9 @@ class ntlGeometryShader :
/*! Get end iterator for all objects */
virtual vector<ntlGeometryObject *>::iterator getObjectsEnd() { return mObjects.end(); }
/*! notify object that dump is in progress (e.g. for field dump) */
virtual void notifyShaderOfDump(int frameNr,char *frameNrStr,string outfilename) = 0;
protected:
//! vector for the objects

View File

@@ -8,10 +8,9 @@
*****************************************************************************/
#include "ntl_lightobject.h"
#include "ntl_lighting.h"
#include "ntl_ray.h"
#include "ntl_scene.h"
#include "ntl_renderglobals.h"
#include "ntl_world.h"
/******************************************************************************
@@ -126,7 +125,7 @@ ntlColor ntlLightObject::illuminatePoint(ntlRay &reflectedRay, ntlGeometryObject
ntlTriangle *tri;
ntlVec3Gfx triNormal;
gfxReal trit;
mpGlob->getScene()->intersectScene(rayOfLight, trit, triNormal, tri, TRI_CASTSHADOWS);
mpGlob->getRenderScene()->intersectScene(rayOfLight, trit, triNormal, tri, TRI_CASTSHADOWS);
if(( trit>0 )&&( trit<lightDirNorm )) visibility = 0.0;
if(mpGlob->getDebugOut() > 5) errorOut("Omni lighting with "<<visibility );
}
@@ -142,3 +141,42 @@ ntlColor ntlLightObject::illuminatePoint(ntlRay &reflectedRay, ntlGeometryObject
}
/******************************************************************************
* Default constructor
*****************************************************************************/
ntlMaterial::ntlMaterial( void ) :
mName( "default" ),
mDiffuseRefl(0.5,0.5,0.5), mAmbientRefl(0.0,0.0,0.0),
mSpecular(0.0), mSpecExponent(0.0), mMirror(0.0),
mTransparence(0.0), mRefracIndex(0.0), mTransAdditive(0.0), mTransAttCol(0.0),
mFresnel( 0 )
//mNtfId(0), mNtfFluid(0), mNtfSolid(0)
{
// just do default init...
}
/******************************************************************************
* Init constructor
*****************************************************************************/
ntlMaterial::ntlMaterial( string name,
const ntlColor& Ref, const ntlColor& Amb,
gfxReal Spec, gfxReal SpecEx, gfxReal Mirr,
gfxReal Trans, gfxReal Refrac, gfxReal TAdd,
const ntlColor& Att, int fres)
{
mName = name;
mDiffuseRefl = Ref;
mAmbientRefl = Amb;
mSpecular = Spec;
mSpecExponent = SpecEx;
mMirror = Mirr;
mTransparence = Trans;
mRefracIndex = Refrac;
mTransAdditive = TAdd;
mTransAttCol = Att;
mFresnel = fres;
}

View File

@@ -3,15 +3,89 @@
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* a geometry object
* all other geometry objects are derived from this one
* a light object
* default omni light implementation
*
*****************************************************************************/
#ifndef NTL_MATERIAL_HH
#define NTL_MATERIAL_HH
#ifndef NTL_LIGHTING_H
#define NTL_LIGHTING_H
#include "ntl_vector3dim.h"
class ntlMaterial;
class ntlRay;
class ntlRenderGlobals;
class ntlGeometryObject;
/* shadow map directions */
#define LSM_RIGHT 0
#define LSM_LEFT 1
#define LSM_UP 2
#define LSM_DOWN 3
#define LSM_FRONT 4
#define LSM_BACK 5
/*! Basic object for lights, all other light are derived from this one */
class ntlLightObject
{
public:
/* CONSTRUCTORS */
/*! Default constructor */
ntlLightObject(ntlRenderGlobals *glob);
/*! Constructor with parameters */
ntlLightObject(ntlRenderGlobals *glob, const ntlColor& col);
/*! Destructor */
virtual ~ntlLightObject();
/*! prepare light for rendering (for example shadow maps) */
virtual void prepare( bool );
/*! do the illumination... */
virtual ntlColor illuminatePoint(ntlRay &reflectedRay,
ntlGeometryObject *closest,
ntlColor &highlight);
/*! shade the point */
const ntlColor
getShadedColor(const ntlRay &reflectedray, ntlVec3Gfx lightDir,
ntlMaterial *surf, ntlColor &highlight) const;
/* access methods */
/*! Access the active flag */
inline void setActive(bool set) { mActive = set; }
inline bool getActive() const { return mActive; }
/*! Access the shadow flag */
inline void setCastShadows(bool set) { mCastShadows = set; }
inline bool getCastShadows() const { return mCastShadows; }
/*! Access the light color */
inline void setColor(ntlColor set) { mcColor = set; }
inline ntlColor getColor() const { return mcColor; }
/*! Access the omni light position */
void setPosition(ntlVec3Gfx set) { mvPosition = set; }
ntlVec3Gfx getPosition() const { return mvPosition; }
protected:
/*! render globals */
ntlRenderGlobals *mpGlob;
/*! is this light acitve? */
bool mActive;
/*! does it cast shadows? */
bool mCastShadows;
/*! color of this light */
ntlColor mcColor;
/*! light position */
ntlVec3Gfx mvPosition;
private:
};
//! Properties of an geo object, describing the reflection properties of the surface
@@ -20,12 +94,12 @@ class ntlMaterial
public:
// CONSTRUCTORS
//! Default constructor
inline ntlMaterial( void );
ntlMaterial( void );
//! Constructor with parameters
/*! Sets reflectance, ambient reflection, specular intensity
* specular exponent, mirror intensity
* transparency, refraction index */
inline ntlMaterial( string name,
ntlMaterial( string name,
const ntlColor& Ref, const ntlColor& Amb,
gfxReal Spec, gfxReal Exp, gfxReal Mirror,
gfxReal Trans, gfxReal Refrac, gfxReal TAdd,
@@ -121,47 +195,6 @@ public:
};
/******************************************************************************
* Default constructor
*****************************************************************************/
inline ntlMaterial::ntlMaterial( void ) :
mName( "default" ),
mDiffuseRefl(0.5,0.5,0.5), mAmbientRefl(0.0,0.0,0.0),
mSpecular(0.0), mSpecExponent(0.0), mMirror(0.0),
mTransparence(0.0), mRefracIndex(0.0), mTransAdditive(0.0), mTransAttCol(0.0),
mFresnel( 0 )
//mNtfId(0), mNtfFluid(0), mNtfSolid(0)
{
// just do default init...
}
/******************************************************************************
* Init constructor
*****************************************************************************/
inline
ntlMaterial::ntlMaterial( string name,
const ntlColor& Ref, const ntlColor& Amb,
gfxReal Spec, gfxReal SpecEx, gfxReal Mirr,
gfxReal Trans, gfxReal Refrac, gfxReal TAdd,
const ntlColor& Att, int fres)
{
mName = name;
mDiffuseRefl = Ref;
mAmbientRefl = Amb;
mSpecular = Spec;
mSpecExponent = SpecEx;
mMirror = Mirr;
mTransparence = Trans;
mRefracIndex = Refrac;
mTransAdditive = TAdd;
mTransAttCol = Att;
mFresnel = fres;
}
/******************************************************************************
* Macro to define the default surface properties for a newly created object
*****************************************************************************/
@@ -201,3 +234,5 @@ ntlMaterial::calculateFresnel(const ntlVec3Gfx &dir, const ntlVec3Gfx &normal, g
#endif

View File

@@ -1,91 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* a light object
* default omni light implementation
*
*****************************************************************************/
#ifndef NTL_LIGHTOBJECT_HH
#define NTL_LIGHTOBJECT_HH
#include "ntl_vector3dim.h"
#include "ntl_material.h"
class ntlRay;
class ntlRenderGlobals;
class ntlGeometryObject;
/* shadow map directions */
#define LSM_RIGHT 0
#define LSM_LEFT 1
#define LSM_UP 2
#define LSM_DOWN 3
#define LSM_FRONT 4
#define LSM_BACK 5
/*! Basic object for lights, all other light are derived from this one */
class ntlLightObject
{
public:
/* CONSTRUCTORS */
/*! Default constructor */
ntlLightObject(ntlRenderGlobals *glob);
/*! Constructor with parameters */
ntlLightObject(ntlRenderGlobals *glob, const ntlColor& col);
/*! Destructor */
virtual ~ntlLightObject();
/*! prepare light for rendering (for example shadow maps) */
virtual void prepare( bool );
/*! do the illumination... */
virtual ntlColor illuminatePoint(ntlRay &reflectedRay,
ntlGeometryObject *closest,
ntlColor &highlight);
/*! shade the point */
const ntlColor
getShadedColor(const ntlRay &reflectedray, ntlVec3Gfx lightDir,
ntlMaterial *surf, ntlColor &highlight) const;
/* access methods */
/*! Access the active flag */
inline void setActive(bool set) { mActive = set; }
inline bool getActive() const { return mActive; }
/*! Access the shadow flag */
inline void setCastShadows(bool set) { mCastShadows = set; }
inline bool getCastShadows() const { return mCastShadows; }
/*! Access the light color */
inline void setColor(ntlColor set) { mcColor = set; }
inline ntlColor getColor() const { return mcColor; }
/*! Access the omni light position */
void setPosition(ntlVec3Gfx set) { mvPosition = set; }
ntlVec3Gfx getPosition() const { return mvPosition; }
protected:
/*! render globals */
ntlRenderGlobals *mpGlob;
/*! is this light acitve? */
bool mActive;
/*! does it cast shadows? */
bool mCastShadows;
/*! color of this light */
ntlColor mcColor;
/*! light position */
ntlVec3Gfx mvPosition;
private:
};
#endif

View File

@@ -77,9 +77,12 @@ public:
inline void initRotationX(Scalar rot);
inline void initRotationY(Scalar rot);
inline void initRotationZ(Scalar rot);
inline void initRotationXYZ(Scalar rotx,Scalar roty, Scalar rotz);
//! init scaling matrix
inline void initScaling(Scalar scale);
inline void initScaling(Scalar x, Scalar y, Scalar z);
//! from 16 value array (init id if all 0)
inline void initArrayCheck(Scalar *array);
//! public to avoid [][] operators
Scalar value[4][4]; //< Storage of vector values
@@ -593,8 +596,8 @@ template<class Scalar>
inline void
ntlMatrix4x4<Scalar>::initRotationX(Scalar rot)
{
double drot = (double)rot;
while(drot < 0.0) drot += (M_PI*2.0);
double drot = (double)(rot/360.0*2.0*M_PI);
//? while(drot < 0.0) drot += (M_PI*2.0);
this->initId();
value[1][1] = (Scalar) cos(drot);
@@ -606,8 +609,8 @@ template<class Scalar>
inline void
ntlMatrix4x4<Scalar>::initRotationY(Scalar rot)
{
double drot = (double)rot;
while(drot < 0.0) drot += (M_PI*2.0);
double drot = (double)(rot/360.0*2.0*M_PI);
//? while(drot < 0.0) drot += (M_PI*2.0);
this->initId();
value[0][0] = (Scalar) cos(drot);
@@ -619,8 +622,8 @@ template<class Scalar>
inline void
ntlMatrix4x4<Scalar>::initRotationZ(Scalar rot)
{
double drot = (double)rot;
while(drot < 0.0) drot += (M_PI*2.0);
double drot = (double)(rot/360.0*2.0*M_PI);
//? while(drot < 0.0) drot += (M_PI*2.0);
this->initId();
value[0][0] = (Scalar) cos(drot);
@@ -628,6 +631,32 @@ ntlMatrix4x4<Scalar>::initRotationZ(Scalar rot)
value[1][0] = (Scalar)(-sin(drot));
value[1][1] = (Scalar) cos(drot);
}
template<class Scalar>
inline void
ntlMatrix4x4<Scalar>::initRotationXYZ( Scalar rotx, Scalar roty, Scalar rotz)
{
ntlMatrix4x4<Scalar> val;
ntlMatrix4x4<Scalar> rot;
this->initId();
// org
/*rot.initRotationX(rotx);
(*this) *= rot;
rot.initRotationY(roty);
(*this) *= rot;
rot.initRotationZ(rotz);
(*this) *= rot;
// org */
// blender
rot.initRotationZ(rotz);
(*this) *= rot;
rot.initRotationY(roty);
(*this) *= rot;
rot.initRotationX(rotx);
(*this) *= rot;
// blender */
}
//! init scaling matrix
template<class Scalar>
@@ -651,6 +680,20 @@ ntlMatrix4x4<Scalar>::initScaling(Scalar x, Scalar y, Scalar z)
}
//! from 16 value array (init id if all 0)
template<class Scalar>
inline void
ntlMatrix4x4<Scalar>::initArrayCheck(Scalar *array)
{
bool allZero = true;
for(int i=0; i<4; i++) {
for(int j=0; j<4; j++) {
value[i][j] = array[i*4+j];
if(array[i*4+j]!=0.0) allZero=false;
}
}
if(allZero) this->initId();
}
#define NTL_MATRICES_H

View File

@@ -8,8 +8,11 @@
*****************************************************************************/
#include "utilities.h"
#include "ntl_ray.h"
#include "ntl_scene.h"
#include "ntl_world.h"
#include "ntl_geometryobject.h"
#include "ntl_geometryshader.h"
/* Minimum value for refl/refr to be traced */
@@ -116,7 +119,7 @@ ntlRay::~ntlRay()
#define MIDDLE 2
//! intersect ray with AABB
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
void ntlRay::intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &retnormal,ntlVec3Gfx &retcoord) const
{
char inside = true; /* inside box? */
@@ -288,7 +291,7 @@ void ntlRay::intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, n
retnormal = normal;
retcoord = coord;
}
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
//! intersect ray with AABB
void ntlRay::intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const
@@ -441,7 +444,7 @@ void ntlRay::intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &
*****************************************************************************/
const ntlColor ntlRay::shade() //const
{
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
ntlGeometryObject *closest = NULL;
gfxReal minT = GFX_REAL_MAX;
vector<ntlLightObject*> *lightlist = mpGlob->getLightList();
@@ -457,9 +460,9 @@ const ntlColor ntlRay::shade() //const
/* find closes object that intersects */
ntlTriangle *tri = NULL;
ntlVec3Gfx normal;
mpGlob->getScene()->intersectScene(*this, minT, normal, tri, 0);
mpGlob->getRenderScene()->intersectScene(*this, minT, normal, tri, 0);
if(minT>0) {
closest = mpGlob->getScene()->getObject( tri->getObjectId() );
closest = mpGlob->getRenderScene()->getObject( tri->getObjectId() );
}
/* object hit... */
@@ -481,7 +484,7 @@ const ntlColor ntlRay::shade() //const
ntlMaterial *clossurf = closest->getMaterial();
/*if(mpGlob->getDebugOut() > 5) {
errorOut("Ray hit: at "<<intersectionPosition<<" n:"<<normal<<" dn:"<<valDN<<" ins:"<<intersectionInside<<" cl:"<<((unsigned int)closest) );
errorOut(" t1:"<<mpGlob->getScene()->getVertex(tri->getPoints()[0])<<" t2:"<<mpGlob->getScene()->getVertex(tri->getPoints()[1])<<" t3:"<<mpGlob->getScene()->getVertex(tri->getPoints()[2]) );
errorOut(" t1:"<<mpGlob->getRenderScene()->getVertex(tri->getPoints()[0])<<" t2:"<<mpGlob->getRenderScene()->getVertex(tri->getPoints()[1])<<" t3:"<<mpGlob->getScene()->getVertex(tri->getPoints()[2]) );
errorOut(" trin:"<<tri->getNormal() );
} // debug */
@@ -559,9 +562,9 @@ const ntlColor ntlRay::shade() //const
refractionPosition2 -= (triangleNormal*getVecEpsilon() );
ntlRay reflectedRay2 = ntlRay(refractionPosition2, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob);
mpGlob->getScene()->intersectScene(reflectedRay2, minT2, normal2, tri2, 0);
mpGlob->getRenderScene()->intersectScene(reflectedRay2, minT2, normal2, tri2, 0);
if(minT2>0) {
closest2 = mpGlob->getScene()->getObject( tri2->getObjectId() );
closest2 = mpGlob->getRenderScene()->getObject( tri2->getObjectId() );
}
/* object hit... */
@@ -649,13 +652,254 @@ const ntlColor ntlRay::shade() //const
return ntlColor(currentColor);
}
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
/* no object hit -> ray goes to infinity */
return mpGlob->getBackgroundCol();
}
/******************************************************************************
******************************************************************************
******************************************************************************
* scene implementation
******************************************************************************
******************************************************************************
*****************************************************************************/
/******************************************************************************
* Constructor
*****************************************************************************/
ntlScene::ntlScene( ntlRenderGlobals *glob, bool del ) :
mpGlob( glob ), mSceneDel(del),
mpTree( NULL ),
mDisplayListId( -1 ),
mSceneBuilt( false ), mFirstInitDone( false )
{
}
/******************************************************************************
* Destructor
*****************************************************************************/
ntlScene::~ntlScene()
{
if(mpTree != NULL) delete mpTree;
// cleanup lists, only if this is the rendering cleanup scene
if(mSceneDel) {
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
//errMsg("ntlScene::~ntlScene","Deleting obj "<<(*iter)->getName() );
delete (*iter);
}
for (vector<ntlLightObject*>::iterator iter = mpGlob->getLightList()->begin();
iter != mpGlob->getLightList()->end(); iter++) {
delete (*iter);
}
for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin();
iter != mpGlob->getMaterials()->end(); iter++) {
delete (*iter);
}
}
errMsg("ntlScene::~ntlScene","Deleted, ObjFree:"<<mSceneDel);
}
/******************************************************************************
* Build the scene arrays (obj, tris etc.)
*****************************************************************************/
void ntlScene::buildScene(double time,bool firstInit)
{
const bool buildInfo=true;
if(firstInit) {
mObjects.clear();
/* init geometry array, first all standard objects */
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
bool geoinit = false;
int tid = (*iter)->getTypeId();
if(tid & GEOCLASSTID_OBJECT) {
ntlGeometryObject *geoobj = (ntlGeometryObject*)(*iter);
geoinit = true;
mObjects.push_back( geoobj );
if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName()<<" Id:"<<geoobj->getObjectId(), 5 );
}
//if(geoshad) {
if(tid & GEOCLASSTID_SHADER) {
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter);
geoinit = true;
if(!mFirstInitDone) {
// only on first init
geoshad->initializeShader();
}
for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
siter != geoshad->getObjectsEnd();
siter++) {
if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName()<<" Id:"<<(*siter)->getObjectId(), 5 );
mObjects.push_back( (*siter) );
}
}
if(!geoinit) {
errFatal("ntlScene::BuildScene","Invalid geometry class!", SIMWORLD_INITERROR);
return;
}
}
}
// collect triangles
mTriangles.clear();
mVertices.clear();
mVertNormals.clear();
/* for test mode deactivate transparencies etc. */
if( mpGlob->getTestMode() ) {
debugOut("ntlScene::buildScene : Test Mode activated!", 2);
// assign random colors to dark materials
int matCounter = 0;
ntlColor stdCols[] = { ntlColor(0,0,1.0), ntlColor(0,1.0,0), ntlColor(1.0,0.7,0) , ntlColor(0.7,0,0.6) };
int stdColNum = 4;
for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin();
iter != mpGlob->getMaterials()->end(); iter++) {
(*iter)->setTransparence(0.0);
(*iter)->setMirror(0.0);
(*iter)->setFresnel(false);
// too dark?
if( norm((*iter)->getDiffuseRefl()) <0.01) {
(*iter)->setDiffuseRefl( stdCols[matCounter] );
matCounter ++;
matCounter = matCounter%stdColNum;
}
}
// restrict output file size to 400
float downscale = 1.0;
if(mpGlob->getResX() > 400){ downscale = 400.0/(float)mpGlob->getResX(); }
if(mpGlob->getResY() > 400){
float downscale2 = 400.0/(float)mpGlob->getResY();
if(downscale2<downscale) downscale=downscale2;
}
mpGlob->setResX( (int)(mpGlob->getResX() * downscale) );
mpGlob->setResY( (int)(mpGlob->getResY() * downscale) );
}
/* collect triangles from objects */
int idCnt = 0; // give IDs to objects
bool debugTriCollect = false;
if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Start...",5);
for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin();
iter != mObjects.end();
iter++) {
/* only add visible objects */
if(firstInit) {
if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Collect init of "<<(*iter)->getName()<<" idCnt:"<<idCnt, 4 );
(*iter)->initialize( mpGlob ); }
if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Collecting tris from "<<(*iter)->getName(), 4 );
int vstart = mVertNormals.size();
(*iter)->setObjectId(idCnt);
(*iter)->getTriangles(&mTriangles, &mVertices, &mVertNormals, idCnt);
(*iter)->applyTransformation(time, &mVertices, &mVertNormals, vstart, mVertices.size(), false );
if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Done with "<<(*iter)->getName()<<" totTris:"<<mTriangles.size()<<" totVerts:"<<mVertices.size()<<" totNorms:"<<mVertNormals.size(), 4 );
idCnt ++;
}
if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"End",5);
/* calculate triangle normals, and initialize flags */
for (vector<ntlTriangle>::iterator iter = mTriangles.begin();
iter != mTriangles.end();
iter++) {
// calculate normal from triangle points
ntlVec3Gfx normal =
cross( (ntlVec3Gfx)( (mVertices[(*iter).getPoints()[2]] - mVertices[(*iter).getPoints()[0]]) *-1.0), // BLITZ minus sign right??
(ntlVec3Gfx)(mVertices[(*iter).getPoints()[1]] - mVertices[(*iter).getPoints()[0]]) );
normalize(normal);
(*iter).setNormal( normal );
}
// scene geometry built
mSceneBuilt = true;
// init shaders that require complete geometry
if(!mFirstInitDone) {
// only on first init
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) {
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter);
geoshad->postGeoConstrInit( mpGlob );
}
}
mFirstInitDone = true;
}
// check unused attributes (for classes and objects!)
for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); iter != mObjects.end(); iter++) {
if((*iter)->getAttributeList()->checkUnusedParams()) {
(*iter)->getAttributeList()->print(); // DEBUG
errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR );
return;
}
}
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); iter != mGeos.end(); iter++) {
if((*iter)->getAttributeList()->checkUnusedParams()) {
(*iter)->getAttributeList()->print(); // DEBUG
errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR );
return;
}
}
}
/******************************************************************************
* Prepare the scene triangles and maps for raytracing
*****************************************************************************/
void ntlScene::prepareScene(double time)
{
/* init triangles... */
buildScene(time, false);
// what for currently not used ???
if(mpTree != NULL) delete mpTree;
mpTree = new ntlTree( mpGlob->getTreeMaxDepth(), mpGlob->getTreeMaxTriangles(),
this, TRI_GEOMETRY );
//debMsgStd("ntlScene::prepareScene",DM_MSG,"Stats - tris:"<< (int)mTriangles.size()<<" verts:"<<mVertices.size()<<" vnorms:"<<mVertNormals.size(), 5 );
}
/******************************************************************************
* Do some memory cleaning, when frame is finished
*****************************************************************************/
void ntlScene::cleanupScene( void )
{
mTriangles.clear();
mVertices.clear();
mVertNormals.clear();
if(mpTree != NULL) delete mpTree;
mpTree = NULL;
}
/******************************************************************************
* Intersect a ray with the scene triangles
*****************************************************************************/
void ntlScene::intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri,int flags) const
{
distance = -1.0;
mpGlob->setCounterSceneInter( mpGlob->getCounterSceneInter()+1 );
mpTree->intersect(r, distance, normal, tri, flags, false);
}

View File

@@ -6,14 +6,20 @@
* ray class
*
*****************************************************************************/
#ifndef NTL_RAY_HH
#define NTL_RAY_HH
#ifndef NTL_RAY_H
#define NTL_RAY_H
#include <sstream>
#include "ntl_vector3dim.h"
#include "ntl_lightobject.h"
#include "ntl_lighting.h"
#include "ntl_geometryobject.h"
#include "ntl_renderglobals.h"
#include "ntl_bsptree.h"
class ntlTriangle;
class ntlRay;
class ntlTree;
class ntlScene;
class ntlRenderGlobals;
//! store data for an intersection of a ray and a triangle
// NOT YET USED
@@ -131,12 +137,279 @@ private:
};
/******************************************************************************
*
* a single triangle
*
*****************************************************************************/
// triangle intersection code in bsptree.cpp
// intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v);
// ...
/*! Triangle flag defines */
#define TRI_GEOMETRY (1<<0)
#define TRI_CASTSHADOWS (1<<1)
#define TRI_MAKECAUSTICS (1<<2)
#define TRI_NOCAUSTICS (1<<3)
class ntlTriangle
{
public:
/* CONSTRUCTORS */
/*! Default constructor */
inline ntlTriangle( void );
/*! Constructor with parameters */
inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags);
/*! Copy - Constructor */
inline ntlTriangle(const ntlTriangle &tri);
/*! Destructor */
inline ~ntlTriangle() {}
/* Access methods */
/*! Acces to points of triangle */
inline int *getPoints( void ) { return mPoints; }
/*! Acces normal smoothing */
inline bool getSmoothNormals( void ) const { return mSmoothNormals; }
inline void setSmoothNormals( bool set){ mSmoothNormals = set; }
/*! Access object */
inline int getObjectId( void ) const { return mObjectId; }
inline void setObjectId( int set) { mObjectId = set; }
/*! Acces normal index */
inline ntlVec3Gfx getNormal( void ) const { return mNormal; }
inline void setNormal( ntlVec3Gfx set ) { mNormal = set; }
/*! Acces flags */
inline int getFlags( void ) const { return mFlags; }
inline void setFlags( int set ) { mFlags = set; }
/*! Access last intersection ray ID */
inline int getLastRay( void ) const { return mLastRay; }
inline void setLastRay( int set ) { mLastRay = set; }
/*! Acces bbox id */
inline int getBBoxId( void ) const { return mBBoxId; }
inline void setBBoxId( int set ) { mBBoxId = set; }
/*! Get average of the three points for this axis */
inline gfxReal getAverage( int axis ) const;
/*! operator < for sorting, uses global sorting axis */
inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs);
/*! operator > for sorting, uses global sorting axis */
inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs);
protected:
private:
/*! indices to the three points of the triangle */
int mPoints[3];
/*! bounding box id (for tree generation), -1 if invalid */
int mBBoxId;
/*! Should the normals of this triangle get smoothed? */
bool mSmoothNormals;
/*! Id of parent object */
int mObjectId;
/*! Index to normal (for not smooth triangles) */
//int mNormalIndex; ??
ntlVec3Gfx mNormal;
/*! Flags for object attributes cast shadows, make caustics etc. */
int mFlags;
/*! ID of last ray that an intersection was calculated for */
int mLastRay;
};
/******************************************************************************
* Default Constructor
*****************************************************************************/
ntlTriangle::ntlTriangle( void ) :
mBBoxId(-1),
mLastRay( 0 )
{
mPoints[0] = mPoints[1] = mPoints[2] = 0;
mSmoothNormals = 0;
mObjectId = 0;
mNormal = ntlVec3Gfx(0.0);
mFlags = 0;
}
/******************************************************************************
* Constructor
*****************************************************************************/
ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) :
mBBoxId(-1),
mLastRay( 0 )
{
mPoints[0] = p[0];
mPoints[1] = p[1];
mPoints[2] = p[2];
mSmoothNormals = smooth;
mObjectId = obj;
mNormal = norm;
mFlags = setflags;
}
/******************************************************************************
* Copy Constructor
*****************************************************************************/
ntlTriangle::ntlTriangle(const ntlTriangle &tri) :
mBBoxId(-1),
mLastRay( 0 )
{
mPoints[0] = tri.mPoints[0];
mPoints[1] = tri.mPoints[1];
mPoints[2] = tri.mPoints[2];
mSmoothNormals = tri.mSmoothNormals;
mObjectId = tri.mObjectId;
mNormal = tri.mNormal;
mFlags = tri.mFlags;
}
/******************************************************************************
* Triangle sorting functions
*****************************************************************************/
/* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */
/* Static global variable for sorting direction */
extern int globalSortingAxis;
/* Access to points array for sorting */
extern vector<ntlVec3Gfx> *globalSortingPoints;
gfxReal ntlTriangle::getAverage( int axis ) const
{
return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] +
(*globalSortingPoints)[ mPoints[1] ][axis] +
(*globalSortingPoints)[ mPoints[2] ][axis] )/3.0);
}
bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs)
{
return ( lhs.getAverage(globalSortingAxis) <
rhs.getAverage(globalSortingAxis) );
}
bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs)
{
return ( lhs.getAverage(globalSortingAxis) >
rhs.getAverage(globalSortingAxis) );
}
/******************************************************************************
*
* Scene object, that contains and manages all geometry objects
*
*****************************************************************************/
class ntlScene
{
public:
/* CONSTRUCTORS */
/*! Default constructor */
ntlScene( ntlRenderGlobals *glob, bool del=true );
/*! Default destructor */
~ntlScene();
/*! Add an object to the scene */
inline void addGeoClass(ntlGeometryClass *geo) {
mGeos.push_back( geo );
geo->setObjectId(mGeos.size());
}
/*! Acces a certain object */
inline ntlGeometryObject *getObject(int id) {
if(!mSceneBuilt) { errMsg("ntlScene::getObject","Scene not inited!"); return NULL; }
return mObjects[id]; }
/*! Acces object array */
inline vector<ntlGeometryObject*> *getObjects() {
if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); return NULL; }
return &mObjects; }
/*! Acces geo class array */
inline vector<ntlGeometryClass*> *getGeoClasses() {
if(!mSceneBuilt) { errMsg("ntlScene::getGeoClasses[]","Scene not inited!"); return NULL; }
return &mGeos; }
/*! draw scene with opengl */
//void draw();
/*! Build/first init the scene arrays */
void buildScene(double time, bool firstInit);
//! Prepare the scene triangles and maps for raytracing
void prepareScene(double time);
//! Do some memory cleaning, when frame is finished
void cleanupScene( void );
/*! Intersect a ray with the scene triangles */
void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const;
/*! return a vertex */
ntlVec3Gfx getVertex(int index) { return mVertices[index]; }
// for tree generation
/*! return pointer to vertices vector */
vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; }
/*! return pointer to vertices vector */
vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; }
/*! return pointer to vertices vector */
vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; }
private:
/*! Global settings */
ntlRenderGlobals *mpGlob;
/*! free objects? (only necessary for render scene, which contains all) */
bool mSceneDel;
/*! List of geometry classes */
vector<ntlGeometryClass *> mGeos;
/*! List of geometry objects */
vector<ntlGeometryObject *> mObjects;
/*! List of triangles */
vector<ntlTriangle> mTriangles;
/*! List of vertices */
vector<ntlVec3Gfx> mVertices;
/*! List of normals */
vector<ntlVec3Gfx> mVertNormals;
/*! List of triangle normals */
vector<ntlVec3Gfx> mTriangleNormals;
/*! Tree to store quickly intersect triangles */
ntlTree *mpTree;
/*! id of dislpay list for raytracer stuff */
int mDisplayListId;
/*! was the scene successfully built? only then getObject(i) requests are valid */
bool mSceneBuilt;
/*! shader/obj initializations are only done on first init */
bool mFirstInitDone;
};
#endif

View File

@@ -1,365 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* main renderer class
*
*****************************************************************************/
#ifndef NTL_RENDERGLOBALS_HH
#define NTL_RENDERGLOBALS_HH
#include "ntl_vector3dim.h"
#include "ntl_rndstream.h"
#include "ntl_geometryobject.h"
#include "ntl_material.h"
#include "ntl_lightobject.h"
class ntlScene;
class SimulationObject;
//! Display mode
#define DM_VIZ 0
#define DM_RAY 1
#define DM_LBM 2
//! Class that handles global rendering parameters
class ntlRenderGlobals
{
public:
//! Standard constructor
inline ntlRenderGlobals();
//! Destructor
~ntlRenderGlobals();
//! Returns the scene manager
inline ntlScene *getScene(void) { return mpScene; }
//! Set the scene manager
inline void setScene(ntlScene *set) { mpScene = set;}
//! Returns the object list
//inline vector<ntlGeometryObject*> *getObjectList(void) { return mpObjList; }
//! Set the object list
//inline void setObjectList(vector<ntlGeometryObject*> *set) { mpObjList = set;}
//! Returns the light object list
inline vector<ntlLightObject*> *getLightList(void) { return mpLightList; }
//! Set the light list
inline void setLightList(vector<ntlLightObject*> *set) { mpLightList = set;}
//! Returns the property object list
inline vector<ntlMaterial*> *getMaterials(void) { return mpMaterials; }
//! Set the property list
inline void setMaterials(vector<ntlMaterial*> *set) { mpMaterials = set;}
//! Returns the list of simulations
inline vector<SimulationObject*> *getSims(void) { return mpSims; }
//! Set the pointer to the list of simulations
inline void setSims(vector<SimulationObject*> *set) { mpSims = set;}
//! Set the x resolution
inline void setResX(unsigned int set) { mResX = set; }
//! Set the y resolution
inline void setResY(unsigned int set) { mResY = set; }
//! Set the anti-aliasing depth
inline void setAADepth(int set) { mAADepth = set; }
//! Set the max color value
inline void setMaxColVal(unsigned int set) { mMaxColVal = set; }
//! Set the maximum ray recursion
inline void setRayMaxDepth(unsigned int set) { mRayMaxDepth = set; }
//! Set the eye point
inline void setEye(ntlVec3Gfx set) { mvEye = set; }
//! Set the look at vector
inline void setLookat(ntlVec3Gfx set) { mvLookat = set; }
//! Set the up vector
inline void setUpVec(ntlVec3Gfx set) { mvUpvec = set; }
//! Set the image aspect
inline void setAspect(float set) { mAspect = set; }
//! Set the field of view
inline void setFovy(float set) { mFovy = set; }
//! Set the background color
inline void setBackgroundCol(ntlColor set) { mcBackgr = set; }
//! Set the ambient lighting color
inline void setAmbientLight(ntlColor set) { mcAmbientLight = set; }
//! Set the debug output var
inline void setDebugOut(int set) { mDebugOut = set; }
//! Set the animation start time
inline void setAniStart(int set) { mAniStart = set; }
//! Set the animation number of frames
inline void setAniFrames(int set) { mAniFrames = set; }
//! Set the animation
inline void setAniCount(int set) { mAniCount = set; }
//! Set the ray counter
inline void setCounterRays(int set) { mCounterRays = set; }
//! Set the ray shades counter
inline void setCounterShades(int set) { mCounterShades = set; }
//! Set the scenen intersection counter
inline void setCounterSceneInter(int set) { mCounterSceneInter = set; }
//! Set if existing frames should be skipped
inline void setFrameSkip(int set) { mFrameSkip = set; }
//! Set the outfilename
inline void setOutFilename(string set) { mOutFilename = set; }
//! get Maximum depth for BSP tree
inline void setTreeMaxDepth( int set ) { mTreeMaxDepth = set; }
//! get Maxmimum nr of triangles per BSP tree node
inline void setTreeMaxTriangles( int set ) { mTreeMaxTriangles = set; }
//! set the enable flag of the test sphere
inline void setTestSphereEnabled( bool set ) { mTestSphereEnabled = set; }
//! set the center of the test sphere
inline void setTestSphereCenter( ntlVec3Gfx set ) { mTestSphereCenter = set; }
//! set the radius of the test sphere
inline void setTestSphereRadius( gfxReal set ) { mTestSphereRadius = set; }
//! set the material name of the test sphere
inline void setTestSphereMaterialName( char* set ) { mTestSphereMaterialName = set; }
//! set debugging pixel coordinates
inline void setDebugPixel( int setx, int sety ) { mDebugPixelX = setx; mDebugPixelY = sety; }
//! set test mode flag
inline void setTestMode( bool set ) { mTestMode = set; }
//! set single frame mode flag
inline void setSingleFrameMode(bool set) {mSingleFrameMode = set; };
//! set single frame mode filename
inline void setSingleFrameFilename(string set) {mSingleFrameFilename = set; };
//! Return the x resolution
inline unsigned int getResX(void) { return mResX; }
//! Return the y resolution
inline unsigned int getResY(void) { return mResY; }
//! Return the anti-aliasing depth
inline int getAADepth(void) { return mAADepth; }
//! Return the max color value for ppm
inline unsigned int getMaxColVal(void) { return mMaxColVal; }
//! Return the maximum ray recursion
inline unsigned int getRayMaxDepth(void) { return mRayMaxDepth; }
//! Return the eye point
inline ntlVec3Gfx getEye(void) { return mvEye; }
//! Return the look at vector
inline ntlVec3Gfx getLookat(void) { return mvLookat; }
//! Return the up vector
inline ntlVec3Gfx getUpVec(void) { return mvUpvec; }
//! Return the image aspect
inline float getAspect(void) { return mAspect; }
//! Return the field of view
inline float getFovy(void) { return mFovy; }
//! Return the background color
inline ntlColor getBackgroundCol(void) { return mcBackgr; }
//! Return the ambient color
inline ntlColor getAmbientLight(void) { return mcAmbientLight; }
//! Return the debug mode setting
inline int getDebugOut(void) { return mDebugOut; }
//! Return the animation start time
inline int getAniStart(void) { return mAniStart; }
//! Return the animation frame number
inline int getAniFrames(void) { return mAniFrames; }
//! Return the animation counter
inline int getAniCount(void) { return mAniCount; }
//! Return the ray counter
inline int getCounterRays(void) { return mCounterRays; }
//! Return the ray shades counter
inline int getCounterShades(void) { return mCounterShades; }
//! Return the scene intersection counter
inline int getCounterSceneInter(void) { return mCounterSceneInter; }
//! Check if existing frames should be skipped
inline int getFrameSkip( void ) { return mFrameSkip; }
//! Return the outfilename
inline string getOutFilename(void) { return mOutFilename; }
//! get Maximum depth for BSP tree
inline int getTreeMaxDepth( void ) { return mTreeMaxDepth; }
//! get Maxmimum nr of triangles per BSP tree node
inline int getTreeMaxTriangles( void ) { return mTreeMaxTriangles; }
//! get open gl attribute list
inline AttributeList* getOpenGlAttributes( void ) { return mpOpenGlAttr; }
//! get blender output attribute list
inline AttributeList* getBlenderAttributes( void ) { return mpBlenderAttr; }
//! is the test sphere enabled?
inline bool getTestSphereEnabled( void ) { return mTestSphereEnabled; }
//! get the center of the test sphere
inline ntlVec3Gfx getTestSphereCenter( void ) { return mTestSphereCenter; }
//! get the radius of the test sphere
inline gfxReal getTestSphereRadius( void) { return mTestSphereRadius; }
//! get the materialname of the test sphere
inline char *getTestSphereMaterialName( void) { return mTestSphereMaterialName; }
//! get the debug pixel coordinate
inline int getDebugPixelX( void ) { return mDebugPixelX; }
//! get the debug pixel coordinate
inline int getDebugPixelY( void ) { return mDebugPixelY; }
//! get test mode flag
inline bool getTestMode( void ) { return mTestMode; }
//! set single frame mode flag
inline bool getSingleFrameMode() { return mSingleFrameMode; };
//! set single frame mode filename
inline string getSingleFrameFilename() { return mSingleFrameFilename; };
// random number functions
//! init random numbers for photon directions
inline void initRandomDirections( int seed ) { if(mpRndDirections) delete mpRndDirections; mpRndDirections = new ntlRandomStream( seed ); }
//! get the next random photon direction
inline ntlVec3Gfx getRandomDirection( void );
//! init random numbers for russian roulette
inline void initRandomRoulette( int seed ) { if(mpRndRoulette) delete mpRndRoulette; mpRndRoulette = new ntlRandomStream( seed ); }
//! get the next random number for russion roulette
inline gfxReal getRandomRoulette( void ) { return mpRndRoulette->getGfxReal(); }
protected:
private:
/*! Scene storage */
ntlScene *mpScene;
//! List of geometry objects
//vector<ntlGeometryObject*> *mpObjList;
//! List of light objects
vector<ntlLightObject*> *mpLightList;
//! List of surface properties
vector<ntlMaterial*> *mpMaterials;
/*! storage for simulations */
vector<SimulationObject*> *mpSims;
//! resolution of the picture
unsigned int mResX, mResY;
//! Anti-Aliasing depth
int mAADepth;
//! max color value for ppm
unsigned int mMaxColVal;
/* Maximal ray recursion depth */
int mRayMaxDepth;
//! The eye point
ntlVec3Gfx mvEye;
//! The look at point
ntlVec3Gfx mvLookat;
//! The up vector
ntlVec3Gfx mvUpvec;
//! The image aspect = Xres/Yres
float mAspect;
//! The horizontal field of view
float mFovy;
//! The background color
ntlColor mcBackgr;
//! The ambient color
ntlColor mcAmbientLight;
//! how much debug output is needed? off by default
char mDebugOut;
//! animation properties, start time
int mAniStart;
//! animation properties, number of frames to render
int mAniFrames;
//! animation status, current frame number
int mAniCount;
/*! Should existing picture frames be skipped? */
int mFrameSkip;
//! count the total number of rays created (also used for ray ID's)
int mCounterRays;
//! count the total number of rays shaded
int mCounterShades;
//! count the total number of scene intersections
int mCounterSceneInter;
/*! filename of output pictures (without suffix or numbers) */
string mOutFilename;
//! get Maximum depth for BSP tree
int mTreeMaxDepth;
//! get Maxmimum nr of triangles per BSP tree node
int mTreeMaxTriangles;
//! attribute list for opengl renderer
AttributeList *mpOpenGlAttr;
//! attribute list for blender output
AttributeList *mpBlenderAttr;
//! Enable test sphere?
bool mTestSphereEnabled;
//! Center of the test sphere
ntlVec3Gfx mTestSphereCenter;
//! Radius of the test sphere
gfxReal mTestSphereRadius;
//! Materialname of the test sphere
char *mTestSphereMaterialName;
//! coordinates of the debugging pixel
int mDebugPixelX, mDebugPixelY;
//! test mode for quick rendering activated?, inited in ntl_scene::buildScene
bool mTestMode;
//! single frame flag
bool mSingleFrameMode;
//! filename for single frame mode
string mSingleFrameFilename;
/*! Two random number streams for photon generation (one for the directions, the other for russion roulette) */
ntlRandomStream *mpRndDirections, *mpRndRoulette;
};
/*****************************************************************************/
/* Constructor with standard value init */
inline ntlRenderGlobals::ntlRenderGlobals() :
mpLightList( NULL ), mpMaterials( NULL ), mpSims( NULL ),
mResX(320), mResY(200), mAADepth(-1), mMaxColVal(255),
mRayMaxDepth( 5 ),
mvEye(0.0,0.0,5.0), mvLookat(0.0,0.0,0.0), mvUpvec(0.0,1.0,0.0),
mAspect(320.0/200.0),
mFovy(45), mcBackgr(0.0,0.0,0.0), mcAmbientLight(0.0,0.0,0.0),
mDebugOut( 0 ),
mAniStart(0), mAniFrames( -1 ), mAniCount( 0 ),
mFrameSkip( 0 ),
mCounterRays( 0 ), mCounterShades( 0 ), mCounterSceneInter( 0 ),
mOutFilename( "pic" ),
mTreeMaxDepth( 30 ), mTreeMaxTriangles( 30 ),
mpOpenGlAttr(NULL),
mpBlenderAttr(NULL),
mTestSphereEnabled( false ),
mDebugPixelX( -1 ), mDebugPixelY( -1 ), mTestMode(false),
mSingleFrameMode(false), mSingleFrameFilename(""),
mpRndDirections( NULL ), mpRndRoulette( NULL )
{
// create internal attribute list for opengl renderer
mpOpenGlAttr = new AttributeList("__ntlOpenGLRenderer");
mpBlenderAttr = new AttributeList("__ntlBlenderAttr");
};
/*****************************************************************************/
/* Destructor */
inline ntlRenderGlobals::~ntlRenderGlobals() {
if(mpOpenGlAttr) delete mpOpenGlAttr;
if(mpBlenderAttr) delete mpBlenderAttr;
}
/*****************************************************************************/
//! get the next random photon direction
inline ntlVec3Gfx ntlRenderGlobals::getRandomDirection( void ) {
return ntlVec3Gfx(
(mpRndDirections->getGfxReal()-0.5),
(mpRndDirections->getGfxReal()-0.5),
(mpRndDirections->getGfxReal()-0.5) );
}
#endif

View File

@@ -1,127 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* A seperate random number stream (e.g. for photon tracing)
* (cf. Numerical recipes in C, sec. ed., p 283, Knuth method)
*
*****************************************************************************/
#ifndef NTL_RANDOMSTREAM_H
//! some big number
#define MBIG 1000000000
//! modify initial seed
#define MSEED 161803398
//! minimum value - no idea why this is a define?
#define MZ 0
//! for normalization to 0..1
#define FAC (1.0/MBIG)
/*! a stream of random numbers using Knuth's portable method */
class ntlRandomStream
{
public:
/*! Default constructor */
inline ntlRandomStream(long seed);
/*! Destructor */
~ntlRandomStream() {}
/*! get a random number from the stream */
inline double getDouble( void );
#ifdef HAVE_GFXTYPES
//! gfx random functions
/*! get a random number from the stream */
inline gfxReal getGfxReal( void );
#endif
private:
/*! random number state */
long idnum;
/*! pointers into number table */
int inext, inextp;
/*! store seed and number for subtraction */
long ma[56];
};
/* init random stream tables */
inline ntlRandomStream::ntlRandomStream(long seed)
{
idnum = seed;
long mj = MSEED - (idnum < 0 ? -idnum : idnum);
mj %= MBIG;
ma[55] = mj;
long mk = 1;
// init table once, otherwise strange results...
for(int i=0;i<=55;i++) ma[i] = (i*i+seed);
// init table in random order
for(int i=1;i<=54;i++) {
int ii = (21*i) % 56;
ma[ii] = mk;
mk = mj - mk;
if(mk < MZ) mk += MBIG;
mj = ma[ii];
}
// "warm up" generator
for(int k=1;k<=4;k++)
for(int i=1;i<=55;i++) {
ma[i] -= ma[1+ (i+30) % 55];
if(ma[i] < MZ) ma[i] += MBIG;
}
inext = 0;
inextp = 31; // the special "31"
idnum = 1;
}
/* return one random value */
inline double ntlRandomStream::getDouble( void )
{
if( ++inext == 56) inext = 1;
if( ++inextp == 56) inextp = 1;
// generate by subtaction
long mj = ma[inext] - ma[inextp];
// check range
if(mj < MZ) mj += MBIG;
ma[ inext ] = mj;
return (double)(mj * FAC);
}
#ifdef HAVE_GFXTYPES
/* return one random value */
inline gfxReal ntlRandomStream::getGfxReal( void )
{
if( ++inext == 56) inext = 1;
if( ++inextp == 56) inextp = 1;
// generate by subtaction
long mj = ma[inext] - ma[inextp];
// check range
if(mj < MZ) mj += MBIG;
ma[ inext ] = mj;
return (gfxReal)(mj * FAC);
}
#endif
#define NTL_RANDOMSTREAM_H
#endif

View File

@@ -1,235 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* Scene object, that contains and manages all geometry objects
*
*****************************************************************************/
#include "utilities.h"
#include "ntl_scene.h"
#include "ntl_geometryobject.h"
#include "ntl_geometryshader.h"
/******************************************************************************
* Constructor
*****************************************************************************/
ntlScene::ntlScene( ntlRenderGlobals *glob ) :
mpGlob( glob ),
mpTree( NULL ),
mDisplayListId( -1 ),
mSceneBuilt( false ), mFirstInitDone( false )
{
}
/******************************************************************************
* Destructor
*****************************************************************************/
ntlScene::~ntlScene()
{
cleanupScene();
// cleanup lists
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
delete (*iter);
}
for (vector<ntlLightObject*>::iterator iter = mpGlob->getLightList()->begin();
iter != mpGlob->getLightList()->end(); iter++) {
delete (*iter);
}
for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin();
iter != mpGlob->getMaterials()->end(); iter++) {
delete (*iter);
}
}
/******************************************************************************
* Build the scene arrays (obj, tris etc.)
*****************************************************************************/
void ntlScene::buildScene( void )
{
const bool buildInfo=false;
mObjects.clear();
/* init geometry array, first all standard objects */
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
bool geoinit = false;
int tid = (*iter)->getTypeId();
if(tid & GEOCLASSTID_OBJECT) {
ntlGeometryObject *geoobj = (ntlGeometryObject*)(*iter);
geoinit = true;
mObjects.push_back( geoobj );
if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName(), 5 );
}
//if(geoshad) {
if(tid & GEOCLASSTID_SHADER) {
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter);
geoinit = true;
if(!mFirstInitDone) {
// only on first init
geoshad->initializeShader();
}
for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
siter != geoshad->getObjectsEnd();
siter++) {
if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 5 );
mObjects.push_back( (*siter) );
}
}
if(!geoinit) {
errFatal("ntlScene::BuildScene","Invalid geometry class!", SIMWORLD_INITERROR);
return;
}
}
// collect triangles
mTriangles.clear();
mVertices.clear();
mVertNormals.clear();
/* for test mode deactivate transparencies etc. */
if( mpGlob->getTestMode() ) {
debugOut("ntlScene::buildScene : Test Mode activated!", 2);
// assign random colors to dark materials
int matCounter = 0;
ntlColor stdCols[] = { ntlColor(0,0,1.0), ntlColor(0,1.0,0), ntlColor(1.0,0.7,0) , ntlColor(0.7,0,0.6) };
int stdColNum = 4;
for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin();
iter != mpGlob->getMaterials()->end(); iter++) {
(*iter)->setTransparence(0.0);
(*iter)->setMirror(0.0);
(*iter)->setFresnel(false);
// too dark?
if( norm((*iter)->getDiffuseRefl()) <0.01) {
(*iter)->setDiffuseRefl( stdCols[matCounter] );
matCounter ++;
matCounter = matCounter%stdColNum;
}
}
// restrict output file size to 400
float downscale = 1.0;
if(mpGlob->getResX() > 400){ downscale = 400.0/(float)mpGlob->getResX(); }
if(mpGlob->getResY() > 400){
float downscale2 = 400.0/(float)mpGlob->getResY();
if(downscale2<downscale) downscale=downscale2;
}
mpGlob->setResX( (int)(mpGlob->getResX() * downscale) );
mpGlob->setResY( (int)(mpGlob->getResY() * downscale) );
}
/* collect triangles from objects */
int idCnt = 0; // give IDs to objects
for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin();
iter != mObjects.end();
iter++) {
/* only add visible objects */
(*iter)->initialize( mpGlob );
(*iter)->getTriangles(&mTriangles, &mVertices, &mVertNormals, idCnt);
idCnt ++;
}
/* calculate triangle normals, and initialize flags */
for (vector<ntlTriangle>::iterator iter = mTriangles.begin();
iter != mTriangles.end();
iter++) {
// calculate normal from triangle points
ntlVec3Gfx normal =
cross( (ntlVec3Gfx)( (mVertices[(*iter).getPoints()[2]] - mVertices[(*iter).getPoints()[0]]) *-1.0), // BLITZ minus sign right??
(ntlVec3Gfx)(mVertices[(*iter).getPoints()[1]] - mVertices[(*iter).getPoints()[0]]) );
normalize(normal);
(*iter).setNormal( normal );
}
// scene geometry built
mSceneBuilt = true;
// init shaders that require complete geometry
if(!mFirstInitDone) {
// only on first init
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
iter != mGeos.end(); iter++) {
if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) {
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter);
geoshad->postGeoConstrInit( mpGlob );
}
}
mFirstInitDone = true;
}
// check unused attributes (for classes and objects!)
for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); iter != mObjects.end(); iter++) {
if((*iter)->getAttributeList()->checkUnusedParams()) {
(*iter)->getAttributeList()->print(); // DEBUG
errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR );
return;
}
}
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); iter != mGeos.end(); iter++) {
if((*iter)->getAttributeList()->checkUnusedParams()) {
(*iter)->getAttributeList()->print(); // DEBUG
errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR );
return;
}
}
}
/******************************************************************************
* Prepare the scene triangles and maps for raytracing
*****************************************************************************/
void ntlScene::prepareScene( void )
{
/* init triangles... */
buildScene();
// what for currently not used ???
if(mpTree != NULL) delete mpTree;
mpTree = new ntlTree( mpGlob->getTreeMaxDepth(), mpGlob->getTreeMaxTriangles(),
this, TRI_GEOMETRY );
//debMsgStd("ntlScene::prepareScene",DM_MSG,"Stats - tris:"<< (int)mTriangles.size()<<" verts:"<<mVertices.size()<<" vnorms:"<<mVertNormals.size(), 5 );
}
/******************************************************************************
* Do some memory cleaning, when frame is finished
*****************************************************************************/
void ntlScene::cleanupScene( void )
{
mObjects.clear();
mTriangles.clear();
mVertices.clear();
mVertNormals.clear();
if(mpTree != NULL) delete mpTree;
mpTree = NULL;
}
/******************************************************************************
* Intersect a ray with the scene triangles
*****************************************************************************/
void ntlScene::intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri,int flags) const
{
distance = -1.0;
mpGlob->setCounterSceneInter( mpGlob->getCounterSceneInter()+1 );
mpTree->intersect(r, distance, normal, tri, flags, false);
}

View File

@@ -1,167 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* Scene object, that contains and manages all geometry objects
*
*****************************************************************************/
#ifndef NTL_SCENE_HH
#define NTL_SCENE_HH
#include <sstream>
#include "ntl_vector3dim.h"
#include "ntl_material.h"
#include "ntl_geometryclass.h"
#include "ntl_triangle.h"
#include "ntl_bsptree.h"
class ntlRay;
class ntlGeometryObject;
//! convenience macro for adding triangles
#define sceneAddTriangle(p1,p2,p3, pn1,pn2,pn3, trin, smooth) {\
\
ntlTriangle tri;\
int tempVert;\
\
if(normals->size() != vertices->size()) {\
errFatal("getTriangles","For '"<<mName<<"': Vertices and normals sizes to not match!!!",SIMWORLD_GENERICERROR);\
} else {\
\
vertices->push_back( p1 ); \
normals->push_back( pn1 ); \
tempVert = normals->size()-1;\
tri.getPoints()[0] = tempVert;\
\
vertices->push_back( p2 ); \
normals->push_back( pn2 ); \
tempVert = normals->size()-1;\
tri.getPoints()[1] = tempVert;\
\
vertices->push_back( p3 ); \
normals->push_back( pn3 ); \
tempVert = normals->size()-1;\
tri.getPoints()[2] = tempVert;\
\
\
/* init flags */\
int flag = 0; \
if(getVisible()){ flag |= TRI_GEOMETRY; }\
if(getCastShadows() ) { \
flag |= TRI_CASTSHADOWS; } \
if( (getMaterial()->getMirror()>0.0) || \
(getMaterial()->getTransparence()>0.0) || \
(getMaterial()->getFresnel()>0.0) ) { \
flag |= TRI_MAKECAUSTICS; } \
else { \
flag |= TRI_NOCAUSTICS; } \
\
/* init geo init id */\
int geoiId = getGeoInitId(); \
if(geoiId > 0) { \
flag |= (1<< (geoiId+4)); \
flag |= mGeoInitType; \
} \
\
tri.setFlags( flag );\
\
/* triangle normal missing */\
tri.setNormal( trin );\
tri.setSmoothNormals( smooth );\
tri.setObjectId( objectId );\
triangles->push_back( tri ); \
} /* normals check*/ \
}\
class ntlScene
{
public:
/* CONSTRUCTORS */
/*! Default constructor */
ntlScene( ntlRenderGlobals *glob );
/*! Default destructor */
~ntlScene();
/*! Add an object to the scene */
inline void addGeoClass(ntlGeometryClass *geo) { mGeos.push_back( geo ); }
/*! Acces a certain object */
inline ntlGeometryObject *getObject(int id) {
if(!mSceneBuilt) { errMsg("ntlScene::getObject","Scene not inited!"); return NULL; }
return mObjects[id]; }
/*! Acces object array */
inline vector<ntlGeometryObject*> *getObjects() {
if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); return NULL; }
return &mObjects; }
/*! Acces geo class array */
inline vector<ntlGeometryClass*> *getGeoClasses() {
if(!mSceneBuilt) { errMsg("ntlScene::getGeoClasses[]","Scene not inited!"); return NULL; }
return &mGeos; }
/*! draw scene with opengl */
//void draw();
/*! Build the scene arrays */
void buildScene( void );
//! Prepare the scene triangles and maps for raytracing
void prepareScene( void );
//! Do some memory cleaning, when frame is finished
void cleanupScene( void );
/*! Intersect a ray with the scene triangles */
void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const;
/*! return a vertex */
ntlVec3Gfx getVertex(int index) { return mVertices[index]; }
// for tree generation
/*! return pointer to vertices vector */
vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; }
/*! return pointer to vertices vector */
vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; }
/*! return pointer to vertices vector */
vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; }
private:
/*! Global settings */
ntlRenderGlobals *mpGlob;
/*! List of geometry classes */
vector<ntlGeometryClass *> mGeos;
/*! List of geometry objects */
vector<ntlGeometryObject *> mObjects;
/*! List of triangles */
vector<ntlTriangle> mTriangles;
/*! List of vertices */
vector<ntlVec3Gfx> mVertices;
/*! List of normals */
vector<ntlVec3Gfx> mVertNormals;
/*! List of triangle normals */
vector<ntlVec3Gfx> mTriangleNormals;
/*! Tree to store quickly intersect triangles */
ntlTree *mpTree;
/*! id of dislpay list for raytracer stuff */
int mDisplayListId;
/*! was the scene successfully built? only then getObject(i) requests are valid */
bool mSceneBuilt;
/*! shader/obj initializations are only done on first init */
bool mFirstInitDone;
};
#endif

View File

@@ -1,183 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* Copyright 2003,2004 Nils Thuerey
*
* a single triangle
*
*****************************************************************************/
#ifndef NTL_TRIANGLE_HH
#define NTL_TRIANGLE_HH
#include "ntl_vector3dim.h"
#include "ntl_material.h"
class ntlRay;
/*! Triangle flag defines */
#define TRI_GEOMETRY (1<<0)
#define TRI_CASTSHADOWS (1<<1)
#define TRI_MAKECAUSTICS (1<<2)
#define TRI_NOCAUSTICS (1<<3)
class ntlTriangle
{
public:
/* CONSTRUCTORS */
/*! Default constructor */
inline ntlTriangle( void );
/*! Constructor with parameters */
inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags);
/*! Copy - Constructor */
inline ntlTriangle(const ntlTriangle &tri);
/*! Destructor */
inline ~ntlTriangle() {}
/* Access methods */
/*! Acces to points of triangle */
inline int *getPoints( void ) { return mPoints; }
/*! Acces normal smoothing */
inline bool getSmoothNormals( void ) const { return mSmoothNormals; }
inline void setSmoothNormals( bool set){ mSmoothNormals = set; }
/*! Access object */
inline int getObjectId( void ) const { return mObjectId; }
inline void setObjectId( int set) { mObjectId = set; }
/*! Acces normal index */
inline ntlVec3Gfx getNormal( void ) const { return mNormal; }
inline void setNormal( ntlVec3Gfx set ) { mNormal = set; }
/*! Acces flags */
inline int getFlags( void ) const { return mFlags; }
inline void setFlags( int set ) { mFlags = set; }
/*! Access last intersection ray ID */
inline int getLastRay( void ) const { return mLastRay; }
inline void setLastRay( int set ) { mLastRay = set; }
/*! Acces bbox id */
inline int getBBoxId( void ) const { return mBBoxId; }
inline void setBBoxId( int set ) { mBBoxId = set; }
/*! Get average of the three points for this axis */
inline gfxReal getAverage( int axis ) const;
/*! operator < for sorting, uses global sorting axis */
inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs);
/*! operator > for sorting, uses global sorting axis */
inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs);
protected:
private:
/*! indices to the three points of the triangle */
int mPoints[3];
/*! bounding box id (for tree generation), -1 if invalid */
int mBBoxId;
/*! Should the normals of this triangle get smoothed? */
bool mSmoothNormals;
/*! Id of parent object */
int mObjectId;
/*! Index to normal (for not smooth triangles) */
//int mNormalIndex; ??
ntlVec3Gfx mNormal;
/*! Flags for object attributes cast shadows, make caustics etc. */
int mFlags;
/*! ID of last ray that an intersection was calculated for */
int mLastRay;
};
/******************************************************************************
* Default Constructor
*****************************************************************************/
ntlTriangle::ntlTriangle( void ) :
mBBoxId(-1),
mLastRay( 0 )
{
mPoints[0] = mPoints[1] = mPoints[2] = 0;
mSmoothNormals = 0;
mObjectId = 0;
mNormal = ntlVec3Gfx(0.0);
mFlags = 0;
}
/******************************************************************************
* Constructor
*****************************************************************************/
ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) :
mBBoxId(-1),
mLastRay( 0 )
{
mPoints[0] = p[0];
mPoints[1] = p[1];
mPoints[2] = p[2];
mSmoothNormals = smooth;
mObjectId = obj;
mNormal = norm;
mFlags = setflags;
}
/******************************************************************************
* Copy Constructor
*****************************************************************************/
ntlTriangle::ntlTriangle(const ntlTriangle &tri) :
mBBoxId(-1),
mLastRay( 0 )
{
mPoints[0] = tri.mPoints[0];
mPoints[1] = tri.mPoints[1];
mPoints[2] = tri.mPoints[2];
mSmoothNormals = tri.mSmoothNormals;
mObjectId = tri.mObjectId;
mNormal = tri.mNormal;
mFlags = tri.mFlags;
}
/******************************************************************************
* Triangle sorting functions
*****************************************************************************/
/* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */
/* Static global variable for sorting direction */
extern int globalSortingAxis;
/* Access to points array for sorting */
extern vector<ntlVec3Gfx> *globalSortingPoints;
gfxReal ntlTriangle::getAverage( int axis ) const
{
return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] +
(*globalSortingPoints)[ mPoints[1] ][axis] +
(*globalSortingPoints)[ mPoints[2] ][axis] )/3.0);
}
bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs)
{
return ( lhs.getAverage(globalSortingAxis) <
rhs.getAverage(globalSortingAxis) );
}
bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs)
{
return ( lhs.getAverage(globalSortingAxis) >
rhs.getAverage(globalSortingAxis) );
}
#endif

View File

@@ -92,6 +92,7 @@ using std::string;
#ifndef M_PI
#define M_PI 3.1415926536
#define M_E 2.7182818284
#endif
// make sure elbeem plugin def is valid

View File

@@ -12,9 +12,7 @@
#include <sstream>
#include "utilities.h"
#include "ntl_world.h"
#include "ntl_scene.h"
#include "parametrizer.h"
#include "globals.h"
// for non-threaded renderViz
#ifndef NOGUI
@@ -25,114 +23,41 @@
/* external parser functions from cfgparser.cxx */
#ifndef ELBEEM_PLUGIN
/* parse given file as config file */
void parseFile(string filename);
/* set pointers for parsing */
void setPointers( ntlRenderGlobals *setglob);
#endif // ELBEEM_PLUGIN
/******************************************************************************
* Constructor
*****************************************************************************/
ntlWorld::ntlWorld(string filename, bool commandlineMode)
/*:
mpGlob(NULL),
mpLightList(NULL), mpPropList(NULL), mpSims(NULL),
mpOpenGLRenderer(NULL),
mStopRenderVisualization( false ),
mThreadRunning( false ),
mSimulationTime(0.0), mFirstSim(-1),
mSingleStepDebug( false ),
mFrameCnt(0)*/
{
#if 0
/* create scene storage */
mpGlob = new ntlRenderGlobals();
mpLightList = new vector<ntlLightObject*>;
mpPropList = new vector<ntlMaterial*>;
mpSims = new vector<SimulationObject*>;
#ifndef ELBEEM_PLUGIN
mpGlob->setLightList(mpLightList);
mpGlob->setMaterials(mpPropList);
mpGlob->setSims(mpSims);
initDefaults();
# ifdef NOGUI
commandlineMode = true; // remove warning...
# endif // NOGUI
/* init default material */
ntlMaterial *def = GET_GLOBAL_DEFAULT_MATERIAL;
mpPropList->push_back( def );
/* init the scene object */
ntlScene *scene;
scene = new ntlScene( mpGlob );
mpGlob->setScene( scene );
// moved TODO test...
#endif // 0
initDefaults();
#ifndef NOGUI
// setup opengl display, save first animation step for start time
if(!commandlineMode) {
mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob );
}
#else // NOGUI
commandlineMode = true; // remove warning...
#endif // NOGUI
// load config
setPointers( getRenderGlobals() );
parseFile( filename.c_str() );
finishWorldInit();
/*if(!SIMWORLD_OK()) return;
// init the scene for the first time
long sstartTime = getTime();
scene->buildScene();
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]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) {
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);
}
// load config
setPointers( getRenderGlobals() );
parseFile( filename.c_str() );
# ifndef NOGUI
// setup opengl display, save first animation step for start time
// init after parsing file...
if(!commandlineMode) {
mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob );
}
# endif // NOGUI
finishWorldInit();
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 simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1);
#ifndef NOGUI
guiResetSimulationTimeRange( mSimulationTime );
#endif
} else {
if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlWorld::ntlWorld",DM_WARNING,"No active simulations!", 1);
}
}
*/
#else // ELBEEM_PLUGIN
errFatal("ntlWorld::init","Cfg file parsing not supported for API version!", SIMWORLD_INITERROR);
#endif // ELBEEM_PLUGIN
}
ntlWorld::ntlWorld(elbeemSimulationSettings *settings)
@@ -141,34 +66,53 @@ ntlWorld::ntlWorld(elbeemSimulationSettings *settings)
// todo init settings
SimulationObject *sim = new SimulationObject();
mpGlob->getSims()->push_back( sim );
mpGlob->getScene()->addGeoClass( sim );
// important - add to both, only render scene objects are free'd
mpGlob->getRenderScene()->addGeoClass( sim );
mpGlob->getSimScene()->addGeoClass( sim );
sim->setGeoStart(ntlVec3Gfx(settings->geoStart[0],settings->geoStart[1],settings->geoStart[2]));
sim->setGeoEnd(ntlVec3Gfx(
settings->geoStart[0]+settings->geoSize[0],
settings->geoStart[1]+settings->geoSize[1],
settings->geoStart[2]+settings->geoSize[2] ));
sim->getSolver()->setSmoothing(1.0, 0.0);
sim->getSolver()->setPreviewSize(settings->previewresxyz);
sim->getSolver()->setRefinementDesired(settings->maxRefine);
// further init in postGeoConstrInit/initializeLbmSimulation of SimulationObject
sim->copyElbeemSettings(settings);
Parametrizer *param = sim->getParametrizer();
param->setSize( settings->resolutionxyz );
param->setDomainSize( settings->realsize );
param->setViscosity( settings->viscosity );
param->setGravity( ParamVec(settings->gravx, settings->gravy, settings->gravx) );
param->setGravity( ParamVec(settings->gravity[0], settings->gravity[1], settings->gravity[2]) );
param->setAniStart( settings->animStart );
param->setAniFrameTime( settings->aniFrameTime );
param->setAniFrameTimeChannel( settings->aniFrameTime );
param->setNormalizedGStar( settings->gstar );
// dont setup lights, camera, materials...?
/*
ntlMaterial *fluidmat = new ntlMaterial( );
currentMaterial->setAmbientRefl( ntlColor(0.3, 0.5, 0.9) );
currentMaterial->setDiffuseRefl( ntlColor(0.3, 0.5, 0.9) );
currentMaterial->setSpecular( 0.2 );
currentMaterial->setSpecExponent( 10.0 );
mpGlob->getMaterials()->push_back( fluidmat );
// */
// init domain channels
vector<ParamFloat> valf;
vector<ParamVec> valv;
vector<double> time;
#define INIT_CHANNEL_FLOAT(channel,size) \
valf.clear(); time.clear(); elbeemSimplifyChannelFloat(channel,&size); \
for(int i=0; i<size; i++) { valf.push_back( channel[2*i+0] ); time.push_back( channel[2*i+1] ); }
#define INIT_CHANNEL_VEC(channel,size) \
valv.clear(); time.clear(); elbeemSimplifyChannelVec3(channel,&size); \
for(int i=0; i<size; i++) { valv.push_back( ParamVec(channel[4*i+0],channel[4*i+1],channel[4*i+2]) ); time.push_back( channel[4*i+3] ); }
INIT_CHANNEL_FLOAT(settings->channelViscosity, settings->channelSizeViscosity);
param->initViscosityChannel(valf,time);
INIT_CHANNEL_VEC(settings->channelGravity, settings->channelSizeGravity);
param->initGravityChannel(valv,time);
INIT_CHANNEL_FLOAT(settings->channelFrameTime, settings->channelSizeFrameTime);
param->initAniFrameTimeChannel(valf,time);
#undef INIT_CHANNEL_FLOAT
#undef INIT_CHANNEL_VEC
mpGlob->setAniFrames( settings->noOfFrames );
mpGlob->setOutFilename( settings->outputPath );
// further init in postGeoConstrInit/initializeLbmSimulation of SimulationObject
}
void ntlWorld::initDefaults()
@@ -196,8 +140,11 @@ void ntlWorld::initDefaults()
mpPropList->push_back( def );
/* init the scene object */
ntlScene *newscene = new ntlScene( mpGlob );
mpGlob->setScene( newscene );
ntlScene *renderscene = new ntlScene( mpGlob, true );
mpGlob->setRenderScene( renderscene );
// sim scene shouldnt delete objs, may only contain subset
ntlScene *simscene = new ntlScene( mpGlob, false );
mpGlob->setSimScene( simscene );
}
void ntlWorld::finishWorldInit()
@@ -206,7 +153,10 @@ void ntlWorld::finishWorldInit()
// init the scene for the first time
long sstartTime = getTime();
mpGlob->getScene()->buildScene();
// first init sim scene for geo setup
mpGlob->getSimScene()->buildScene(0.0, true);
mpGlob->getRenderScene()->buildScene(0.0, true);
long sstopTime = getTime();
debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Scene build time: "<< getTimeString(sstopTime-sstartTime) <<" ", 10);
@@ -225,7 +175,7 @@ void ntlWorld::finishWorldInit()
// check largest timestep
if(mFirstSim>=0) {
if( (*mpSims)[i]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) {
if( (*mpSims)[i]->getTimestep() > (*mpSims)[mFirstSim]->getTimestep() ) {
mFirstSim = i;
debMsgStd("ntlWorld::ntlWorld",DM_MSG,"First Sim changed: "<<i ,10);
}
@@ -246,7 +196,7 @@ void ntlWorld::finishWorldInit()
long stopTime = getTime();
mSimulationTime += (*mpSims)[mFirstSim]->getStartTime();
debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1);
debMsgStd("ntlWorld::ntlWorld",DM_MSG,"Time for start-sims:"<< getTimeString(stopTime-startTime) , 1);
#ifndef NOGUI
guiResetSimulationTimeRange( mSimulationTime );
#endif
@@ -263,7 +213,8 @@ void ntlWorld::finishWorldInit()
*****************************************************************************/
ntlWorld::~ntlWorld()
{
delete mpGlob->getScene();
delete mpGlob->getRenderScene();
delete mpGlob->getSimScene();
delete mpGlob;
delete mpLightList;
delete mpPropList;
@@ -271,6 +222,7 @@ ntlWorld::~ntlWorld()
#ifndef NOGUI
if(mpOpenGLRenderer) delete mpOpenGLRenderer;
#endif // NOGUI
debMsgStd("ntlWorld",DM_NOTIFY, "ntlWorld done", 10);
}
/******************************************************************************/
@@ -349,9 +301,9 @@ int ntlWorld::renderVisualization( bool multiThreaded )
advanceSims(mFrameCnt);
mFrameCnt++;
long stopTime = getTime();
debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for "<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<"s ", 10);
debMsgStd("ntlWorld::renderVisualization",DM_MSG,"Time for t="<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<" ", 10);
} else {
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime();
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep();
singleStepSims(targetTime);
// check paniced sims (normally done by advanceSims
@@ -390,7 +342,7 @@ int ntlWorld::renderVisualization( bool multiThreaded )
int ntlWorld::singleStepVisualization( void )
{
mThreadRunning = true;
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime();
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep();
singleStepSims(targetTime);
mSimulationTime = (*mpSims)[0]->getCurrentTime();
@@ -419,12 +371,10 @@ int ntlWorld::advanceSims(int framenum)
//debMsgStd("ntlWorld::advanceSims",DM_MSG,"Advancing sims to "<<targetTime, 10 ); // timedebug
for(size_t i=0;i<mpSims->size();i++) { (*mpSims)[i]->setFrameNum(framenum); }
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime();
//FIXME check blender abort here...
//FIXME check no ipo export
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime(framenum);
// time stopped? nothing else to do...
if( (*mpSims)[mFirstSim]->getFrameTime() <= 0.0 ){
if( (*mpSims)[mFirstSim]->getFrameTime(framenum) <= 0.0 ){
done=true; allPanic=false;
}
@@ -437,17 +387,25 @@ int ntlWorld::advanceSims(int framenum)
#endif // ELBEEM_BLENDER==1
// step all the sims, and check for panic
debMsgStd("ntlWorld::advanceSims",DM_MSG, " sims "<<mpSims->size()<<" t"<<targetTime<<" done:"<<done<<" panic:"<<allPanic, 10); // debug // timedebug
while(!done) {
double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getStepTime();
double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getTimestep();
singleStepSims(nextTargetTime);
// check target times
done = true;
allPanic = false;
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<<" c"<<(*mpSims)[i]->getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<<targetTime, 10); // debug // timedebug
//if((framenum>0) && (nextTargetTime<=(*mpSims)[mFirstSim]->getCurrentTime()) ) {
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;
@@ -474,7 +432,7 @@ int ntlWorld::advanceSims(int framenum)
/* dont check target time, if *targetTime==NULL */
void ntlWorld::singleStepSims(double targetTime) {
const bool debugTime = false;
//double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime();
//double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getTimestep();
if(debugTime) errMsg("ntlWorld::singleStepSims","Target time: "<<targetTime);
for(size_t i=0;i<mpSims->size();i++) {
@@ -484,7 +442,7 @@ void ntlWorld::singleStepSims(double targetTime) {
bool done = false;
while(!done) {
// try to prevent round off errs
if(debugTime) errMsg("ntlWorld::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getStepTime()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug
if(debugTime) errMsg("ntlWorld::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getTimestep()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug
if( (targetTime - sim->getCurrentTime()) > LBM_TIME_EPSILON) {
if(debugTime) errMsg("ntlWorld::singleStepSims","Stepping sim "<<i<<" t:"<< sim->getCurrentTime()); // timedebug
sim->step();
@@ -509,7 +467,7 @@ void ntlWorld::singleStepSims(double targetTime) {
*****************************************************************************/
int ntlWorld::renderScene( void )
{
#ifndef ELBEEM_BLENDER
#ifndef ELBEEM_PLUGIN
char nrStr[5]; /* nr conversion */
//std::ostringstream outfilename(""); /* ppm file */
std::ostringstream outfn_conv(""); /* converted ppm with other suffix */
@@ -541,8 +499,8 @@ int ntlWorld::renderScene( void )
/* start program */
timeStart = getTime();
/* build scene geometry */
glob->getScene()->prepareScene();
/* build scene geometry, calls buildScene(t,false) */
glob->getRenderScene()->prepareScene(mSimulationTime);
/* start program */
totalStart = getTime();
@@ -566,7 +524,7 @@ int ntlWorld::renderScene( void )
/* check if vectors are valid */
if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) {
errorOut("NTL ERROR: Invalid viewpoint vectors!\n");
errMsg("ntlWorld::renderScene","Invalid viewpoint vectors! up="<<upVec<<" right="<<rightVec);
return(1);
}
@@ -856,15 +814,66 @@ int ntlWorld::renderScene( void )
delete [] aaCol;
delete [] aaUse;
delete [] finalPic;
glob->getScene()->cleanupScene();
glob->getRenderScene()->cleanupScene();
if(mpGlob->getSingleFrameMode() ) {
debMsgStd("ntlWorld::renderScene",DM_NOTIFY, "Single frame mode done...", 1 );
return 1;
}
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
return 0;
}
/******************************************************************************
* renderglobals
*****************************************************************************/
/*****************************************************************************/
/* Constructor with standard value init */
ntlRenderGlobals::ntlRenderGlobals() :
mpRenderScene(NULL), mpSimScene(NULL),
mpLightList( NULL ), mpMaterials( NULL ), mpSims( NULL ),
mResX(320), mResY(200), mAADepth(-1), mMaxColVal(255),
mRayMaxDepth( 5 ),
mvEye(0.0,0.0,5.0), mvLookat(0.0,0.0,0.0), mvUpvec(0.0,1.0,0.0),
mAspect(320.0/200.0),
mFovy(45), mcBackgr(0.0,0.0,0.0), mcAmbientLight(0.0,0.0,0.0),
mDebugOut( 0 ),
mAniStart(0), mAniFrames( -1 ), mAniCount( 0 ),
mFrameSkip( 0 ),
mCounterRays( 0 ), mCounterShades( 0 ), mCounterSceneInter( 0 ),
mOutFilename( "pic" ),
mTreeMaxDepth( 30 ), mTreeMaxTriangles( 30 ),
mpOpenGlAttr(NULL),
mpBlenderAttr(NULL),
mTestSphereEnabled( false ),
mDebugPixelX( -1 ), mDebugPixelY( -1 ), mTestMode(false),
mSingleFrameMode(false), mSingleFrameFilename("")
//,mpRndDirections( NULL ), mpRndRoulette( NULL )
{
// create internal attribute list for opengl renderer
mpOpenGlAttr = new AttributeList("__ntlOpenGLRenderer");
mpBlenderAttr = new AttributeList("__ntlBlenderAttr");
};
/*****************************************************************************/
/* Destructor */
ntlRenderGlobals::~ntlRenderGlobals() {
if(mpOpenGlAttr) delete mpOpenGlAttr;
if(mpBlenderAttr) delete mpBlenderAttr;
}
/*****************************************************************************/
//! get the next random photon direction
//ntlVec3Gfx ntlRenderGlobals::getRandomDirection( void ) {
//return ntlVec3Gfx(
//(mpRndDirections->getGfxReal()-0.5),
//(mpRndDirections->getGfxReal()-0.5),
//(mpRndDirections->getGfxReal()-0.5) );
//}

View File

@@ -11,13 +11,14 @@
#include "ntl_vector3dim.h"
#include "ntl_ray.h"
#include "ntl_lighting.h"
#include "ntl_geometryobject.h"
#include "ntl_lightobject.h"
#include "ntl_renderglobals.h"
#include "ntl_material.h"
#include "simulation_object.h"
#include "elbeem.h"
class ntlOpenGLRenderer;
class ntlScene;
class SimulationObject;
class ntlRandomStream;
class ntlWorld
{
@@ -100,6 +101,7 @@ class ntlWorld
/*! remember the current simulation time */
double mSimulationTime;
/*! first simulation that is valid */
int mFirstSim;
@@ -110,4 +112,279 @@ class ntlWorld
int mFrameCnt;
};
//! Class that handles global rendering parameters
class ntlRenderGlobals
{
public:
//! Standard constructor
ntlRenderGlobals();
//! Destructor
~ntlRenderGlobals();
//! Returns the renderscene manager (scene changes for each frame)
inline ntlScene *getRenderScene(void) { return mpRenderScene; }
//! Set the renderscene manager
inline void setRenderScene(ntlScene *set) { mpRenderScene = set;}
//! Returns the simulation scene manager (static scene with sim objects)
inline ntlScene *getSimScene(void) { return mpSimScene; }
//! Set the simulation scene manager
inline void setSimScene(ntlScene *set) { mpSimScene = set;}
//! Returns the light object list
inline vector<ntlLightObject*> *getLightList(void) { return mpLightList; }
//! Set the light list
inline void setLightList(vector<ntlLightObject*> *set) { mpLightList = set;}
//! Returns the property object list
inline vector<ntlMaterial*> *getMaterials(void) { return mpMaterials; }
//! Set the property list
inline void setMaterials(vector<ntlMaterial*> *set) { mpMaterials = set;}
//! Returns the list of simulations
inline vector<SimulationObject*> *getSims(void) { return mpSims; }
//! Set the pointer to the list of simulations
inline void setSims(vector<SimulationObject*> *set) { mpSims = set;}
//! Set the x resolution
inline void setResX(unsigned int set) { mResX = set; }
//! Set the y resolution
inline void setResY(unsigned int set) { mResY = set; }
//! Set the anti-aliasing depth
inline void setAADepth(int set) { mAADepth = set; }
//! Set the max color value
inline void setMaxColVal(unsigned int set) { mMaxColVal = set; }
//! Set the maximum ray recursion
inline void setRayMaxDepth(unsigned int set) { mRayMaxDepth = set; }
//! Set the eye point
inline void setEye(ntlVec3Gfx set) { mvEye = set; }
//! Set the look at vector
inline void setLookat(ntlVec3Gfx set) { mvLookat = set; }
//! Set the up vector
inline void setUpVec(ntlVec3Gfx set) { mvUpvec = set; }
//! Set the image aspect
inline void setAspect(float set) { mAspect = set; }
//! Set the field of view
inline void setFovy(float set) { mFovy = set; }
//! Set the background color
inline void setBackgroundCol(ntlColor set) { mcBackgr = set; }
//! Set the ambient lighting color
inline void setAmbientLight(ntlColor set) { mcAmbientLight = set; }
//! Set the debug output var
inline void setDebugOut(int set) { mDebugOut = set; }
//! Set the animation start time
inline void setAniStart(int set) { mAniStart = set; }
//! Set the animation number of frames
inline void setAniFrames(int set) { mAniFrames = set; }
//! Set the animation
inline void setAniCount(int set) { mAniCount = set; }
//! Set the ray counter
inline void setCounterRays(int set) { mCounterRays = set; }
//! Set the ray shades counter
inline void setCounterShades(int set) { mCounterShades = set; }
//! Set the scenen intersection counter
inline void setCounterSceneInter(int set) { mCounterSceneInter = set; }
//! Set if existing frames should be skipped
inline void setFrameSkip(int set) { mFrameSkip = set; }
//! Set the outfilename
inline void setOutFilename(string set) { mOutFilename = set; }
//! get Maximum depth for BSP tree
inline void setTreeMaxDepth( int set ) { mTreeMaxDepth = set; }
//! get Maxmimum nr of triangles per BSP tree node
inline void setTreeMaxTriangles( int set ) { mTreeMaxTriangles = set; }
//! set the enable flag of the test sphere
inline void setTestSphereEnabled( bool set ) { mTestSphereEnabled = set; }
//! set the center of the test sphere
inline void setTestSphereCenter( ntlVec3Gfx set ) { mTestSphereCenter = set; }
//! set the radius of the test sphere
inline void setTestSphereRadius( gfxReal set ) { mTestSphereRadius = set; }
//! set the material name of the test sphere
inline void setTestSphereMaterialName( char* set ) { mTestSphereMaterialName = set; }
//! set debugging pixel coordinates
inline void setDebugPixel( int setx, int sety ) { mDebugPixelX = setx; mDebugPixelY = sety; }
//! set test mode flag
inline void setTestMode( bool set ) { mTestMode = set; }
//! set single frame mode flag
inline void setSingleFrameMode(bool set) {mSingleFrameMode = set; };
//! set single frame mode filename
inline void setSingleFrameFilename(string set) {mSingleFrameFilename = set; };
//! Return the x resolution
inline unsigned int getResX(void) { return mResX; }
//! Return the y resolution
inline unsigned int getResY(void) { return mResY; }
//! Return the anti-aliasing depth
inline int getAADepth(void) { return mAADepth; }
//! Return the max color value for ppm
inline unsigned int getMaxColVal(void) { return mMaxColVal; }
//! Return the maximum ray recursion
inline unsigned int getRayMaxDepth(void) { return mRayMaxDepth; }
//! Return the eye point
inline ntlVec3Gfx getEye(void) { return mvEye; }
//! Return the look at vector
inline ntlVec3Gfx getLookat(void) { return mvLookat; }
//! Return the up vector
inline ntlVec3Gfx getUpVec(void) { return mvUpvec; }
//! Return the image aspect
inline float getAspect(void) { return mAspect; }
//! Return the field of view
inline float getFovy(void) { return mFovy; }
//! Return the background color
inline ntlColor getBackgroundCol(void) { return mcBackgr; }
//! Return the ambient color
inline ntlColor getAmbientLight(void) { return mcAmbientLight; }
//! Return the debug mode setting
inline int getDebugOut(void) { return mDebugOut; }
//! Return the animation start time
inline int getAniStart(void) { return mAniStart; }
//! Return the animation frame number
inline int getAniFrames(void) { return mAniFrames; }
//! Return the animation counter
inline int getAniCount(void) { return mAniCount; }
//! Return the ray counter
inline int getCounterRays(void) { return mCounterRays; }
//! Return the ray shades counter
inline int getCounterShades(void) { return mCounterShades; }
//! Return the scene intersection counter
inline int getCounterSceneInter(void) { return mCounterSceneInter; }
//! Check if existing frames should be skipped
inline int getFrameSkip( void ) { return mFrameSkip; }
//! Return the outfilename
inline string getOutFilename(void) { return mOutFilename; }
//! get Maximum depth for BSP tree
inline int getTreeMaxDepth( void ) { return mTreeMaxDepth; }
//! get Maxmimum nr of triangles per BSP tree node
inline int getTreeMaxTriangles( void ) { return mTreeMaxTriangles; }
//! get open gl attribute list
inline AttributeList* getOpenGlAttributes( void ) { return mpOpenGlAttr; }
//! get blender output attribute list
inline AttributeList* getBlenderAttributes( void ) { return mpBlenderAttr; }
//! is the test sphere enabled?
inline bool getTestSphereEnabled( void ) { return mTestSphereEnabled; }
//! get the center of the test sphere
inline ntlVec3Gfx getTestSphereCenter( void ) { return mTestSphereCenter; }
//! get the radius of the test sphere
inline gfxReal getTestSphereRadius( void) { return mTestSphereRadius; }
//! get the materialname of the test sphere
inline char *getTestSphereMaterialName( void) { return mTestSphereMaterialName; }
//! get the debug pixel coordinate
inline int getDebugPixelX( void ) { return mDebugPixelX; }
//! get the debug pixel coordinate
inline int getDebugPixelY( void ) { return mDebugPixelY; }
//! get test mode flag
inline bool getTestMode( void ) { return mTestMode; }
//! set single frame mode flag
inline bool getSingleFrameMode() { return mSingleFrameMode; };
//! set single frame mode filename
inline string getSingleFrameFilename() { return mSingleFrameFilename; };
private:
/*! Scene storage (dynamic rendering scene) */
ntlScene *mpRenderScene;
/*! Scene storage (static sim scene, inited only once) */
ntlScene *mpSimScene;
//! List of light objects
vector<ntlLightObject*> *mpLightList;
//! List of surface properties
vector<ntlMaterial*> *mpMaterials;
/*! storage for simulations */
vector<SimulationObject*> *mpSims;
//! resolution of the picture
unsigned int mResX, mResY;
//! Anti-Aliasing depth
int mAADepth;
//! max color value for ppm
unsigned int mMaxColVal;
/* Maximal ray recursion depth */
int mRayMaxDepth;
//! The eye point
ntlVec3Gfx mvEye;
//! The look at point
ntlVec3Gfx mvLookat;
//! The up vector
ntlVec3Gfx mvUpvec;
//! The image aspect = Xres/Yres
float mAspect;
//! The horizontal field of view
float mFovy;
//! The background color
ntlColor mcBackgr;
//! The ambient color
ntlColor mcAmbientLight;
//! how much debug output is needed? off by default
char mDebugOut;
//! animation properties, start time
int mAniStart;
//! animation properties, number of frames to render
int mAniFrames;
//! animation status, current frame number
int mAniCount;
/*! Should existing picture frames be skipped? */
int mFrameSkip;
//! count the total number of rays created (also used for ray ID's)
int mCounterRays;
//! count the total number of rays shaded
int mCounterShades;
//! count the total number of scene intersections
int mCounterSceneInter;
/*! filename of output pictures (without suffix or numbers) */
string mOutFilename;
//! get Maximum depth for BSP tree
int mTreeMaxDepth;
//! get Maxmimum nr of triangles per BSP tree node
int mTreeMaxTriangles;
//! attribute list for opengl renderer
AttributeList *mpOpenGlAttr;
//! attribute list for blender output
AttributeList *mpBlenderAttr;
//! Enable test sphere?
bool mTestSphereEnabled;
//! Center of the test sphere
ntlVec3Gfx mTestSphereCenter;
//! Radius of the test sphere
gfxReal mTestSphereRadius;
//! Materialname of the test sphere
char *mTestSphereMaterialName;
//! coordinates of the debugging pixel
int mDebugPixelX, mDebugPixelY;
//! test mode for quick rendering activated?, inited in ntl_scene::buildScene
bool mTestMode;
//! single frame flag
bool mSingleFrameMode;
//! filename for single frame mode
string mSingleFrameFilename;
/*! Two random number streams for photon generation (one for the directions, the other for russion roulette) */
//ntlRandomStream *mpRndDirections, *mpRndRoulette;
};
#endif

View File

@@ -10,6 +10,9 @@
#include <sstream>
#include "parametrizer.h"
// debug output flag
#define DEBUG_PARAMCHANNELS 0
/*! param seen debug string array */
char *ParamStrings[] = {
"RelaxTime",
@@ -19,7 +22,7 @@ char *ParamStrings[] = {
"DomainSize",
"GravityForce",
"TimeLength",
"StepTime",
"Timestep",
"Size",
"TimeFactor",
"AniFrames",
@@ -42,26 +45,25 @@ char *ParamStrings[] = {
* Default constructor
*****************************************************************************/
Parametrizer::Parametrizer( void ) :
mRelaxTime( 1.0 ), mReynolds( 0.0 ),
mViscosity( 8.94e-7 ), mcViscosity( 8.94e-7 ),
mcViscosity( 8.94e-7 ),
mSoundSpeed( 1500 ),
mDomainSize( 0.1 ), mCellSize( 0.01 ),
mGravity(0.0, 0.0, 0.0), mcGravity( ParamVec(0.0) ),
mLatticeGravity(0.0, 0.0, 0.0),
mStepTime(0.0001), mDesiredStepTime(-1.0),
mMaxStepTime(-1.0),
mMinStepTime(-1.0),
mcGravity( ParamVec(0.0) ),
mTimestep(0.0001), mDesiredTimestep(-1.0),
mMaxTimestep(-1.0),
mMinTimestep(-1.0),
mSizex(50), mSizey(50), mSizez(50),
mTimeFactor( 1.0 ),
//mAniFrames(0),
mAniFrameTime(0.0001), mcAniFrameTime(0.0001),
mcAniFrameTime(0.0001),
mAniFrameTime(0.0001),
mTimeStepScale(1.0),
mAniStart(0.0),
mExtent(1.0, 1.0, 1.0), mSurfaceTension( 0.0 ),
mExtent(1.0, 1.0, 1.0), //mSurfaceTension( 0.0 ),
mDensity(1000.0), mGStar(0.0001), mFluidVolumeHeight(0.0),
mSimulationMaxSpeed(0.0),
mTadapMaxOmega(2.0), mTadapMaxSpeed(0.1)/*FIXME test 0.16666 */, mTadapLevels(1),
mTadapMaxOmega(2.0), mTadapMaxSpeed(0.1), mTadapLevels(1),
mFrameNum(0),
mSeenValues( 0 ), mCalculatedValues( 0 )
//mActive( false )
{
}
@@ -89,15 +91,8 @@ void Parametrizer::parseAttrList()
mSetupType = mpAttrs->readString("p_setup",mSetupType, "Parametrizer","mSetupType", false);
// real params
mRelaxTime = mpAttrs->readFloat("p_relaxtime",mRelaxTime, "Parametrizer","mRelaxTime", false);
if(getAttributeList()->exists("p_relaxtime")) seenThis( PARAM_RELAXTIME );
mReynolds = mpAttrs->readFloat("p_reynolds",mReynolds, "Parametrizer","mReynolds", false);
if(getAttributeList()->exists("p_reynolds")) seenThis( PARAM_REYNOLDS );
mViscosity = mpAttrs->readFloat("p_viscosity",mViscosity, "Parametrizer","mViscosity", false);
mcViscosity = mpAttrs->readChannelFloat("p_viscosity");
if(getAttributeList()->exists("p_viscosity")) seenThis( PARAM_VISCOSITY );
if(getAttributeList()->exists("p_viscosity")) {
mcViscosity = mpAttrs->readChannelFloat("p_viscosity"); seenThis( PARAM_VISCOSITY ); }
mSoundSpeed = mpAttrs->readFloat("p_soundspeed",mSoundSpeed, "Parametrizer","mSoundSpeed", false);
if(getAttributeList()->exists("p_soundspeed")) seenThis( PARAM_SOUNDSPEED );
@@ -105,27 +100,24 @@ void Parametrizer::parseAttrList()
mDomainSize = mpAttrs->readFloat("p_domainsize",mDomainSize, "Parametrizer","mDomainSize", false);
if(getAttributeList()->exists("p_domainsize")) seenThis( PARAM_DOMAINSIZE );
if(mDomainSize<=0.0) {
errMsg("Parametrizer::parseAttrList","Invalid real world domain size:"<<mAniFrameTime<<", resetting to 0.1");
errMsg("Parametrizer::parseAttrList","Invalid real world domain size:"<<mDomainSize<<", resetting to 0.1");
mDomainSize = 0.1;
}
mGravity = mpAttrs->readVec3d("p_gravity",mGravity, "Parametrizer","mGravity", false);
mcGravity = mpAttrs->readChannelVec3d("p_gravity");
if(getAttributeList()->exists("p_gravity")) seenThis( PARAM_GRAVITY );
if(getAttributeList()->exists("p_gravity")) { // || (!mcGravity.isInited()) ) {
mcGravity = mpAttrs->readChannelVec3d("p_gravity"); seenThis( PARAM_GRAVITY );
}
mStepTime = mpAttrs->readFloat("p_steptime",mStepTime, "Parametrizer","mStepTime", false);
mTimestep = mpAttrs->readFloat("p_steptime",mTimestep, "Parametrizer","mTimestep", false);
if(getAttributeList()->exists("p_steptime")) seenThis( PARAM_STEPTIME );
mTimeFactor = mpAttrs->readFloat("p_timefactor",mTimeFactor, "Parametrizer","mTimeFactor", false);
if(getAttributeList()->exists("p_timefactor")) seenThis( PARAM_TIMEFACTOR );
mAniFrameTime = mpAttrs->readFloat("p_aniframetime",mAniFrameTime, "Parametrizer","mAniFrameTime", false);
mcAniFrameTime = mpAttrs->readChannelFloat("p_aniframetime");
if(getAttributeList()->exists("p_aniframetime")) { seenThis( PARAM_ANIFRAMETIME ); }
if(mAniFrameTime<0.0) {
errMsg("Parametrizer::parseAttrList","Invalid frame time:"<<mAniFrameTime<<", resetting to 0.0001");
mAniFrameTime = 0.0001;
if(getAttributeList()->exists("p_aniframetime")) { //|| (!mcAniFrameTime.isInited()) ) {
mcAniFrameTime = mpAttrs->readChannelFloat("p_aniframetime");seenThis( PARAM_ANIFRAMETIME );
}
mTimeStepScale = mpAttrs->readFloat("p_timestepscale",mTimeStepScale, "Parametrizer","mTimeStepScale", false);
mAniStart = mpAttrs->readFloat("p_anistart",mAniStart, "Parametrizer","mAniStart", false);
if(getAttributeList()->exists("p_anistart")) seenThis( PARAM_ANISTART );
@@ -134,14 +126,14 @@ void Parametrizer::parseAttrList()
mAniStart = 0.0;
}
mSurfaceTension = mpAttrs->readFloat("p_surfacetension",mSurfaceTension, "Parametrizer","mSurfaceTension", false);
if(getAttributeList()->exists("p_surfacetension")) seenThis( PARAM_SURFACETENSION );
//mSurfaceTension = mpAttrs->readFloat("p_surfacetension",mSurfaceTension, "Parametrizer","mSurfaceTension", false);
//if(getAttributeList()->exists("p_surfacetension")) seenThis( PARAM_SURFACETENSION );
mDensity = mpAttrs->readFloat("p_density",mDensity, "Parametrizer","mDensity", false);
if(getAttributeList()->exists("p_density")) seenThis( PARAM_DENSITY );
mCellSize = mpAttrs->readFloat("p_cellsize",mCellSize, "Parametrizer","mCellSize", false);
if(getAttributeList()->exists("p_cellsize")) seenThis( PARAM_CELLSIZE );
ParamFloat cellSize = 0.0; // unused, deprecated
cellSize = mpAttrs->readFloat("p_cellsize",cellSize, "Parametrizer","cellSize", false);
mGStar = mpAttrs->readFloat("p_gstar",mGStar, "Parametrizer","mGStar", false);
if(getAttributeList()->exists("p_gstar")) seenThis( PARAM_GSTAR );
@@ -156,16 +148,28 @@ void Parametrizer::parseAttrList()
/******************************************************************************
*! advance to next render/output frame
*****************************************************************************/
void Parametrizer::setFrameNum(int num) {
double frametime = (double)num;
double oldval = mAniFrameTime;
mAniFrameTime = mcAniFrameTime.get(frametime);
if(mAniFrameTime<0.0) {
errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<mAniFrameTime<<" at frame "<<num<<", resetting to "<<oldval);
mAniFrameTime = oldval;
void Parametrizer::setFrameNum(int frame) {
//double oldval = mAniFrameTime;
//mAniFrameTime = mcAniFrameTime.get(frametime);
//if(mAniFrameTime<0.0) {
//errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<mAniFrameTime<<" at frame "<<frame<<", resetting to "<<oldval);
//mAniFrameTime = oldval; }
//errMsg("ChannelAnimDebug","anim: anif"<<mAniFrameTime<<" at "<<frame<<" ");
// debug getAttributeList()->find("p_aniframetime")->print();
mFrameNum = frame;
if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","setFrameNum frame-num="<<mFrameNum);
}
/*! get time of an animation frame (renderer) */
ParamFloat Parametrizer::getAniFrameTime( int frame ) {
double frametime = (double)frame;
ParamFloat anift = mcAniFrameTime.get(frametime);
if(anift<0.0) {
ParamFloat resetv = 0.;
errMsg("Parametrizer::setFrameNum","Invalid frame time:"<<anift<<" at frame "<<frame<<", resetting to "<<resetv);
anift = resetv;
}
//errMsg("ChannelAnimDebug","anim: anif"<<mAniFrameTime<<" at "<<num<<" ");
getAttributeList()->find("p_aniframetime")->print();
if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","getAniFrameTime frame="<<frame<<", frametime="<<anift<<" ");
return anift;
}
/******************************************************************************
@@ -173,8 +177,8 @@ void Parametrizer::setFrameNum(int num) {
*****************************************************************************/
ParamVec Parametrizer::calculateAddForce(ParamVec vec, string usage)
{
ParamVec ret = vec * (mStepTime*mStepTime) /mCellSize;
debMsgStd("Parametrizer::calculateVector", DM_MSG, "scaled vector = "<<ret<<" for '"<<usage<<"', org = "<<vec<<" dt="<<mStepTime ,10);
ParamVec ret = vec * (mTimestep*mTimestep) /mCellSize;
debMsgStd("Parametrizer::calculateVector", DM_MSG, "scaled vector = "<<ret<<" for '"<<usage<<"', org = "<<vec<<" dt="<<mTimestep ,10);
return ret;
}
@@ -196,109 +200,98 @@ ParamFloat Parametrizer::calculateCellSize(void)
/* simple calulation functions */
/*****************************************************************************/
/*! get omega for LBM */
//ParamFloat Parametrizer::calculateOmega( void ) { return (1.0/mRelaxTime); }
/*! get omega for LBM from channel */
ParamFloat Parametrizer::calculateOmega( ParamFloat t ) {
mViscosity = mcViscosity.get(t);
ParamFloat viscStar = calculateLatticeViscosity();
mRelaxTime = (6.0 * viscStar + 1) * 0.5;
//errMsg("ChannelAnimDebug","anim: omega"<<(1.0/mRelaxTime)<<" v"<<mViscosity<<" at "<<t<<" ");
return (1.0/mRelaxTime);
}
/*! get no. of timesteps for LBM */
//int calculateNoOfSteps( void ) {
int Parametrizer::calculateNoOfSteps( ParamFloat timelen ) {
return (int)(timelen/mStepTime);
ParamFloat Parametrizer::calculateOmega( double time ) {
ParamFloat viscStar = calculateLatticeViscosity(time);
ParamFloat relaxTime = (6.0 * viscStar + 1) * 0.5;
if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","calculateOmega viscStar="<<viscStar<<" relaxtime="<<relaxTime);
return (1.0/relaxTime);
}
/*! get external force x component */
//ParamVec Parametrizer::calculateGravity( void ) { return mLatticeGravity; }
ParamVec Parametrizer::calculateGravity( ParamFloat t ) {
mGravity = mcGravity.get(t);
ParamFloat forceFactor = (mStepTime *mStepTime)/mCellSize;
mLatticeGravity = mGravity * forceFactor;
//errMsg("ChannelAnimDebug","anim: grav"<<mLatticeGravity<<" g"<<mGravity<<" at "<<t<<" ");
return mLatticeGravity;
ParamVec Parametrizer::calculateGravity( double time ) {
ParamVec grav = mcGravity.get(time);
ParamFloat forceFactor = (mTimestep *mTimestep)/mCellSize;
ParamVec latticeGravity = grav * forceFactor;
if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","calculateGravity grav="<<grav<<" ff"<<forceFactor<<" lattGrav="<<latticeGravity);
return latticeGravity;
}
/*! calculate the lattice viscosity */
ParamFloat Parametrizer::calculateLatticeViscosity( double time ) {
// check seen values
int reqValues = PARAM_VISCOSITY | PARAM_STEPTIME;
if(!checkSeenValues( reqValues ) ){
errMsg("Parametrizer::calculateLatticeViscosity"," Missing arguments!");
}
ParamFloat viscStar = mcViscosity.get(time) * mTimestep / (mCellSize*mCellSize);
if(DEBUG_PARAMCHANNELS) errMsg("DEBUG_PARAMCHANNELS","calculateLatticeViscosity viscStar="<<viscStar);
return viscStar;
}
/*! get no of steps for the given length in seconds */
int Parametrizer::calculateStepsForSecs( ParamFloat s ) {
return (int)(s/mStepTime);
return (int)(s/mTimestep);
}
/*! get start time of animation */
int Parametrizer::calculateAniStart( void ) {
return (int)(mAniStart/mStepTime);
return (int)(mAniStart/mTimestep);
}
/*! get no of steps for a single animation frame */
int Parametrizer::calculateAniStepsPerFrame( void ) {
int Parametrizer::calculateAniStepsPerFrame(int frame) {
if(!checkSeenValues(PARAM_ANIFRAMETIME)) {
errFatal("Parametrizer::calculateAniStepsPerFrame", "Missing ani frame time argument!", SIMWORLD_INITERROR);
return 1;
}
int value = (int)(mAniFrameTime/mStepTime);
int value = (int)(getAniFrameTime(frame)/mTimestep);
if((value<0) || (value>1000000)) {
errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="<<mAniFrameTime<<") <> ani-frame-time ("<<mStepTime<<") settings, aborting...", SIMWORLD_INITERROR);
errFatal("Parametrizer::calculateAniStepsPerFrame", "Invalid step-time (="<<mAniFrameTime<<") <> ani-frame-time ("<<mTimestep<<") settings, aborting...", SIMWORLD_INITERROR);
return 1;
}
return value;
}
/*! get no. of timesteps for LBM */
int Parametrizer::calculateNoOfSteps( ParamFloat timelen ) {
return (int)(timelen/mTimestep);
}
/*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */
ParamVec Parametrizer::calculateExtent( void ) {
return mExtent;
}
/*! get (scaled) surface tension */
ParamFloat Parametrizer::calculateSurfaceTension( void ) {
return mSurfaceTension;
//ParamFloat Parametrizer::calculateSurfaceTension( void ) { return mSurfaceTension; }
/*! get the length of a single time step */
// explicity scaled by time factor for refinement
ParamFloat Parametrizer::getTimestep( void ) {
return mTimestep;
}
/*! calculate lattice velocity from real world value [m/s] */
ParamVec Parametrizer::calculateLattVelocityFromRw( ParamVec ivel ) {
ParamVec velvec = ivel;
velvec /= mCellSize;
velvec *= mStepTime;
velvec *= mTimestep;
return velvec;
}
/*! calculate real world [m/s] velocity from lattice value */
ParamVec Parametrizer::calculateRwVelocityFromLatt( ParamVec ivel ) {
ParamVec velvec = ivel;
velvec *= mCellSize;
velvec /= mStepTime;
velvec /= mTimestep;
return velvec;
}
/*! get the length of a single time step */
// explicity scaled by time factor for refinement
// testing purposes (e.g. fsgr solver)
// not working... done manually in solver
ParamFloat Parametrizer::getStepTime( void ) {
//return mTimeFactor * mStepTime;
return mStepTime;
}
/*! calculate the lattice viscosity */
ParamFloat Parametrizer::calculateLatticeViscosity( void ) {
// check seen values
int reqValues = PARAM_VISCOSITY | PARAM_STEPTIME; // |PARAM_CELLSIZE | PARAM_GRAVITY;
if(!checkSeenValues( reqValues ) ){
errMsg("Parametrizer::calculateLatticeViscosity"," Missing arguments!");
}
ParamFloat viscStar = mViscosity * mStepTime / (mCellSize*mCellSize);
return viscStar;
}
/*! get g star value with fhvol calculations */
ParamFloat Parametrizer::getCurrentGStar( void ) {
ParamFloat gStar = mGStar; // check? TODO get from mNormalizedGStar?
if(mFluidVolumeHeight>0.0) {
gStar = mGStar/mFluidVolumeHeight;
}
if(mFluidVolumeHeight>0.0) { gStar = mGStar/mFluidVolumeHeight; }
return gStar;
}
@@ -306,18 +299,12 @@ ParamFloat Parametrizer::getCurrentGStar( void ) {
* function that tries to calculate all the missing values from the given ones
* prints errors and returns false if thats not possible
*****************************************************************************/
bool Parametrizer::calculateAllMissingValues( bool silent )
bool Parametrizer::calculateAllMissingValues( double time, bool silent )
{
bool init = false; // did we init correctly?
int valuesChecked = 0;
int reqValues;
// are we active anyway?
//if(!mActive) {
// not active - so there's nothing to calculate
//return true;
//}
// we always need the sizes
reqValues = PARAM_SIZE;
valuesChecked |= reqValues;
@@ -326,10 +313,6 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
return false;
}
if(checkSeenValues(PARAM_CELLSIZE)) {
errMsg("Parametrizer::calculateAllMissingValues"," Dont explicitly set cell size (use domain size instead)");
return false;
}
if(!checkSeenValues(PARAM_DOMAINSIZE)) {
errMsg("Parametrizer::calculateAllMissingValues"," Missing domain size argument!");
return false;
@@ -343,7 +326,6 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
/* Carolin init , see DA for details */
ParamFloat maxDeltaT = 0.0;
ParamFloat maxSpeed = 1.0/6.0; // for rough reynolds approx
/* normalized gstar init */
reqValues = PARAM_NORMALIZEDGSTAR;
@@ -355,7 +337,13 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
errMsg("Parametrizer::calculateAllMissingValues","Invalid NormGstar: "<<mNormalizedGStar<<"... resetting to "<<normgstarReset);
mNormalizedGStar = normgstarReset;
}
mGStar = mNormalizedGStar/maxsize;
// TODO FIXME add use testdata check!
mGStar = mNormalizedGStar/mSizez;
errMsg("Warning","Used z-dir for gstar!");
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," g star set to "<<mGStar<<" from normalizedGStar="<<mNormalizedGStar ,1);
seenThis(PARAM_GSTAR);
}
@@ -370,20 +358,19 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
mGStar = gstarReset;
}
ParamFloat gStar = getCurrentGStar();
ParamFloat gStar = getCurrentGStar(); // mGStar
if(mFluidVolumeHeight>0.0) {
debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," height"<<mFluidVolumeHeight<<" resGStar = "<<gStar, 10);
}
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," g star = "<<gStar, 10);
//if(!checkSeenValues(PARAM_GRAVITY)) { errMsg("Parametrizer::calculateAllMissingValues","Setup requires gravity force!"); goto failure; }
ParamFloat forceStrength = 0.0;
if(checkSeenValues(PARAM_GRAVITY)) { forceStrength = norm(mGravity); }
//if(forceStrength<=0) { errMsg("Parametrizer::calculateAllMissingValues"," Init failed - forceStrength = "<<forceStrength); goto failure; }
//if(checkSeenValues(PARAM_GRAVITY)) { forceStrength = norm( calculateGravity(time) ); }
if(checkSeenValues(PARAM_GRAVITY)) { forceStrength = norm( mcGravity.get(time) ); }
// determine max. delta density per timestep trough gravity force
if(forceStrength>0.0) {
maxDeltaT = sqrt( gStar*mCellSize/forceStrength );
maxDeltaT = sqrt( gStar*mCellSize *mTimeStepScale /forceStrength );
} else {
// use 1 lbm setp = 1 anim step as max
maxDeltaT = mAniFrameTime;
@@ -391,22 +378,22 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," targeted step time = "<<maxDeltaT, 10);
ParamFloat viscStarFac = mViscosity/(mCellSize*mCellSize);
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," viscStarFac = "<<viscStarFac, 10);
//ParamFloat viscStarFac = mViscosity/(mCellSize*mCellSize);
//if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," viscStarFac = "<<viscStarFac<<" viscosity:"<<mViscosity, 10);
// time step adaptivty, only for caro with max sim speed
ParamFloat setDeltaT = maxDeltaT;
if(mDesiredStepTime>0.0) {
if(mDesiredTimestep>0.0) {
// explicitly set step time according to max velocity in sim
setDeltaT = mDesiredStepTime;
mDesiredStepTime = -1.0;
setDeltaT = mDesiredTimestep;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," desired step time = "<<setDeltaT, 10);
mDesiredTimestep = -1.0;
} else {
// just use max delta t as current
}
// and once for init determine minimal delta t by omega max.
if((mMinStepTime<0.0) || (mMaxStepTime<0.0)) {
if((mMinTimestep<0.0) || (mMaxTimestep<0.0)) {
ParamFloat minDeltaT;
ParamFloat maxOmega = mTadapMaxOmega;
ParamFloat minRelaxTime = 1.0/maxOmega;
@@ -417,8 +404,8 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
maxOmega = 1.0/minRelaxTime;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," maxOmega="<<maxOmega<<" minRelaxTime="<<minRelaxTime<<" levels="<<mTadapLevels, 1);
// visc-star for min relax time to calculate min delta ta
if(mViscosity>0.0) {
minDeltaT = ((2.0*minRelaxTime-1.0)/6.0) * mCellSize * mCellSize / mViscosity;
if(mcViscosity.get(time)>0.0) {
minDeltaT = ((2.0*minRelaxTime-1.0)/6.0) * mCellSize * mCellSize / mcViscosity.get(time);
} else {
// visc=0, this is not physical, but might happen
minDeltaT = 0.0;
@@ -426,63 +413,38 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," min delta t = "<<minDeltaT<<" , range = " << (maxDeltaT/minDeltaT) ,1);
// sim speed + accel shouldnt exceed 0.1?
mMaxStepTime = maxDeltaT;
mMinStepTime = minDeltaT;
mMaxTimestep = maxDeltaT;
mMinTimestep = minDeltaT;
// only use once...
}
setStepTime( setDeltaT ); // set mStepTime to new value
//ParamFloat viscStar = mViscosity * mStepTime / (mCellSize*mCellSize);
ParamFloat viscStar = calculateLatticeViscosity();
mRelaxTime = (6.0 * viscStar + 1) * 0.5;
setTimestep( setDeltaT ); // set mTimestep to new value
init = true;
}
// finish init
if(init) {
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," omega = "<<calculateOmega(0.0)<<", relax time = "<<mRelaxTime<<", delt="<<mStepTime,1);
//debMsgStd("Parametrizer::calculateAllMissingValues: lbm steps = "<<calculateNoOfSteps()<<" ",1);
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," omega = "<<calculateOmega(0.0)<<", delt="<<mTimestep,1);
if(checkSeenValues(PARAM_GRAVITY)) {
ParamFloat forceFactor = (mStepTime *mStepTime)/mCellSize;
//if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," given force = "<<PRINT_NTLVEC(mGravity),1);
mLatticeGravity = mGravity * forceFactor;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," gravity force = "<<PRINT_NTLVEC(mGravity)<<", scaled with "<<forceFactor<<" to "<<mLatticeGravity,1);
}
if((checkSeenValues(PARAM_SURFACETENSION))&&(mSurfaceTension>0.0)) {
ParamFloat massDelta = 1.0;
ParamFloat densityStar = 1.0;
massDelta = mDensity / densityStar *mCellSize*mCellSize*mCellSize;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," massDelta = "<<massDelta, 10);
mSurfaceTension = mSurfaceTension*mStepTime*mStepTime/massDelta;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," surface tension = "<<mSurfaceTension<<" ",1);
ParamFloat forceFactor = (mTimestep *mTimestep)/mCellSize; // only used for printing...
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," gravity force = "<<PRINT_NTLVEC(mcGravity.get(time))<<", scaled with "<<forceFactor<<" to "<<calculateGravity(time),1);
}
mExtent = ParamVec( mCellSize*mSizex, mCellSize*mSizey, mCellSize*mSizez );
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m ",1);
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m , gs:"<<PRINT_VEC(mSizex,mSizey,mSizez)<<" cs:"<<mCellSize,1);
if(!checkSeenValues(PARAM_ANIFRAMETIME)) {
errFatal("Parametrizer::calculateAllMissingValues"," Warning no ani frame time given!", SIMWORLD_INITERROR);
mAniFrameTime = mStepTime;
mAniFrameTime = mTimestep;
}
//mAniFrameTime = mAniFrames * mStepTime;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani frame steps = "<<calculateAniStepsPerFrame()<<" ", 1);
//mAniFrameTime = mAniFrames * mTimestep;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani frame steps = "<<calculateAniStepsPerFrame(mFrameNum)<<" for frame "<<mFrameNum, 1);
if((checkSeenValues(PARAM_ANISTART))&&(calculateAniStart()>0)) {
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani start steps = "<<calculateAniStart()<<" ",1);
}
// calculate reynolds number
if(mViscosity>0.0) {
ParamFloat reynoldsApprox = -1.0;
ParamFloat gridSpeed = (maxSpeed*mCellSize/mStepTime);
reynoldsApprox = (mDomainSize*gridSpeed) / mViscosity;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," reynolds number (D="<<mDomainSize<<", assuming V="<<gridSpeed<<")= "<<reynoldsApprox<<" ", 1);
}
if(!SIMWORLD_OK()) return false;
// everything ok
return true;
@@ -510,7 +472,59 @@ bool Parametrizer::calculateAllMissingValues( bool silent )
// OLD interface stuff
// reactivate at some point?
/*! surface tension, [kg/s^2] */
//ParamFloat mSurfaceTension;
/*! set starting time of the animation (renderer) */
//void setSurfaceTension(ParamFloat set) { mSurfaceTension = set; seenThis( PARAM_SURFACETENSION ); }
/*! get starting time of the animation (renderer) */
//ParamFloat getSurfaceTension( void ) { return mSurfaceTension; }
/*if((checkSeenValues(PARAM_SURFACETENSION))&&(mSurfaceTension>0.0)) {
ParamFloat massDelta = 1.0;
ParamFloat densityStar = 1.0;
massDelta = mDensity / densityStar *mCellSize*mCellSize*mCellSize;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," massDelta = "<<massDelta, 10);
mSurfaceTension = mSurfaceTension*mTimestep*mTimestep/massDelta;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," surface tension = "<<mSurfaceTension<<" ",1);
} // */
// probably just delete:
/*! reynolds number (calculated from domain length and max. speed [dimensionless] */
//ParamFloat mReynolds;
/*! set relaxation time */
//void setRelaxTime(ParamFloat set) { mRelaxTime = set; seenThis( PARAM_RELAXTIME ); }
/*! get relaxation time */
//ParamFloat getRelaxTime( void ) { return mRelaxTime; }
/*! set reynolds number */
//void setReynolds(ParamFloat set) { mReynolds = set; seenThis( PARAM_REYNOLDS ); }
/*! get reynolds number */
//ParamFloat getReynolds( void ) { return mReynolds; }
// calculate reynolds number
/*if(mViscosity>0.0) {
ParamFloat maxSpeed = 1.0/6.0; // for rough reynolds approx
ParamFloat reynoldsApprox = -1.0;
ParamFloat gridSpeed = (maxSpeed*mCellSize/mTimestep);
reynoldsApprox = (mDomainSize*gridSpeed) / mViscosity;
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," reynolds number (D="<<mDomainSize<<", assuming V="<<gridSpeed<<")= "<<reynoldsApprox<<" ", 1);
} // */
//? mRelaxTime = mpAttrs->readFloat("p_relaxtime",mRelaxTime, "Parametrizer","mRelaxTime", false);
//if(getAttributeList()->exists("p_relaxtime")) seenThis( PARAM_RELAXTIME );
//? mReynolds = mpAttrs->readFloat("p_reynolds",mReynolds, "Parametrizer","mReynolds", false);
//if(getAttributeList()->exists("p_reynolds")) seenThis( PARAM_REYNOLDS );
//mViscosity = mpAttrs->readFloat("p_viscosity",mViscosity, "Parametrizer","mViscosity", false);
//if(getAttributeList()->exists("p_viscosity") || (!mcViscosity.isInited()) ) { }
//if(getAttributeList()->exists("p_viscosity"))
//ParamFloat viscStar = calculateLatticeViscosity(time);
//RelaxTime = (6.0 * viscStar + 1) * 0.5;

View File

@@ -32,7 +32,6 @@ typedef ntlVec3d ParamVec;
#define PARAM_ANISTART (1<<12)
#define PARAM_SURFACETENSION (1<<13)
#define PARAM_DENSITY (1<<14)
#define PARAM_CELLSIZE (1<<15)
#define PARAM_GSTAR (1<<16)
#define PARAM_SIMMAXSPEED (1<<18)
#define PARAM_FLUIDVOLHEIGHT (1<<19)
@@ -58,9 +57,9 @@ class Parametrizer {
void parseAttrList( void );
/*! function that tries to calculate all the missing values from the given ones
* prints errors and returns false if thats not possible */
bool calculateAllMissingValues( bool silent = false );
bool oldCalculateAllMissingValues( void );
* prints errors and returns false if thats not possible
* currently needs time value as well */
bool calculateAllMissingValues( double time, bool silent );
/*! is the parametrizer used at all? */
bool isUsed() { return true; }
@@ -83,7 +82,9 @@ class Parametrizer {
/*! check if the calculated flags are set in the values int */
bool checkCalculatedValues(int check) { /*errorOut( " b"<<((mSeenValues&check)==check) );*/ return ((mCalculatedValues&check)==check); }
/*! advance to next render/output frame */
void setFrameNum(int num);
void setFrameNum(int frame);
ParamFloat getAniFrameTime(int frame);
ParamFloat getCurrentAniFrameTime(){ return getAniFrameTime(mFrameNum); };
/*! scale a given speed vector in m/s to lattice values
* usage string is only needed for debugging */
@@ -91,17 +92,17 @@ class Parametrizer {
/* simple calulation functions */
/*! get omega for LBM */
ParamFloat calculateOmega( ParamFloat t );
ParamFloat calculateOmega( double time );
/*! get no. of timesteps for LBM */
int calculateNoOfSteps( ParamFloat timelen );
/*! get external force x component */
ParamVec calculateGravity( ParamFloat t );
ParamVec calculateGravity( double time );
/*! get no of steps for the given length in seconds */
int calculateStepsForSecs( ParamFloat s );
/*! get no of steps for a singel animation frame */
int calculateAniStepsPerFrame(int frame);
/*! get start time of animation */
int calculateAniStart( void );
/*! get no of steps for a singel animation frame */
int calculateAniStepsPerFrame( void );
/*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */
ParamVec calculateExtent( void );
/*! get (scaled) surface tension */
@@ -111,7 +112,7 @@ class Parametrizer {
/*! calculate size of a single cell */
ParamFloat calculateCellSize(void);
/*! calculate the lattice viscosity */
ParamFloat calculateLatticeViscosity(void);
ParamFloat calculateLatticeViscosity( double time );
/*! calculate lattice velocity from real world value [m/s] */
ParamVec calculateLattVelocityFromRw( ParamVec ivel );
@@ -119,23 +120,9 @@ class Parametrizer {
ParamVec calculateRwVelocityFromLatt( ParamVec ivel );
/*! set relaxation time */
void setRelaxTime(ParamFloat set) { mRelaxTime = set; seenThis( PARAM_RELAXTIME ); }
/*! get relaxation time */
ParamFloat getRelaxTime( void ) { return mRelaxTime; }
/*! set reynolds number */
void setReynolds(ParamFloat set) { mReynolds = set; seenThis( PARAM_REYNOLDS ); }
/*! get reynolds number */
ParamFloat getReynolds( void ) { return mReynolds; }
/*! set kinematic viscosity */
void setViscosity(ParamFloat set) {
mViscosity = set; seenThis( PARAM_VISCOSITY );
mcViscosity = AnimChannel<ParamFloat>(mViscosity);
}
/*! get current kinematic viscosity (warning - this might change over time) */
ParamFloat getViscosity( void ) { return mViscosity; }
void setViscosity(ParamFloat set) { mcViscosity = AnimChannel<ParamFloat>(set); seenThis( PARAM_VISCOSITY ); }
void initViscosityChannel(vector<ParamFloat> val, vector<double> time) { mcViscosity = AnimChannel<ParamFloat>(val,time); }
/*! set speed of sound */
void setSoundSpeed(ParamFloat set) { mSoundSpeed = set; seenThis( PARAM_SOUNDSPEED ); }
@@ -143,25 +130,21 @@ class Parametrizer {
ParamFloat getSoundSpeed( void ) { return mSoundSpeed; }
/*! set the external force */
void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) {
mGravity = ParamVec(setx,sety,setz); seenThis( PARAM_GRAVITY );
mcGravity = AnimChannel<ParamVec>(mGravity);
}
void setGravity(ParamVec set) {
mGravity = set; seenThis( PARAM_GRAVITY );
mcGravity = AnimChannel<ParamVec>(mGravity);
}
void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { mcGravity = AnimChannel<ParamVec>(ParamVec(setx,sety,setz)); seenThis( PARAM_GRAVITY ); }
void setGravity(ParamVec set) { mcGravity = AnimChannel<ParamVec>(set); seenThis( PARAM_GRAVITY ); }
void initGravityChannel(vector<ParamVec> val, vector<double> time) { mcGravity = AnimChannel<ParamVec>(val,time); }
ParamVec getGravity(double time) { return mcGravity.get( time ); }
/*! set the length of a single time step */
void setStepTime(ParamFloat set) { mStepTime = set; seenThis( PARAM_STEPTIME ); }
void setTimestep(ParamFloat set) { mTimestep = set; seenThis( PARAM_STEPTIME ); }
/*! get the length of a single time step */
ParamFloat getStepTime( void);
ParamFloat getTimestep( void);
/*! set a desired step time for rescaling/adaptive timestepping */
void setDesiredStepTime(ParamFloat set) { mDesiredStepTime = set; }
void setDesiredTimestep(ParamFloat set) { mDesiredTimestep = set; }
/*! get the length of a single time step */
ParamFloat getMaxStepTime( void ) { return mMaxStepTime; }
ParamFloat getMaxTimestep( void ) { return mMaxTimestep; }
/*! get the length of a single time step */
ParamFloat getMinStepTime( void ) { return mMinStepTime; }
ParamFloat getMinTimestep( void ) { return mMinTimestep; }
/*! set the time scaling factor */
void setTimeFactor(ParamFloat set) { mTimeFactor = set; seenThis( PARAM_TIMEFACTOR ); }
@@ -173,20 +156,15 @@ class Parametrizer {
void setSize(int i,int j, int k) { mSizex = i; mSizey = j; mSizez = k; seenThis( PARAM_SIZE ); }
/*! set time of an animation frame (renderer) */
void setAniFrameTime(ParamFloat set) { mAniFrameTime = set; seenThis( PARAM_ANIFRAMETIME ); }
/*! get time of an animation frame (renderer) */
ParamFloat getAniFrameTime( void ) { return mAniFrameTime; }
//void setAniFrameTime(ParamFloat set) { mAniFrameTime = set; seenThis( PARAM_ANIFRAMETIME ); }
void setAniFrameTimeChannel(ParamFloat set) { mcAniFrameTime = AnimChannel<ParamFloat>(set); seenThis( PARAM_ANIFRAMETIME ); }
void initAniFrameTimeChannel(vector<ParamFloat> val, vector<double> time) { mcAniFrameTime = AnimChannel<ParamFloat>(val,time); seenThis( PARAM_ANIFRAMETIME ); }
/*! set starting time of the animation (renderer) */
void setAniStart(ParamFloat set) { mAniStart = set; seenThis( PARAM_ANISTART ); }
/*! get starting time of the animation (renderer) */
ParamFloat getAniStart( void ) { return mAniStart; }
/*! set starting time of the animation (renderer) */
void setSurfaceTension(ParamFloat set) { mSurfaceTension = set; seenThis( PARAM_SURFACETENSION ); }
/*! get starting time of the animation (renderer) */
ParamFloat getSurfaceTension( void ) { return mSurfaceTension; }
/*! set fluid density */
void setDensity(ParamFloat set) { mDensity = set; seenThis( PARAM_DENSITY ); }
/*! get fluid density */
@@ -213,8 +191,8 @@ class Parametrizer {
/*! get the size of a single lbm cell */
ParamFloat getDomainSize( void ) { return mDomainSize; }
/*! set the size of a single lbm cell */
void setCellSize(ParamFloat set) { mCellSize = set; seenThis( PARAM_CELLSIZE ); }
/*! set the size of a single lbm cell (dont use, normally set by domainsize and resolution) */
void setCellSize(ParamFloat set) { mCellSize = set; }
/*! get the size of a single lbm cell */
ParamFloat getCellSize( void ) { return mCellSize; }
@@ -246,9 +224,6 @@ class Parametrizer {
/*! get maximum allowed omega for time adaptivity */
int getTadapLevels( void ) { return mTadapLevels; }
/*! get current gravity value (warning this might change over time!) */
ParamVec getGravity( void ) { return mGravity; }
/*! set */
// void set(ParamFloat set) { m = set; seenThis( PARAM_ ); }
/*! get */
@@ -258,15 +233,7 @@ class Parametrizer {
private:
/*! relaxation time [s] */
ParamFloat mRelaxTime;
/*! reynolds number (calculated from domain length and max. speed [dimensionless] */
ParamFloat mReynolds;
/*! kinematic viscosity of the fluid [m^2/s] */
ParamFloat mViscosity;
/*! animated channel */
AnimChannel<ParamFloat> mcViscosity;
/*! speed of sound of the fluid [m/s] */
@@ -282,18 +249,14 @@ class Parametrizer {
ParamFloat mTimeStep;
/*! external force as acceleration [m/s^2] */
ParamVec mGravity;
AnimChannel<ParamVec> mcGravity;
/*! force converted to lattice units (returned by calc gravity) */
ParamVec mLatticeGravity;
/*! length of one time step in the simulation */
ParamFloat mStepTime;
ParamFloat mTimestep;
/*! desired step time for rescaling/adaptive timestepping, only regarded if >0.0, reset after usage */
ParamFloat mDesiredStepTime;
ParamFloat mDesiredTimestep;
/*! minimal and maximal step times for current setup */
ParamFloat mMaxStepTime, mMinStepTime;
ParamFloat mMaxTimestep, mMinTimestep;
/*! domain resoultion, the same values as in lbmsolver */
int mSizex, mSizey, mSizez;
@@ -302,9 +265,11 @@ class Parametrizer {
ParamFloat mTimeFactor;
/*! for renderer - length of an animation step [s] */
ParamFloat mAniFrameTime;
/*! animated channel */
AnimChannel<ParamFloat> mcAniFrameTime;
/*! current value for next frame */
ParamFloat mAniFrameTime;
/*! time step scaling factor for testing/debugging */
ParamFloat mTimeStepScale;
/*! for renderer - start time of the animation [s] */
ParamFloat mAniStart;
@@ -312,9 +277,6 @@ class Parametrizer {
/*! extent of the domain in meters */
ParamVec mExtent;
/*! surface tension, [kg/s^2] */
ParamFloat mSurfaceTension;
/*! fluid density [kg/m^3], default 1.0 g/cm^3 */
ParamFloat mDensity;
@@ -334,6 +296,8 @@ class Parametrizer {
/*! no. of levels for max omega (set by fsgr, not in cfg file) */
int mTadapLevels;
/*! remember current frame number */
int mFrameNum;
/*! values that are seen for this simulation */
int mSeenValues;
@@ -341,9 +305,6 @@ class Parametrizer {
/*! values that are calculated from the seen ones for this simulation */
int mCalculatedValues;
/*! is the parametrizer active? */
//bool mActive;
/*! pointer to the attribute list */
AttributeList *mpAttrs;
};

View File

@@ -15,7 +15,9 @@
#include "particletracer.h"
#include "ntl_matrices.h"
#include "ntl_ray.h"
#include "ntl_scene.h"
#include "ntl_matrices.h"
#include <zlib.h>
@@ -24,17 +26,33 @@
*****************************************************************************/
ParticleTracer::ParticleTracer() :
ntlGeometryObject(),
mParts(1),
mNumParticles(0), mTrailLength(1), mTrailInterval(1),mTrailIntervalCounter(0),
mPartSize(0.01), mTrailScale(1.0),
mParts(),
//mTrailLength(1), mTrailInterval(1),mTrailIntervalCounter(0),
mPartSize(0.01),
mStart(-1.0), mEnd(1.0),
mSimStart(-1.0), mSimEnd(1.0),
mPartScale(1.0) , mPartHeadDist( 0.5 ), mPartTailDist( -4.5 ), mPartSegments( 4 ),
mValueScale(0),
mValueCutoffTop(0.0), mValueCutoffBottom(0.0)
mValueCutoffTop(0.0), mValueCutoffBottom(0.0),
mDumpParts(0), mShowOnly(0), mpTrafo(NULL)
{
// check env var
#ifdef ELBEEM_PLUGIN
mDumpParts=1; // default on
#endif // ELBEEM_PLUGIN
if(getenv("ELBEEM_DUMPPARTICLE")) { // DEBUG!
int set = atoi( getenv("ELBEEM_DUMPPARTICLE") );
if((set>=0)&&(set!=mDumpParts)) {
mDumpParts=set;
debMsgStd("ParticleTracer::notifyOfDump",DM_NOTIFY,"Using envvar ELBEEM_DUMPPARTICLE to set mDumpParts to "<<set<<","<<mDumpParts,8);
}
}
};
ParticleTracer::~ParticleTracer() {
debMsgStd("ParticleTracer::~ParticleTracer",DM_MSG,"destroyed",10);
}
/*****************************************************************************/
//! parse settings from attributes (dont use own list!)
/*****************************************************************************/
@@ -42,6 +60,9 @@ void ParticleTracer::parseAttrList(AttributeList *att)
{
AttributeList *tempAtt = mpAttrs;
mpAttrs = att;
int mNumParticles =0; // UNUSED
int mTrailLength = 0; // UNUSED
int mTrailInterval= 0; // UNUSED
mNumParticles = mpAttrs->readInt("particles",mNumParticles, "ParticleTracer","mNumParticles", false);
mTrailLength = mpAttrs->readInt("traillength",mTrailLength, "ParticleTracer","mTrailLength", false);
mTrailInterval= mpAttrs->readInt("trailinterval",mTrailInterval, "ParticleTracer","mTrailInterval", false);
@@ -54,17 +75,18 @@ void ParticleTracer::parseAttrList(AttributeList *att)
mValueCutoffTop = mpAttrs->readFloat("part_valcutofftop",mValueCutoffTop, "ParticleTracer","mValueCutoffTop", false);
mValueCutoffBottom = mpAttrs->readFloat("part_valcutoffbottom",mValueCutoffBottom, "ParticleTracer","mValueCutoffBottom", false);
mTrailScale = mpAttrs->readFloat("trail_scale",mTrailScale, "ParticleTracer","mTrailScale", false);
mDumpParts = mpAttrs->readInt ("part_dump",mDumpParts, "ParticleTracer","mDumpParts", false);
mShowOnly = mpAttrs->readInt ("part_showonly",mShowOnly, "ParticleTracer","mShowOnly", false);
string matPart;
matPart = mpAttrs->readString("material_part", "default", "ParticleTracer","material", false);
setMaterialName( matPart );
// trail length has to be at least one, if anything should be displayed
if((mNumParticles>0)&&(mTrailLength<2)) mTrailLength = 2;
//if((mNumParticles>0)&&(mTrailLength<2)) mTrailLength = 2;
// restore old list
mpAttrs = tempAtt;
mParts.resize(mTrailLength*mTrailInterval);
//mParts.resize(mTrailLength*mTrailInterval);
}
/******************************************************************************
@@ -74,37 +96,66 @@ void ParticleTracer::draw()
{
}
/******************************************************************************
* init trafo matrix
*****************************************************************************/
void ParticleTracer::initTrafoMatrix() {
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;
if(!mpTrafo) mpTrafo = new ntlMat4Gfx(0.0);
mpTrafo->initId();
for(int i=0; i<3; i++) { mpTrafo->value[i][i] = scale[i]; }
for(int i=0; i<3; i++) { mpTrafo->value[i][3] = trans[i]; }
}
/******************************************************************************
* set the number of timesteps to trace
* adapt time step by rescaling velocities
*****************************************************************************/
void ParticleTracer::setTimesteps(int steps)
{
steps=0; // remove warning...
void ParticleTracer::adaptPartTimestep(float factor) {
for(size_t i=0; i<mParts.size(); i++) {
mParts[i].setVel( mParts[i].getVel() * factor );
}
}
/******************************************************************************
* add a particle at this position
*****************************************************************************/
void ParticleTracer::addParticle(double x, double y, double z)
void ParticleTracer::addParticle(float x, float y, float z)
{
ntlVec3Gfx p(x,y,z);
ParticleObject part( p );
//mParts[0].push_back( part );
//mParts.push_back( part );
// TODO handle other arrays?
//part.setActive( false );
for(size_t l=0; l<mParts.size(); l++) {
mParts.push_back( part );
//for(size_t l=0; l<mParts.size(); l++) {
// add deactivated particles to other arrays
mParts[l].push_back( part );
// deactivate further particles
if(l>1) {
//if(l>1) {
//mParts[l][ mParts.size()-1 ].setActive( false );
}
}
//}
//}
}
void ParticleTracer::cleanup() {
// cleanup
int last = (int)mParts.size()-1;
//for(vector<ParticleObject>::iterator pit= getParticlesBegin();pit!= getParticlesEnd(); pit++) {
for(int i=0; i<=last; i++) {
if( mParts[i].getActive()==false ) {
ParticleObject *p = &mParts[i];
ParticleObject *p2 = &mParts[last];
*p = *p2; last--; mParts.pop_back();
}
}
}
/******************************************************************************
* save particle positions before adding a new timestep
@@ -114,6 +165,7 @@ void ParticleTracer::addParticle(double x, double y, double z)
void ParticleTracer::savePreviousPositions()
{
//debugOut(" PARTS SIZE "<<mParts.size() ,10);
/*
if(mTrailIntervalCounter==0) {
//errMsg("spp"," PARTS SIZE "<<mParts.size() );
for(size_t l=mParts.size()-1; l>0; l--) {
@@ -131,9 +183,65 @@ void ParticleTracer::savePreviousPositions()
}
mTrailIntervalCounter++;
if(mTrailIntervalCounter>=mTrailInterval) mTrailIntervalCounter = 0;
UNUSED!? */
}
/*! dump particles if desired */
void ParticleTracer::notifyOfDump(int frameNr,char *frameNrStr,string outfilename) {
debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"obj:"<<this->getName()<<" frame:"<<frameNrStr, 10); // DEBUG
if(mDumpParts>0) {
// dump to binary file
std::ostringstream boutfilename("");
//boutfilename << ecrpath.str() << glob->getOutFilename() <<"_"<< this->getName() <<"_" << frameNrStr << ".obj";
//boutfilename << outfilename <<"_particles_"<< this->getName() <<"_" << frameNrStr<< ".gz";
boutfilename << outfilename <<"_particles_" << frameNrStr<< ".gz";
debMsgStd("ParticleTracer::notifyOfDump",DM_MSG,"B-Dumping: "<< this->getName()
<<", particles:"<<mParts.size()<<" "<< " to "<<boutfilename.str()<<" #"<<frameNr , 7);
// 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; }
if(mParts[i].getLifeTime()<30) { continue; } //? CHECK
ParticleObject *p = &mParts[i];
int type = p->getType();
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;
}
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?
}
/******************************************************************************
@@ -143,45 +251,71 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles,
vector<ntlVec3Gfx> *vertices,
vector<ntlVec3Gfx> *normals, int objectId )
{
#ifdef ELBEEM_BLENDER
#ifdef ELBEEM_PLUGIN
// suppress warnings...
vertices = NULL; triangles = NULL;
normals = NULL; objectId = 0;
#else // ELBEEM_BLENDER
#else // ELBEEM_PLUGIN
// 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;
gfxReal partNormSize = 0.01 * mPartScale;
ntlVec3Gfx pScale = 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])
);
if(debugParts) errMsg("DebugParts"," geo:"<< mSimStart<<","<<mEnd<<"; sim:"<<mSimStart<<","<<mSimEnd<<"; S "<<pScale );
ntlVec3Gfx org = mStart;
int segments = mPartSegments;
int lnewst = mTrailLength-1;
int loldst = mTrailLength-2;
//int lnewst = mTrailLength-1;
// TODO get rid of mPart[X] array
//? int loldst = mTrailLength-2;
// trails gehen nicht so richtig mit der
// richtung der partikel...
for(size_t i=0; i<mParts[lnewst].size(); i++) {
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;
for(size_t i=0; i<mParts.size(); i++) {
//mParts[0][i].setActive(true);
ParticleObject *p = &mParts[i];
if( mParts[lnewst][i].getActive()==false ) continue;
if( mParts[loldst][i].getActive()==false ) continue;
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;
}
} else {
// by default dont display inter
if(type&PART_INTER) continue;
}
ntlVec3Gfx pnew = mParts[lnewst][i].getPos();
ntlVec3Gfx pold = mParts[loldst][i].getPos();
ntlVec3Gfx pdir = pnew - pold;
ntlVec3Gfx pnew = p->getPos();
if(type&PART_FLOAT) { // WARNING same handling for dump!
// add one gridcell offset
//pnew[2] += 1.0;
}
ntlVec3Gfx pdir = p->getVel();
gfxReal plen = normalize( pdir );
if( plen < 1e-05) pdir = ntlVec3Gfx(-1.0 ,0.0 ,0.0);
ntlVec3Gfx p = org + pnew*pScale;
ntlVec3Gfx pos = (*mpTrafo) * pnew;
//ntlVec3Gfx pos = pnew; // T
//pos[0] = pos[0]*scale[0]+trans[0]; // T
//pos[1] = pos[1]*scale[1]+trans[1]; // T
//pos[2] = pos[2]*scale[2]+trans[2]; // T
gfxReal partsize = 0.0;
if(debugParts) errMsg("DebugParts"," i"<<i<<" new"<<pnew<<" old"<<pold );
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) {
@@ -194,6 +328,8 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles,
} else {
partsize = mPartScale; // 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 );
@@ -207,9 +343,9 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles,
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];
//? cvmat.value[l][0] = cv1[l];
//? cvmat.value[l][1] = cv2[l];
//? cvmat.value[l][2] = cv3[l];
}
pstart = (cvmat * pstart);
pend = (cvmat * pend);
@@ -231,10 +367,10 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles,
p1 = (cvmat * p1);
p2 = (cvmat * p2);
sceneAddTriangle( p+pstart, p+p1, p+p2,
ns,n1,n2, ntlVec3Gfx(0.0), 1 );
sceneAddTriangle( p+pend , p+p2, p+p1,
ns,n2,n1, ntlVec3Gfx(0.0), 1 );
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;
@@ -244,31 +380,7 @@ void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles,
//} // trail
return; // DEBUG
// add trails
//double tScale = 0.01 * mPartScale * mTrailScale;
double trails = 0.01 * mPartScale * mTrailScale;
//for(int l=0; l<mParts.size()-1; l++) {
for(int l=0; l<mTrailLength-2; l++) {
for(size_t i=0; i<mParts[0].size(); i++) {
int tl1 = l*mTrailInterval;
int tl2 = (l+1)*mTrailInterval;
if( mParts[tl1][i].getActive()==false ) continue;
if( mParts[tl2][i].getActive()==false ) continue;
ntlVec3Gfx p1 = org+mParts[tl1][i].getPos()*pScale;
ntlVec3Gfx p2 = org+mParts[tl2][i].getPos()*pScale;
ntlVec3Gfx n = ntlVec3Gfx(0,0,-1);
sceneAddTriangle( p1+ntlVec3Gfx(0,trails,0), p1+ntlVec3Gfx(0,-trails,0), p2,
n,n,n, ntlVec3Gfx(0.0), 1 );
sceneAddTriangle( p2, p1+ntlVec3Gfx(0,-trails,0), p1+ntlVec3Gfx(0,trails,0),
n,n,n, ntlVec3Gfx(0.0), 1 );
tris += 2;
}
}
debugOut("ParticleTracer::getTriangles "<<mName<<" : Triangulated "<< (mParts[0].size()) <<" particles (triangles: "<<tris<<") ", 10);
//debugOut(" s"<<mStart<<" e"<<mEnd<<" ss"<<mSimStart<<" se"<<mSimEnd , 10);
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
}

View File

@@ -9,7 +9,18 @@
#ifndef NTL_PARTICLETRACER_H
#include "ntl_geometryobject.h"
template<class Scalar> class ntlMatrix4x4;
// particle types
#define PART_BUBBLE (1<< 1)
#define PART_DROP (1<< 2)
#define PART_INTER (1<< 3)
#define PART_FLOAT (1<< 4)
// particle state
#define PART_IN (1<< 8)
#define PART_OUT (1<< 9)
#define PART_INACTIVE (1<<10)
//! A single particle
class ParticleObject
@@ -17,24 +28,26 @@ class ParticleObject
public:
//! Standard constructor
inline ParticleObject(ntlVec3Gfx mp) :
mPos(mp),mVel(0.0), mStatus(0), mActive( true ) { };
mPos(mp),mVel(0.0), mSize(1.0), mStatus(0),mLifeTime(0) { };
//! Copy constructor
inline ParticleObject(const ParticleObject &a) :
mPos(a.mPos), mVel(a.mVel),
mStatus(a.mStatus), mActive(a.mActive) { };
mPos(a.mPos), mVel(a.mVel), mSize(a.mSize),
mStatus(a.mStatus),
mLifeTime(a.mLifeTime) { };
//! Destructor
inline ~ParticleObject() { /* empty */ };
//! add vector to position
inline void advance(double vx, double vy, double vz) {
inline void advance(float vx, float vy, float vz) {
mPos[0] += vx; mPos[1] += vy; mPos[2] += vz; }
//! advance with own velocity
inline void advanceVel() { mPos += mVel; }
//! add acceleration to velocity
inline void addToVel(ntlVec3Gfx acc) { mVel += acc; }
//! get vector to position
//! get/set vector to position
inline ntlVec3Gfx getPos() { return mPos; }
inline void setPos(ntlVec3Gfx set) { mPos=set; }
//! set velocity
inline void setVel(ntlVec3Gfx set) { mVel = set; }
//! set velocity
@@ -42,14 +55,31 @@ class ParticleObject
//! get velocity
inline ntlVec3Gfx getVel() { return mVel; }
//! get/set size value
inline gfxReal getSize() { return mSize; }
inline void setSize(gfxReal set) { mSize=set; }
//! get whole flags
inline int getFlags() const { return mStatus; }
//! get status (higher byte)
inline int getStatus() const { return (mStatus&0xFF00); }
//! set status (higher byte)
inline void setStatus(int set) { mStatus = set|(mStatus&0x00FF); }
//! get type (lower byte)
inline int getType() const { return (mStatus&0x00FF); }
//! set type (lower byte)
inline void setType(int set) { mStatus = set|(mStatus&0xFF00); }
//! get active flag
inline bool getActive() { return mActive; }
inline bool getActive() const { return ((mStatus&PART_INACTIVE)==0); }
//! set active flag
inline void setActive(bool set) { mActive = set; }
//! get status int
inline int getStatus() { return mStatus; }
//! setstatus int
inline void setStatus(int set) { mStatus = set; }
inline void setActive(bool set) {
if(set) mStatus &= (~PART_INACTIVE);
else mStatus |= PART_INACTIVE;
}
//! get/set lifetime
inline int getLifeTime() const { return mLifeTime; }
//! set type (lower byte)
inline void setLifeTime(int set) { mLifeTime = set; }
protected:
@@ -57,11 +87,12 @@ class ParticleObject
ntlVec3Gfx mPos;
/*! the particle velocity */
ntlVec3Gfx mVel;
/*! size / mass of particle */
gfxReal mSize;
/*! particle status */
int mStatus;
/*! particle active? */
bool mActive;
/*! count survived time steps */
int mLifeTime;
};
@@ -73,10 +104,10 @@ class ParticleTracer :
//! Standard constructor
ParticleTracer();
//! Destructor
~ParticleTracer() { /* empty */ };
~ParticleTracer();
//! add a particle at this position
void addParticle(double x, double y, double z);
void addParticle(float x, float y, float z);
//! save particle positions before adding a new timestep
void savePreviousPositions();
@@ -87,78 +118,60 @@ class ParticleTracer :
//! parse settings from attributes (dont use own list!)
void parseAttrList( AttributeList *att );
//! adapt time step by rescaling velocities
void adaptPartTimestep(float factor);
// access funcs
//! set the number of timesteps to trace
void setTimesteps(int steps);
//! set the number of particles
inline void setNumParticles(int set) { mNumParticles = set; }
//! get the number of particles
inline int getNumParticles() { return mNumParticles; }
//! set the number of timesteps to trace
inline void setTrailLength(int set) { mTrailLength = set; mParts.resize(mTrailLength*mTrailInterval); }
//! get the number of timesteps to trace
inline int getTrailLength() { return mTrailLength; }
//! set the number of timesteps between each anim step saving
inline void setTrailInterval(int set) { mTrailInterval = set; mParts.resize(mTrailLength*mTrailInterval); }
//! get the no. of particles in the current array
inline int getPartArraySize() { return mParts[0].size(); }
inline int getNumParticles() { return mParts.size(); }
//! iterate over all newest particles (for advancing positions)
inline vector<ParticleObject>::iterator getParticlesBegin() { return mParts[0].begin(); }
inline vector<ParticleObject>::iterator getParticlesBegin() { return mParts.begin(); }
//! end iterator for newest particles
inline vector<ParticleObject>::iterator getParticlesEnd() { return mParts[0].end(); }
inline vector<ParticleObject>::iterator getParticlesEnd() { return mParts.end(); }
//! end iterator for newest particles
inline ParticleObject* getLast() { return &(mParts[0][ mParts[0].size()-1 ]); }
inline ParticleObject* getLast() { return &(mParts[ mParts.size()-1 ]); }
/*! set geometry start (for renderer) */
inline void setStart(ntlVec3Gfx set) { mStart = set; }
inline void setStart(ntlVec3Gfx set) { mStart = set; initTrafoMatrix(); }
/*! set geometry end (for renderer) */
inline void setEnd(ntlVec3Gfx set) { mEnd = set; }
inline void setEnd(ntlVec3Gfx set) { mEnd = set; initTrafoMatrix(); }
/*! get values */
inline ntlVec3Gfx getStart() { return mStart; }
/*! set geometry end (for renderer) */
inline ntlVec3Gfx getEnd() { return mEnd; }
/*! set simulation domain start */
inline void setSimStart(ntlVec3Gfx set) { mSimStart = set; }
inline void setSimStart(ntlVec3Gfx set) { mSimStart = set; initTrafoMatrix(); }
/*! set simulation domain end */
inline void setSimEnd(ntlVec3Gfx set) { mSimEnd = set; }
inline void setSimEnd(ntlVec3Gfx set) { mSimEnd = set; initTrafoMatrix(); }
/*! set/get dump flag */
inline void setDumpParts(bool set) { mDumpParts = set; }
inline bool getDumpParts() { return mDumpParts; }
//! set the particle scaling factor
inline void setPartScale(double set) { mPartScale = set; }
//! set the trail scaling factor
inline void setTrailScale(double set) { mTrailScale = set; }
inline void setPartScale(float set) { mPartScale = set; }
// NTL geometry implementation
/*! Get the triangles from this object */
virtual void getTriangles( vector<ntlTriangle> *triangles,
vector<ntlVec3Gfx> *vertices,
vector<ntlVec3Gfx> *normals, int objectId );
virtual void notifyOfDump(int frameNr,char *frameNrStr,string outfilename);
// free deleted particles
void cleanup();
protected:
/*! the particle array (for multiple timesteps) */
vector< vector<ParticleObject> > mParts;
/*! desired number of particles */
int mNumParticles;
/*! number of particle positions to trace */
int mTrailLength;
/*! number of timesteps to between saving particle positions */
int mTrailInterval;
int mTrailIntervalCounter;
vector<ParticleObject> mParts;
/*! size of the particles to display */
double mPartSize;
/*! size of the particle trail */
double mTrailScale;
float mPartSize;
/*! start and end vectors for the triangulation region to create particles in */
ntlVec3Gfx mStart, mEnd;
@@ -167,18 +180,28 @@ class ParticleTracer :
ntlVec3Gfx mSimStart, mSimEnd;
/*! scaling param for particles */
double mPartScale;
float mPartScale;
/*! head and tail distance for particle shapes */
double mPartHeadDist, mPartTailDist;
float mPartHeadDist, mPartTailDist;
/*! no of segments for particle cone */
int mPartSegments;
/*! use length/absval of values to scale particles? */
int mValueScale;
/*! value length maximal cutoff value, for mValueScale==2 */
double mValueCutoffTop;
float mValueCutoffTop;
/*! value length minimal cutoff value, for mValueScale==2 */
double mValueCutoffBottom;
float mValueCutoffBottom;
/*! dump particles (or certain types of) to disk? */
int mDumpParts;
/*! show only a certain type (debugging) */
int mShowOnly;
//! transform matrix
ntlMatrix4x4<gfxReal> *mpTrafo;
/*! init sim/pos transformation */
void initTrafoMatrix();
};
#define NTL_PARTICLETRACER_H

View File

@@ -8,9 +8,13 @@
*****************************************************************************/
#include "simulation_object.h"
#include "solver_interface.h"
#include "ntl_bsptree.h"
#include "ntl_scene.h"
#include "ntl_ray.h"
#include "ntl_world.h"
#include "solver_interface.h"
#include "particletracer.h"
#include "elbeem.h"
#ifdef _WIN32
#else
@@ -32,22 +36,15 @@ SimulationObject::SimulationObject() :
mpGlob(NULL),
mPanic( false ),
mDebugType( 1 /* =FLUIDDISPNothing*/ ),
mSolverType("-"), mStepsPerFrame( 10 ),
mpLbm(NULL),
mpParam( NULL ),
mStepsPerFrame( 10 ),
mpLbm(NULL), mpParam( NULL ),
mShowSurface(true), mShowParticles(false),
mSelectedCid( NULL ),
mpElbeemSettings( NULL )
stnOld("opt"),
stnFsgr("fsgr")
{
mpParam = new Parametrizer();
for(int i=0; i<MAX_DEBDISPSET; i++) {
mDebDispSet[i].type = (i);
mDebDispSet[i].on = false;
mDebDispSet[i].scale = 1.0;
}
//for(int i=0; i<MAX_DEBDISPSET; i++) { mDebDispSet[i].type = (i); mDebDispSet[i].on = false; mDebDispSet[i].scale = 1.0; }
// reset time
mTime = 0.0;
@@ -60,9 +57,10 @@ SimulationObject::SimulationObject() :
*****************************************************************************/
SimulationObject::~SimulationObject()
{
if(mpGiTree != NULL) delete mpGiTree;
delete mpLbm;
delete mpParam;
if(mpGiTree) delete mpGiTree;
if(mpElbeemSettings) delete mpElbeemSettings;
if(mpLbm) delete mpLbm;
if(mpParam) delete mpParam;
debMsgStd("SimulationObject",DM_MSG,"El'Beem Done!\n",10);
}
@@ -77,7 +75,7 @@ void SimulationObject::initGeoTree(int id) {
return;
}
mGeoInitId = id;
ntlScene *scene = mpGlob->getScene();
ntlScene *scene = mpGlob->getSimScene();
mpGiObjects = scene->getObjects();
if(mpGiTree != NULL) delete mpGiTree;
@@ -95,6 +93,11 @@ void SimulationObject::freeGeoTree() {
// copy & remember settings for later use
void SimulationObject::copyElbeemSettings(elbeemSimulationSettings *settings) {
mpElbeemSettings = new elbeemSimulationSettings;
*mpElbeemSettings = *settings;
}
/******************************************************************************
* simluation interface: initialize simulation using the given configuration file
@@ -102,33 +105,34 @@ void SimulationObject::freeGeoTree() {
int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
{
if(!SIMWORLD_OK()) return 1;
// already inited?
if(mpLbm) return 0;
mpGlob = glob;
if(!getVisible()) {
mpAttrs->setAllUsed();
return 0;
}
//mDimension is deprecated
//mDimension, mSolverType are deprecated
string mSolverType("");
mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false );
if(mSolverType == stnFsgr) {
mpLbm = createSolver();
} else if(mSolverType == stnOld) {
errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR);
return 1;
}
//errFatal("SimulationObject::initializeLbmSimulation","Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead", SIMWORLD_INITERROR); return 1;
mpLbm = createSolver();
/* check lbm pointer */
if(mpLbm == NULL) {
errFatal("SimulationObject::initializeLbmSimulation","Unable to init dim"<<mSolverType<<" LBM solver! ", SIMWORLD_INITERROR);
errFatal("SimulationObject::initializeLbmSimulation","Unable to init LBM solver! ", SIMWORLD_INITERROR);
return 1;
}
debugOut("SimulationObject::initialized "<< mpLbm->getIdString() <<" LBM solver! ", 2);
debMsgStd("SimulationObject::initialized",DM_MSG,"IdStr:"<<mpLbm->getIdString() <<" LBM solver! ", 2);
// for non-param simulations
mpLbm->setParametrizer( mpParam );
mpParam->setAttrList( getAttributeList() );
// not needed.. done in solver_init: mpParam->setSize ...
// not needed.. done in solver_init: mpParam->setSize ... in solver_interface
mpParam->parseAttrList();
mpLbm->setAttrList( getAttributeList() );
@@ -152,6 +156,27 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
mpLbm->setGeoEnd( mGeoEnd );
mpLbm->setRenderGlobals( mpGlob );
mpLbm->setName( getName() + "_lbm" );
if(mpElbeemSettings) {
// set further settings from API struct init
mpLbm->setSmoothing(1.0 * mpElbeemSettings->surfaceSmoothing, 1.0 * mpElbeemSettings->surfaceSmoothing);
mpLbm->setSizeX(mpElbeemSettings->resolutionxyz);
mpLbm->setSizeY(mpElbeemSettings->resolutionxyz);
mpLbm->setSizeZ(mpElbeemSettings->resolutionxyz);
mpLbm->setPreviewSize(mpElbeemSettings->previewresxyz);
mpLbm->setRefinementDesired(mpElbeemSettings->maxRefine);
mpLbm->setGenerateParticles(mpElbeemSettings->generateParticles);
string dinitType = std::string("no");
if (mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_PARTSLIP) dinitType = std::string("part");
else if(mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_FREESLIP) dinitType = std::string("free");
else /*if(mpElbeemSettings->obstacleType==FLUIDSIM_OBSTACLE_NOSLIP)*/ dinitType = std::string("no");
mpLbm->setDomainBound(dinitType);
mpLbm->setDomainPartSlip(mpElbeemSettings->obstaclePartslip);
mpLbm->setDumpVelocities(mpElbeemSettings->generateVertexVectors);
debMsgStd("SimulationObject::initialize",DM_MSG,"Added domain bound: "<<dinitType<<" ps="<<mpElbeemSettings->obstaclePartslip<<" vv"<<mpElbeemSettings->generateVertexVectors<<","<<mpLbm->getDumpVelocities(), 9 );
debMsgStd("SimulationObject::initialize",DM_MSG,"Set ElbeemSettings values "<<mpLbm->getGenerateParticles(),10);
}
mpLbm->initializeSolver();
// print cell type stats
@@ -175,7 +200,7 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
}
mpLbm->deleteCellIterator( &cid );
#if ELBEEM_BLENDER!=1
#if ELBEEM_PLUGIN!=1
char charNl = '\n';
debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5);
debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5);
@@ -199,12 +224,18 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<"] "<< charNl;
if(diffInits > 0) {
debugOut("SimulationObject::initializeLbmSimulation celltype Warning: Diffinits="<<diffInits<<" !!!!!!!!!" , 5);
debMsgStd("SimulationObject::initializeLbmSimulation",DM_MSG,"celltype Warning: Diffinits="<<diffInits<<" !!!!!!!!!" , 5);
}
debugOutNnl(out.str(), 5);
}
#endif // ELBEEM_BLENDER==1
#endif // ELBEEM_PLUGIN==1
// might be modified by mpLbm
mpParts->setStart( mGeoStart );
mpParts->setEnd( mGeoEnd );
mpParts->setCastShadows( false );
mpParts->setReceiveShadows( false );
mpParts->searchMaterial( glob->getMaterials() );
mpLbm->initParticles(mpParts);
// this has to be inited here - before, the values might be unknown
@@ -218,12 +249,19 @@ int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
if(mShowSurface) mObjects.push_back( surf );
}
mpParts->setStart( mGeoStart );
mpParts->setEnd( mGeoEnd );
mpParts->setCastShadows( false );
mpParts->setReceiveShadows( false );
mpParts->searchMaterial( glob->getMaterials() );
if(mShowParticles) mObjects.push_back(mpParts);
#ifdef ELBEEM_PLUGIN
mShowParticles=1;
#endif // ELBEEM_PLUGIN
//if(getenv("ELBEEM_DUMPPARTICLE")) { // DEBUG ENABLE!!!!!!!!!!
if(mpLbm->getGenerateParticles()>0.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();
@@ -247,17 +285,17 @@ void SimulationObject::setFrameNum(int num) {
*****************************************************************************/
void SimulationObject::step( void )
{
if(mpParam->getAniFrameTime()>0.0) {
if(mpParam->getCurrentAniFrameTime()>0.0) {
// dont advance for stopped time
mpLbm->step();
mpParts->savePreviousPositions();
mpLbm->advanceParticles(mpParts);
mTime += mpParam->getStepTime();
mTime += mpParam->getTimestep();
}
if(mpLbm->getPanic()) mPanic = true;
//debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getStepTime())<<", framet="<<getFrameTime()<<") ", 10);
//debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getTimestep())<<", framet="<<getFrameTime()<<") ", 10);
}
/*! prepare visualization of simulation for e.g. raytracing */
void SimulationObject::prepareVisualization( void ) {
@@ -273,12 +311,12 @@ double SimulationObject::getStartTime( void ) {
return mpParam->getAniStart();
}
/* get time for a single animation frame */
double SimulationObject::getFrameTime( void ) {
return mpParam->getAniFrameTime();
double SimulationObject::getFrameTime( int frame ) {
return mpParam->getAniFrameTime(frame);
}
/* get time for a single time step */
double SimulationObject::getStepTime( void ) {
return mpParam->getStepTime();
double SimulationObject::getTimestep( void ) {
return mpParam->getTimestep();
}
@@ -307,17 +345,12 @@ SimulationObject::getObjectsEnd()
void SimulationObject::drawDebugDisplay() {
#ifndef NOGUI
//debugOut(" SD: "<<mDebugType<<" v"<<getVisible()<<" don"<< (mDebDispSet[mDebugType].on) , 10);
if(!getVisible()) return;
if( mDebugType > (MAX_DEBDISPSET-1) ){
errFatal("SimulationObject::drawDebugDisplay","Invalid debug type!", SIMWORLD_GENERICERROR);
return;
}
mDebDispSet[ mDebugType ].on = true;
//if( mDebugType > (MAX_DEBDISPSET-1) ){ errFatal("SimulationObject::drawDebugDisplay","Invalid debug type!", SIMWORLD_GENERICERROR); return; }
//mDebDispSet[ mDebugType ].on = true;
//errorOut( mDebugType <<"//"<< mDebDispSet[mDebugType].type );
mpLbm->debugDisplay( &mDebDispSet[ mDebugType ] );
mpLbm->debugDisplay( mDebugType );
//::lbmMarkedCellDisplay<>( mpLbm );
mpLbm->lbmMarkedCellDisplay();
@@ -331,7 +364,7 @@ void SimulationObject::drawInteractiveDisplay()
if(!getVisible()) return;
if(mSelectedCid) {
// in debugDisplayNode if dispset is on is ignored...
mpLbm->debugDisplayNode( &mDebDispSet[ FLUIDDISPGrid ], mSelectedCid );
mpLbm->debugDisplayNode( FLUIDDISPGrid, mSelectedCid );
}
#endif
}
@@ -365,4 +398,9 @@ void SimulationObject::setMouseClick()
}
}
/*! notify object that dump is in progress (e.g. for field dump) */
void SimulationObject::notifyShaderOfDump(int frameNr,char *frameNrStr,string outfilename) {
if(!mpLbm) return;
mpLbm->notifySolverOfDump(frameNr,frameNrStr,outfilename);
}

View File

@@ -13,13 +13,15 @@
#define USE_GLUTILITIES
#include "ntl_geometryshader.h"
#include "solver_interface.h"
#include "parametrizer.h"
class LbmSolverInterface;
class CellIdentifierInterface;
class ntlTree;
class ntlRenderGlobals;
class ntlRenderGlobals;
class ParticleTracer;
struct elbeemSimulationSettings;
//! type fluid geometry init
@@ -48,6 +50,8 @@ class SimulationObject :
SimulationObject();
/*! Destructor */
virtual ~SimulationObject();
/*! for init from API */
void copyElbeemSettings(elbeemSimulationSettings *settings);
/*! init tree for certain geometry init */
@@ -86,6 +90,8 @@ class SimulationObject :
/*! Do geo etc. init */
virtual int postGeoConstrInit(ntlRenderGlobals *glob) { return initializeLbmSimulation(glob); };
virtual int initializeShader() { /* ... */ return true; };
/*! notify object that dump is in progress (e.g. for field dump) */
virtual void notifyShaderOfDump(int frameNr,char *frameNrStr,string outfilename);
/*! simluation interface: draw the simulation with OpenGL */
virtual void draw( void ) {};
virtual vector<ntlGeometryObject *>::iterator getObjectsBegin();
@@ -97,13 +103,6 @@ class SimulationObject :
/*! prepare visualization of simulation for e.g. raytracing */
virtual void prepareVisualization( void );
/*! get current start simulation time */
virtual double getStartTime( void );
/*! get time for a single animation frame */
virtual double getFrameTime( void );
/*! get time for a single time step in the simulation */
virtual double getStepTime( void );
/*! GUI - display debug info */
virtual void drawDebugDisplay();
/*! GUI - display interactive info */
@@ -112,6 +111,13 @@ class SimulationObject :
virtual void setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir);
virtual void setMouseClick();
/*! get current start simulation time */
double getStartTime( void );
/*! get time for a single animation frame */
double getFrameTime( int frame );
/*! get time for a single time step in the simulation */
double getTimestep( void );
//! access solver
LbmSolverInterface *getSolver(){ return mpLbm; }
@@ -143,7 +149,6 @@ class SimulationObject :
//! dimension of the simulation - now given by LBM-DIM define globally
//! solver type
string mSolverType;
/*! when no parametrizer, use this as no. of steps per frame */
int mStepsPerFrame;
@@ -165,24 +170,21 @@ class SimulationObject :
bool mShowParticles;
/*! debug display settings */
#ifndef USE_MSVC6FIXES
static const int MAX_DEBDISPSET = 10;
#else
// so this is a known and documented MSVC6 bug
// work around
enum {MAX_DEBDISPSET = 10};
#endif
fluidDispSettings mDebDispSet[ MAX_DEBDISPSET ];
int mDebDispSetting;
/*! pointer to identifier of selected node */
CellIdentifierInterface *mSelectedCid;
/*! storage of API settings */
elbeemSimulationSettings *mpElbeemSettings;
public:
// debug display setting funtions
/*! set type of info to display */
inline void setDebugDisplay(int disp) { mDebugType = disp; }
inline int getDebugDisplay() { return mDebugType; }
/* miscelleanous access functions */
@@ -198,10 +200,6 @@ class SimulationObject :
virtual inline ntlVec3Gfx *getBBStart() { return &mGeoStart; }
virtual inline ntlVec3Gfx *getBBEnd() { return &mGeoEnd; }
/*! solver dimension constants */
const string stnOld;
const string stnFsgr;
};

View File

@@ -15,7 +15,7 @@
#include "utilities.h"
#include "solver_interface.h"
#include "ntl_scene.h"
#include "ntl_ray.h"
#include <stdio.h>
#if PARALLEL==1
@@ -25,22 +25,14 @@
#define PARALLEL 0
#endif // PARALLEL
#ifndef LBMMODEL_DEFINED
// force compiler error!
ERROR - define model first!
#endif // LBMMODEL_DEFINED
// general solver setting defines
// default to 3dim
#ifndef LBMDIM
#define LBMDIM 3
#endif // LBMDIM
//! debug coordinate accesses and the like? (much slower)
// might be enabled by compilation
#ifndef FSGR_STRICT_DEBUG
#define FSGR_STRICT_DEBUG 0
#endif // FSGR_STRICT_DEBUG
//! debug coordinate accesses and the like? (much slower)
#define FSGR_OMEGA_DEBUG 0
@@ -81,6 +73,7 @@ ERROR - define model first!
#define FSGR_MAXNOOFLEVELS 5
// enable/disable fine grid compression for finest level
// make sure this is same as useGridComp in calculateMemreqEstimate
#if LBMDIM==3
#define COMPRESSGRIDS 1
#else
@@ -113,15 +106,14 @@ ERROR - define model first!
#endif
#endif
#if ELBEEM_BLENDER!=1
#if LBM_INCLUDE_TESTSOLVERS==1
#include "solver_test.h"
#endif // ELBEEM_BLENDER==1
#endif // LBM_INCLUDE_TESTSOLVERS==1
/*****************************************************************************/
/*! cell access classes */
template<typename D>
class UniformFsgrCellIdentifier :
public CellIdentifierInterface
public CellIdentifierInterface , public LbmCellContents
{
public:
//! which grid level?
@@ -137,14 +129,13 @@ class UniformFsgrCellIdentifier :
virtual string getAsString() {
std::ostringstream ret;
ret <<"{ i"<<x<<",j"<<y;
if(D::cDimension>2) ret<<",k"<<z;
if(LBMDIM>2) ret<<",k"<<z;
ret <<" }";
return ret.str();
}
virtual bool equal(CellIdentifierInterface* other) {
//UniformFsgrCellIdentifier<D> *cid = dynamic_cast<UniformFsgrCellIdentifier<D> *>( other );
UniformFsgrCellIdentifier<D> *cid = (UniformFsgrCellIdentifier<D> *)( other );
UniformFsgrCellIdentifier *cid = (UniformFsgrCellIdentifier *)( other );
if(!cid) return false;
if( x==cid->x && y==cid->y && z==cid->z && level==cid->level ) return true;
return false;
@@ -165,7 +156,7 @@ public:
//! size this level was advanced to
LbmFloat time;
//! size of a single lbm step in time units on this level
LbmFloat stepsize;
LbmFloat timestep;
//! step count
int lsteps;
//! gravity force for this level
@@ -203,9 +194,8 @@ public:
/*****************************************************************************/
/*! class for solving a LBM problem */
template<class D>
class LbmFsgrSolver :
public D // this means, the solver is a lbmData object and implements the lbmInterface
public LbmSolverInterface // this means, the solver is a lbmData object and implements the lbmInterface
{
public:
@@ -213,26 +203,23 @@ class LbmFsgrSolver :
LbmFsgrSolver();
//! Destructor
virtual ~LbmFsgrSolver();
//! id string of solver
virtual string getIdString();
//! dimension of solver
virtual int getDimension();
//! initilize variables fom attribute list
virtual void parseAttrList();
//! Initialize omegas and forces on all levels (for init/timestep change)
void initLevelOmegas();
//! finish the init with config file values (allocate arrays...)
virtual bool initializeSolver(); //( ntlTree* /*tree*/, vector<ntlGeometryObject*>* /*objects*/ );
virtual bool initializeSolver();
//! notify object that dump is in progress (e.g. for field dump)
virtual void notifySolverOfDump(int frameNr,char *frameNrStr,string outfilename);
#if LBM_USE_GUI==1
//! show simulation info (implement LbmSolverInterface pure virtual func)
virtual void debugDisplay(fluidDispSettings *set);
virtual void debugDisplay(int set);
#endif
// implement CellIterator<UniformFsgrCellIdentifier> interface
typedef UniformFsgrCellIdentifier<typename D::LbmCellContents> stdCellId;
typedef UniformFsgrCellIdentifier stdCellId;
virtual CellIdentifierInterface* getFirstCell( );
virtual void advanceCell( CellIdentifierInterface* );
virtual bool noEndCell( CellIdentifierInterface* );
@@ -249,7 +236,7 @@ class LbmFsgrSolver :
virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set);
virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set);
virtual LbmFloat getEquilDf ( int );
virtual int getDfNum ( );
virtual ntlVec3Gfx getVelocityAt (float x, float y, float z);
// convert pointers
stdCellId* convertBaseCidToStdCid( CellIdentifierInterface* basecid);
@@ -264,6 +251,8 @@ class LbmFsgrSolver :
LBM_INLINED void initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass);
LBM_INLINED void initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel);
LBM_INLINED void changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag);
//! interpolate velocity and density at a given position
void interpolateCellValues(int level,int ei,int ej,int ek,int workSet, LbmFloat &retrho, LbmFloat &retux, LbmFloat &retuy, LbmFloat &retuz);
/*! perform a single LBM step */
void stepMain();
@@ -288,8 +277,8 @@ class LbmFsgrSolver :
// gui/output debugging functions
#if LBM_USE_GUI==1
virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifierInterface* cell );
virtual void lbmDebugDisplay(fluidDispSettings *dispset);
virtual void debugDisplayNode(int dispset, CellIdentifierInterface* cell );
virtual void lbmDebugDisplay(int dispset);
virtual void lbmMarkedCellDisplay();
#endif // LBM_USE_GUI==1
virtual void debugPrintNodeInfo(CellIdentifierInterface* cell, int forceSet=-1);
@@ -298,7 +287,7 @@ class LbmFsgrSolver :
void prepareVisualization( void );
/*! type for cells */
typedef typename D::LbmCell LbmCell;
//typedef typename this->LbmCell LbmCell;
protected:
@@ -311,6 +300,8 @@ class LbmFsgrSolver :
void adaptTimestep();
//! init mObjectSpeeds for current parametrization
void recalculateObjectSpeeds();
//! init moving obstacles for next sim step sim
void initMovingObstacles(bool staticInit);
//! flag reinit step - always works on finest grid!
void reinitFlags( int workSet );
//! mass dist weights
@@ -347,10 +338,6 @@ class LbmFsgrSolver :
//! use time adaptivity?
bool mTimeAdap;
//! domain boundary free/no slip type
string mDomainBound;
//! part slip value for domain
LbmFloat mDomainPartSlipValue;
//! fluid vol height
LbmFloat mFVHeight;
@@ -364,12 +351,17 @@ class LbmFsgrSolver :
//! smoother surface initialization?
int mInitSurfaceSmoothing;
//! lock time step down switching
int mTimestepReduceLock;
//! count no. of switches
int mTimeSwitchCounts;
// only switch of maxvel is higher for several steps...
int mTimeMaxvelStepCnt;
//! total simulation time so far
LbmFloat mSimulationTime;
LbmFloat mSimulationTime, mLastSimTime;
//! smallest and largest step size so far
LbmFloat mMinStepTime, mMaxStepTime;
LbmFloat mMinTimestep, mMaxTimestep;
//! track max. velocity
LbmFloat mMxvx, mMxvy, mMxvz, mMaxVlen;
@@ -442,17 +434,10 @@ class LbmFsgrSolver :
int mDisableStandingFluidInit;
//! debug function to force tadap syncing
int mForceTadapRefine;
#ifndef ELBEEM_BLENDER
// test functions
bool mUseTestdata;
LbmTestdata *mpTest;
void initTestdata();
void destroyTestdata();
void handleTestdata();
void exportTestdata();
//! border cutoff value
int mCutoff;
//! store particle tracer
ParticleTracer *mpParticles;
#endif // ELBEEM_BLENDER==1
// strict debug interface
# if FSGR_STRICT_DEBUG==1
@@ -467,8 +452,226 @@ class LbmFsgrSolver :
LbmFloat* debRACPNT(int level, int ii,int ij,int ik, int is );
LbmFloat& debRAC(LbmFloat* s,int l);
# endif // FSGR_STRICT_DEBUG==1
bool mUseTestdata;
#if LBM_INCLUDE_TESTSOLVERS==1
// test functions
LbmTestdata *mpTest;
void initTestdata();
void destroyTestdata();
void handleTestdata();
void exportTestdata();
void set3dHeight(int ,int );
public:
// needed from testdata
void find3dHeight(int i,int j, LbmFloat prev, LbmFloat &ret, LbmFloat &retux, LbmFloat &retuy);
#endif // LBM_INCLUDE_TESTSOLVERS==1
public: // former LbmModelLBGK functions
// relaxation funtions - implemented together with relax macros
static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz);
static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz);
inline LbmFloat getLesNoneqTensorCoeff( LbmFloat df[], LbmFloat feq[] );
inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo);
inline void collideArrays( int i, int j, int k, // position - more for debugging
LbmFloat df[], LbmFloat &outrho, // out only!
// velocity modifiers (returns actual velocity!)
LbmFloat &mux, LbmFloat &muy, LbmFloat &muz, LbmFloat omega, LbmFloat csmago, LbmFloat *newOmegaRet, LbmFloat *newQoRet);
// former LBM models
public:
//! shorten static const definitions
#define STCON static const
#if LBMDIM==3
//! id string of solver
virtual string getIdString() { return string("FreeSurfaceFsgrSolver[BGK_D3Q19]"); }
//! how many dimensions? UNUSED? replace by LBMDIM?
STCON int cDimension;
// Wi factors for collide step
STCON LbmFloat cCollenZero;
STCON LbmFloat cCollenOne;
STCON LbmFloat cCollenSqrtTwo;
//! threshold value for filled/emptied cells
STCON LbmFloat cMagicNr2;
STCON LbmFloat cMagicNr2Neg;
STCON LbmFloat cMagicNr;
STCON LbmFloat cMagicNrNeg;
//! size of a single set of distribution functions
STCON int cDfNum;
//! direction vector contain vecs for all spatial dirs, even if not used for LBM model
STCON int cDirNum;
//! distribution functions directions
typedef enum {
cDirInv= -1,
cDirC = 0,
cDirN = 1,
cDirS = 2,
cDirE = 3,
cDirW = 4,
cDirT = 5,
cDirB = 6,
cDirNE = 7,
cDirNW = 8,
cDirSE = 9,
cDirSW = 10,
cDirNT = 11,
cDirNB = 12,
cDirST = 13,
cDirSB = 14,
cDirET = 15,
cDirEB = 16,
cDirWT = 17,
cDirWB = 18
} dfDir;
/* Vector Order 3D:
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
* 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1
* 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1
* 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1
*/
/*! name of the dist. function
only for nicer output */
STCON char* dfString[ 19 ];
/*! index of normal dist func, not used so far?... */
STCON int dfNorm[ 19 ];
/*! index of inverse dist func, not fast, but useful... */
STCON int dfInv[ 19 ];
/*! index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefX[ 19 ];
/*! index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefY[ 19 ];
/*! index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefZ[ 19 ];
/*! dist func vectors */
STCON int dfVecX[ 27 ];
STCON int dfVecY[ 27 ];
STCON int dfVecZ[ 27 ];
/*! arrays as before with doubles */
STCON LbmFloat dfDvecX[ 27 ];
STCON LbmFloat dfDvecY[ 27 ];
STCON LbmFloat dfDvecZ[ 27 ];
/*! principal directions */
STCON int princDirX[ 2*3 ];
STCON int princDirY[ 2*3 ];
STCON int princDirZ[ 2*3 ];
/*! vector lengths */
STCON LbmFloat dfLength[ 19 ];
/*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
static LbmFloat dfEquil[ 19 ];
/*! arrays for les model coefficients */
static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ];
static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ];
#else // end LBMDIM==3 , LBMDIM==2
//! id string of solver
virtual string getIdString() { return string("FreeSurfaceFsgrSolver[BGK_D2Q9]"); }
//! how many dimensions?
STCON int cDimension;
//! Wi factors for collide step
STCON LbmFloat cCollenZero;
STCON LbmFloat cCollenOne;
STCON LbmFloat cCollenSqrtTwo;
//! threshold value for filled/emptied cells
STCON LbmFloat cMagicNr2;
STCON LbmFloat cMagicNr2Neg;
STCON LbmFloat cMagicNr;
STCON LbmFloat cMagicNrNeg;
//! size of a single set of distribution functions
STCON int cDfNum;
STCON int cDirNum;
//! distribution functions directions
typedef enum {
cDirInv= -1,
cDirC = 0,
cDirN = 1,
cDirS = 2,
cDirE = 3,
cDirW = 4,
cDirNE = 5,
cDirNW = 6,
cDirSE = 7,
cDirSW = 8
} dfDir;
/* Vector Order 2D:
* 0 1 2 3 4 5 6 7 8
* 0, 0,0, 1,-1, 1,-1,1,-1
* 0, 1,-1, 0,0, 1,1,-1,-1 */
/* name of the dist. function
only for nicer output */
STCON char* dfString[ 9 ];
/* index of normal dist func, not used so far?... */
STCON int dfNorm[ 9 ];
/* index of inverse dist func, not fast, but useful... */
STCON int dfInv[ 9 ];
/* index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefX[ 9 ];
/* index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefY[ 9 ];
/* index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefZ[ 9 ];
/* dist func vectors */
STCON int dfVecX[ 9 ];
STCON int dfVecY[ 9 ];
/* Z, 2D values are all 0! */
STCON int dfVecZ[ 9 ];
/* arrays as before with doubles */
STCON LbmFloat dfDvecX[ 9 ];
STCON LbmFloat dfDvecY[ 9 ];
/* Z, 2D values are all 0! */
STCON LbmFloat dfDvecZ[ 9 ];
/*! principal directions */
STCON int princDirX[ 2*2 ];
STCON int princDirY[ 2*2 ];
STCON int princDirZ[ 2*2 ];
/* vector lengths */
STCON LbmFloat dfLength[ 9 ];
/* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
static LbmFloat dfEquil[ 9 ];
/*! arrays for les model coefficients */
static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ];
static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ];
#endif // LBMDIM==2
};
#undef STCON
/*****************************************************************************/
@@ -479,7 +682,7 @@ class LbmFsgrSolver :
// cell mark debugging
#if FSGR_STRICT_DEBUG==10
#define debugMarkCell(lev,x,y,z) \
errMsg("debugMarkCell",D::mName<<" step: "<<D::mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \
errMsg("debugMarkCell",this->mName<<" step: "<<this->mStepCnt<<" lev:"<<(lev)<<" marking "<<PRINT_VEC((x),(y),(z))<<" line "<< __LINE__ ); \
debugMarkCellCall((lev),(x),(y),(z));
#else // FSGR_STRICT_DEBUG==1
#define debugMarkCell(lev,x,y,z) \
@@ -494,8 +697,8 @@ class LbmFsgrSolver :
//! flag array acces macro
#define _RFLAG(level,xx,yy,zz,set) mLevel[level].mprsFlags[set][ LBMGI((level),(xx),(yy),(zz),(set)) ]
#define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set) ]
#define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set) ]
#define _RFLAG_NB(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+this->dfVecX[dir],(yy)+this->dfVecY[dir],(zz)+this->dfVecZ[dir],set) ]
#define _RFLAG_NBINV(level,xx,yy,zz,set, dir) mLevel[level].mprsFlags[set][ LBMGI((level),(xx)+this->dfVecX[this->dfInv[dir]],(yy)+this->dfVecY[this->dfInv[dir]],(zz)+this->dfVecZ[this->dfInv[dir]],set) ]
// array data layouts
// standard array layout -----------------------------------------------------------------------------------------------
@@ -503,8 +706,8 @@ class LbmFsgrSolver :
//#define _LBMQI(level, ii,ij,ik, is, lunused) ( ((is)*mLevel[level].lOffsz) + (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) )
#define _LBMQI(level, ii,ij,ik, is, lunused) ( (mLevel[level].lOffsy*(ik)) + (mLevel[level].lOffsx*(ij)) + (ii) )
#define _QCELL(level,xx,yy,zz,set,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx),(yy),(zz),(set), l)*dTotalNum +(l)])
#define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[dir],(yy)+D::dfVecY[dir],(zz)+D::dfVecZ[dir],set, l)*dTotalNum +(l)])
#define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+D::dfVecX[D::dfInv[dir]],(yy)+D::dfVecY[D::dfInv[dir]],(zz)+D::dfVecZ[D::dfInv[dir]],set, l)*dTotalNum +(l)])
#define _QCELL_NB(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+this->dfVecX[dir],(yy)+this->dfVecY[dir],(zz)+this->dfVecZ[dir],set, l)*dTotalNum +(l)])
#define _QCELL_NBINV(level,xx,yy,zz,set, dir,l) (mLevel[level].mprsCells[(set)][ LBMQI((level),(xx)+this->dfVecX[this->dfInv[dir]],(yy)+this->dfVecY[this->dfInv[dir]],(zz)+this->dfVecZ[this->dfInv[dir]],set, l)*dTotalNum +(l)])
#define QCELLSTEP dTotalNum
#define _RACPNT(level, ii,ij,ik, is ) &QCELL(level,ii,ij,ik,is,0)
@@ -555,7 +758,6 @@ class LbmFsgrSolver :
#define dNW 6
#define dSE 7
#define dSW 8
#define LBM_DFNUM 9
#else
// direction indices
#define dC 0
@@ -577,12 +779,11 @@ class LbmFsgrSolver :
#define dEB 16
#define dWT 17
#define dWB 18
#define LBM_DFNUM 19
#endif
//? #define dWB 18
// default init for dFlux values
#define FLUX_INIT 0.5f * (float)(D::cDfNum)
#define FLUX_INIT 0.5f * (float)(this->cDfNum)
// only for non DF dir handling!
#define dNET 19
@@ -617,24 +818,44 @@ class LbmFsgrSolver :
/******************************************************************************/
/*! equilibrium functions */
/******************************************************************************/
/*! calculate length of velocity vector */
inline LbmFloat LbmFsgrSolver::getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) {
return ((ux)*dfDvecX[l]+(uy)*dfDvecY[l]+(uz)*dfDvecZ[l]);
};
/*! calculate equilibrium DF for given values */
inline LbmFloat LbmFsgrSolver::getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) {
#if FSGR_STRICT_DEBUG==1
if((l<0)||(l>LBM_DFNUM)) { errFatal("LbmFsgrSolver::getCollideEq","Invalid DFEQ call "<<l, SIMWORLD_PANIC ); /* no access to mPanic here */ }
#endif // FSGR_STRICT_DEBUG==1
LbmFloat tmp = getVelVecLen(l,ux,uy,uz);
return( dfLength[l] *(
+ rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz))
+ 3.0 *tmp
+ 9.0/2.0 *(tmp*tmp) )
);
};
/*****************************************************************************/
/* init a given cell with flag, density, mass and equilibrium dist. funcs */
template<class D>
void LbmFsgrSolver<D>::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) {
void LbmFsgrSolver::changeFlag(int level, int xx,int yy,int zz,int set,CellFlagType newflag) {
CellFlagType pers = RFLAG(level,xx,yy,zz,set) & CFPersistMask;
RFLAG(level,xx,yy,zz,set) = newflag | pers;
}
template<class D>
void
LbmFsgrSolver<D>::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) {
LbmFsgrSolver::initEmptyCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass) {
/* init eq. dist funcs */
LbmFloat *ecel;
int workSet = mLevel[level].setCurr;
ecel = RACPNT(level, i,j,k, workSet);
FORDF0 { RAC(ecel, l) = D::dfEquil[l] * rho; }
FORDF0 { RAC(ecel, l) = this->dfEquil[l] * rho; }
RAC(ecel, dMass) = mass;
RAC(ecel, dFfrac) = mass/rho;
RAC(ecel, dFlux) = FLUX_INIT;
@@ -646,14 +867,13 @@ LbmFsgrSolver<D>::initEmptyCell(int level, int i,int j,int k, CellFlagType flag,
return;
}
template<class D>
void
LbmFsgrSolver<D>::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) {
LbmFsgrSolver::initVelocityCell(int level, int i,int j,int k, CellFlagType flag, LbmFloat rho, LbmFloat mass, LbmVec vel) {
LbmFloat *ecel;
int workSet = mLevel[level].setCurr;
ecel = RACPNT(level, i,j,k, workSet);
FORDF0 { RAC(ecel, l) = D::getCollideEq(l, rho,vel[0],vel[1],vel[2]); }
FORDF0 { RAC(ecel, l) = getCollideEq(l, rho,vel[0],vel[1],vel[2]); }
RAC(ecel, dMass) = mass;
RAC(ecel, dFfrac) = mass/rho;
RAC(ecel, dFlux) = FLUX_INIT;
@@ -665,24 +885,20 @@ LbmFsgrSolver<D>::initVelocityCell(int level, int i,int j,int k, CellFlagType fl
return;
}
template<class D>
int LbmFsgrSolver<D>::getForZMinBnd() {
int LbmFsgrSolver::getForZMinBnd() {
return 0;
}
template<class D>
int LbmFsgrSolver<D>::getForZMin1() {
if(D::cDimension==2) return 0;
int LbmFsgrSolver::getForZMin1() {
if(LBMDIM==2) return 0;
return 1;
}
template<class D>
int LbmFsgrSolver<D>::getForZMaxBnd(int lev) {
if(D::cDimension==2) return 1;
int LbmFsgrSolver::getForZMaxBnd(int lev) {
if(LBMDIM==2) return 1;
return mLevel[lev].lSizez -0;
}
template<class D>
int LbmFsgrSolver<D>::getForZMax1(int lev) {
if(D::cDimension==2) return 1;
int LbmFsgrSolver::getForZMax1(int lev) {
if(LBMDIM==2) return 1;
return mLevel[lev].lSizez -1;
}

View File

@@ -1,21 +0,0 @@
/******************************************************************************
*
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
* All code distributed as part of El'Beem is covered by the version 2 of the
* GNU General Public License. See the file COPYING for details.
* Copyright 2003-2005 Nils Thuerey
*
* Combined 2D/3D Lattice Boltzmann Solver auxiliary classes
*
*****************************************************************************/
#ifndef LBMHEADER_H
/* LBM Files */
#include "solver_interface.h"
#define LBMHEADER_H
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -12,284 +12,11 @@
/* LBM Files */
#include "solver_interface.h"
#include "ntl_scene.h"
#include "ntl_ray.h"
#include "ntl_world.h"
#include "elbeem.h"
/*****************************************************************************/
//! common variables
/*****************************************************************************/
/*! class for solver templating - 3D implementation D3Q19 */
//! how many dimensions?
const int LbmD3Q19::cDimension = 3;
// Wi factors for collide step
const LbmFloat LbmD3Q19::cCollenZero = (1.0/3.0);
const LbmFloat LbmD3Q19::cCollenOne = (1.0/18.0);
const LbmFloat LbmD3Q19::cCollenSqrtTwo = (1.0/36.0);
//! threshold value for filled/emptied cells
const LbmFloat LbmD3Q19::cMagicNr2 = 1.0005;
const LbmFloat LbmD3Q19::cMagicNr2Neg = -0.0005;
const LbmFloat LbmD3Q19::cMagicNr = 1.010001;
const LbmFloat LbmD3Q19::cMagicNrNeg = -0.010001;
//! size of a single set of distribution functions
const int LbmD3Q19::cDfNum = 19;
//! direction vector contain vecs for all spatial dirs, even if not used for LBM model
const int LbmD3Q19::cDirNum = 27;
//const string LbmD3Q19::dfString[ cDfNum ] = {
const char* LbmD3Q19::dfString[ cDfNum ] = {
" C", " N"," S"," E"," W"," T"," B",
"NE","NW","SE","SW",
"NT","NB","ST","SB",
"ET","EB","WT","WB"
};
const int LbmD3Q19::dfNorm[ cDfNum ] = {
cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB,
cDirNE, cDirNW, cDirSE, cDirSW,
cDirNT, cDirNB, cDirST, cDirSB,
cDirET, cDirEB, cDirWT, cDirWB
};
const int LbmD3Q19::dfInv[ cDfNum ] = {
cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT,
cDirSW, cDirSE, cDirNW, cDirNE,
cDirSB, cDirST, cDirNB, cDirNT,
cDirWB, cDirWT, cDirEB, cDirET
};
const int LbmD3Q19::dfRefX[ cDfNum ] = {
0, 0, 0, 0, 0, 0, 0,
cDirSE, cDirSW, cDirNE, cDirNW,
0, 0, 0, 0,
cDirEB, cDirET, cDirWB, cDirWT
};
const int LbmD3Q19::dfRefY[ cDfNum ] = {
0, 0, 0, 0, 0, 0, 0,
cDirNW, cDirNE, cDirSW, cDirSE,
cDirNB, cDirNT, cDirSB, cDirST,
0, 0, 0, 0
};
const int LbmD3Q19::dfRefZ[ cDfNum ] = {
0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
cDirST, cDirSB, cDirNT, cDirNB,
cDirWT, cDirWB, cDirET, cDirEB
};
// Vector Order 3D:
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1
// 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1
// 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1
const int LbmD3Q19::dfVecX[ cDirNum ] = {
0, 0,0, 1,-1, 0,0,
1,-1,1,-1,
0,0,0,0,
1,1,-1,-1,
1,-1, 1,-1,
1,-1, 1,-1,
};
const int LbmD3Q19::dfVecY[ cDirNum ] = {
0, 1,-1, 0,0,0,0,
1,1,-1,-1,
1,1,-1,-1,
0,0,0,0,
1, 1,-1,-1,
1, 1,-1,-1
};
const int LbmD3Q19::dfVecZ[ cDirNum ] = {
0, 0,0,0,0,1,-1,
0,0,0,0,
1,-1,1,-1,
1,-1,1,-1,
1, 1, 1, 1,
-1,-1,-1,-1
};
const LbmFloat LbmD3Q19::dfDvecX[ cDirNum ] = {
0, 0,0, 1,-1, 0,0,
1,-1,1,-1,
0,0,0,0,
1,1,-1,-1,
1,-1, 1,-1,
1,-1, 1,-1
};
const LbmFloat LbmD3Q19::dfDvecY[ cDirNum ] = {
0, 1,-1, 0,0,0,0,
1,1,-1,-1,
1,1,-1,-1,
0,0,0,0,
1, 1,-1,-1,
1, 1,-1,-1
};
const LbmFloat LbmD3Q19::dfDvecZ[ cDirNum ] = {
0, 0,0,0,0,1,-1,
0,0,0,0,
1,-1,1,-1,
1,-1,1,-1,
1, 1, 1, 1,
-1,-1,-1,-1
};
/* principal directions */
const int LbmD3Q19::princDirX[ 2*LbmD3Q19::cDimension ] = {
1,-1, 0,0, 0,0
};
const int LbmD3Q19::princDirY[ 2*LbmD3Q19::cDimension ] = {
0,0, 1,-1, 0,0
};
const int LbmD3Q19::princDirZ[ 2*LbmD3Q19::cDimension ] = {
0,0, 0,0, 1,-1
};
/*! arrays for les model coefficients, inited in lbmsolver constructor */
LbmFloat LbmD3Q19::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ];
LbmFloat LbmD3Q19::lesCoeffOffdiag[ cDimension ][ cDirNum ];
const LbmFloat LbmD3Q19::dfLength[ cDfNum ]= {
cCollenZero,
cCollenOne, cCollenOne, cCollenOne,
cCollenOne, cCollenOne, cCollenOne,
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo,
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo,
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo
};
/* precalculated equilibrium dfs, inited in lbmsolver constructor */
LbmFloat LbmD3Q19::dfEquil[ cDfNum ];
// D3Q19 end
/*****************************************************************************/
/*! class for solver templating - 2D implementation D2Q9 */
//! how many dimensions?
const int LbmD2Q9::cDimension = 2;
//! Wi factors for collide step
const LbmFloat LbmD2Q9::cCollenZero = (4.0/9.0);
const LbmFloat LbmD2Q9::cCollenOne = (1.0/9.0);
const LbmFloat LbmD2Q9::cCollenSqrtTwo = (1.0/36.0);
//! threshold value for filled/emptied cells
const LbmFloat LbmD2Q9::cMagicNr2 = 1.0005;
const LbmFloat LbmD2Q9::cMagicNr2Neg = -0.0005;
const LbmFloat LbmD2Q9::cMagicNr = 1.010001;
const LbmFloat LbmD2Q9::cMagicNrNeg = -0.010001;
//! size of a single set of distribution functions
const int LbmD2Q9::cDfNum = 9;
const int LbmD2Q9::cDirNum = 9;
//const string LbmD2Q9::dfString[ cDfNum ] = {
const char* LbmD2Q9::dfString[ cDfNum ] = {
" C",
" N", " S", " E", " W",
"NE", "NW", "SE","SW"
};
const int LbmD2Q9::dfNorm[ cDfNum ] = {
cDirC,
cDirN, cDirS, cDirE, cDirW,
cDirNE, cDirNW, cDirSE, cDirSW
};
const int LbmD2Q9::dfInv[ cDfNum ] = {
cDirC,
cDirS, cDirN, cDirW, cDirE,
cDirSW, cDirSE, cDirNW, cDirNE
};
const int LbmD2Q9::dfRefX[ cDfNum ] = {
0,
0, 0, 0, 0,
cDirSE, cDirSW, cDirNE, cDirNW
};
const int LbmD2Q9::dfRefY[ cDfNum ] = {
0,
0, 0, 0, 0,
cDirNW, cDirNE, cDirSW, cDirSE
};
const int LbmD2Q9::dfRefZ[ cDfNum ] = {
0, 0, 0, 0, 0,
0, 0, 0, 0
};
// Vector Order 2D:
// 0 1 2 3 4 5 6 7 8
// 0, 0,0, 1,-1, 1,-1,1,-1
// 0, 1,-1, 0,0, 1,1,-1,-1
const int LbmD2Q9::dfVecX[ cDirNum ] = {
0,
0,0, 1,-1,
1,-1,1,-1
};
const int LbmD2Q9::dfVecY[ cDirNum ] = {
0,
1,-1, 0,0,
1,1,-1,-1
};
const int LbmD2Q9::dfVecZ[ cDirNum ] = {
0, 0,0,0,0, 0,0,0,0
};
const LbmFloat LbmD2Q9::dfDvecX[ cDirNum ] = {
0,
0,0, 1,-1,
1,-1,1,-1
};
const LbmFloat LbmD2Q9::dfDvecY[ cDirNum ] = {
0,
1,-1, 0,0,
1,1,-1,-1
};
const LbmFloat LbmD2Q9::dfDvecZ[ cDirNum ] = {
0, 0,0,0,0, 0,0,0,0
};
const int LbmD2Q9::princDirX[ 2*LbmD2Q9::cDimension ] = {
1,-1, 0,0
};
const int LbmD2Q9::princDirY[ 2*LbmD2Q9::cDimension ] = {
0,0, 1,-1
};
const int LbmD2Q9::princDirZ[ 2*LbmD2Q9::cDimension ] = {
0,0, 0,0
};
/*! arrays for les model coefficients, inited in lbmsolver constructor */
LbmFloat LbmD2Q9::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ];
LbmFloat LbmD2Q9::lesCoeffOffdiag[ cDimension ][ cDirNum ];
const LbmFloat LbmD2Q9::dfLength[ cDfNum ]= {
cCollenZero,
cCollenOne, cCollenOne, cCollenOne, cCollenOne,
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo
};
/* precalculated equilibrium dfs, inited in lbmsolver constructor */
LbmFloat LbmD2Q9::dfEquil[ cDfNum ];
// D2Q9 end
/******************************************************************************
@@ -308,9 +35,9 @@ LbmSolverInterface::LbmSolverInterface() :
mInitDone( false ),
mInitDensityGradient( false ),
mpAttrs( NULL ), mpParam( NULL ),
mNumParticlesLost(0), mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0),
mNumParticlesLost(0),
mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0),
mDebugVelScale( 0.01 ), mNodeInfoString("+"),
mRandom( 5123 ),
mvGeoStart(-1.0), mvGeoEnd(1.0),
mAccurateGeoinit(0),
mName("lbm_default") ,
@@ -321,10 +48,14 @@ LbmSolverInterface::LbmSolverInterface() :
mpGiObjects( NULL ), mGiObjInside(), mpGlob( NULL ),
mRefinementDesired(0),
mOutputSurfacePreview(0), mPreviewFactor(0.25),
mSmoothSurface(0.0), mSmoothNormals(0.0),
mMarkedCells(), mMarkedCellIndex(0)
mSmoothSurface(1.0), mSmoothNormals(1.0),
mPartGenProb(0.),
mDumpVelocities(false),
mMarkedCells(), mMarkedCellIndex(0),
mDomainBound("noslip"), mDomainPartSlipValue(0.1),
mTForceStrength(0.0)
{
#if ELBEEM_BLENDER==1
#if ELBEEM_PLUGIN==1
if(gDebugLevel<=1) mSilent = true;
#endif
}
@@ -341,7 +72,7 @@ void initGridSizes(int &sizex, int &sizey, int &sizez,
int mMaxRefine, bool parallel)
{
// fix size inits to force cubic cells and mult4 level dimensions
const int debugGridsizeInit = 1;
const int debugGridsizeInit = 0;
if(debugGridsizeInit) debMsgStd("initGridSizes",DM_MSG,"Called - size X:"<<sizex<<" Y:"<<sizey<<" Z:"<<sizez<<" " ,10);
int maxGridSize = sizex; // get max size
@@ -383,6 +114,10 @@ void initGridSizes(int &sizex, int &sizey, int &sizez,
void calculateMemreqEstimate( int resx,int resy,int resz, int refine,
double *reqret, string *reqstr) {
// debug estimation?
const bool debugMemEst = false;
// COMPRESSGRIDS define is not available here, make sure it matches
const bool useGridComp = true;
// make sure we can handle bid numbers here... all double
double memCnt = 0.0;
double ddTotalNum = (double)dTotalNum;
@@ -392,12 +127,15 @@ void calculateMemreqEstimate( int resx,int resy,int resz, int refine,
double currResz = (double)resz;
double rcellSize = ((currResx*currResy*currResz) *ddTotalNum);
memCnt += (double)(sizeof(CellFlagType) * (rcellSize/ddTotalNum +4.0) *2.0);
#if COMPRESSGRIDS==0
memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0);
#else // COMPRESSGRIDS==0
double compressOffset = (double)(currResx*currResy*ddTotalNum*2.0);
memCnt += (double)(sizeof(LbmFloat) * (rcellSize+compressOffset +4.0));
#endif // COMPRESSGRIDS==0
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"res:"<<PRINT_VEC(currResx,currResy,currResz)<<" rcellSize:"<<rcellSize<<" mc:"<<memCnt, 10);
if(!useGridComp) {
memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0);
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG," no-comp, mc:"<<memCnt, 10);
} else {
double compressOffset = (double)(currResx*currResy*ddTotalNum*2.0);
memCnt += (double)(sizeof(LbmFloat) * (rcellSize+compressOffset +4.0));
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG," w-comp, mc:"<<memCnt, 10);
}
for(int i=refine-1; i>=0; i--) {
currResx /= 2.0;
currResy /= 2.0;
@@ -405,10 +143,12 @@ void calculateMemreqEstimate( int resx,int resy,int resz, int refine,
rcellSize = ((currResz*currResy*currResx) *ddTotalNum);
memCnt += (double)(sizeof(CellFlagType) * (rcellSize/ddTotalNum +4.0) *2.0);
memCnt += (double)(sizeof(LbmFloat) * (rcellSize +4.0) *2.0);
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"refine "<<i<<", mc:"<<memCnt, 10);
}
// isosurface memory
memCnt += (double)( (3*sizeof(int)+sizeof(float)) * ((resx+2)*(resy+2)*(resz+2)) );
if(debugMemEst) debMsgStd("calculateMemreqEstimate",DM_MSG,"iso, mc:"<<memCnt, 10);
double memd = memCnt;
char *sizeStr = "";
@@ -453,7 +193,7 @@ CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultVal
return (CellFlagType)( CFFluid );
}
errMsg("LbmSolverInterface::readBoundaryFlagInt","Invalid value '"<<val<<"' " );
# if LBM_STRICT_DEBUG==1
# if FSGR_STRICT_DEBUG==1
errFatal("readBoundaryFlagInt","Strict abort..."<<val, SIMWORLD_INITERROR);
# endif
return defaultValue;
@@ -480,7 +220,9 @@ void LbmSolverInterface::parseStdAttrList() {
mSizex = (int)sizeVec[0];
mSizey = (int)sizeVec[1];
mSizez = (int)sizeVec[2];
mpParam->setSize(mSizex, mSizey, mSizez ); // param needs size in any case
// param needs size in any case
// test solvers might not have mpPara, though
if(mpParam) mpParam->setSize(mSizex, mSizey, mSizez );
mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmSolverInterface", "mInitDensityGradient", false);
mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmSolverInterface", "mGeoInitId", false);
@@ -488,6 +230,20 @@ void LbmSolverInterface::parseStdAttrList() {
mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmSolverInterface", "mDebugVelScale", false);
mNodeInfoString = mpAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false );
mDumpVelocities = mpAttrs->readBool("dump_velocities", mDumpVelocities, "SimulationLbm","mDumpVelocities", false );
if(getenv("ELBEEM_DUMPVELOCITIES")) {
int get = atoi(getenv("ELBEEM_DUMPVELOCITIES"));
if((get==0)||(get==1)) {
mDumpVelocities = get;
debMsgStd("LbmSolverInterface::parseAttrList",DM_NOTIFY,"Using envvar ELBEEM_DUMPVELOCITIES to set mDumpVelocities to "<<get<<","<<mDumpVelocities,8);
}
}
// new test vars
mTForceStrength = mpAttrs->readFloat("tforcestrength", mTForceStrength,"LbmSolverInterface", "mTForceStrength", false);
mPartGenProb = mpAttrs->readFloat("partgenprob", mPartGenProb,"LbmFsgrSolver", "mPartGenProb", false);
}
@@ -500,7 +256,7 @@ void LbmSolverInterface::parseStdAttrList() {
void LbmSolverInterface::initGeoTree(int id) {
if(mpGlob == NULL) { errFatal("LbmSolverInterface::initGeoTree","Requires globals!",SIMWORLD_INITERROR); return; }
mGeoInitId = id;
ntlScene *scene = mpGlob->getScene();
ntlScene *scene = mpGlob->getSimScene();
mpGiObjects = scene->getObjects();
mGiObjInside.resize( mpGiObjects->size() );
mGiObjDistance.resize( mpGiObjects->size() );
@@ -779,25 +535,26 @@ bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, ntlVec3Gfx dir,
}
}
/*****************************************************************************/
/*! get max. velocity of all objects to initialize as fluid regions or inflow */
ntlVec3Gfx LbmSolverInterface::getGeoMaxInitialVelocity() {
ntlVec3Gfx LbmSolverInterface::getGeoMaxMovementVelocity(LbmFloat simtime, LbmFloat stepsize) {
ntlVec3Gfx max(0.0);
if(mpGlob == NULL) return max;
ntlScene *scene = mpGlob->getScene();
mpGiObjects = scene->getObjects();
// mpGiObjects has to be inited here...
for(int i=0; i< (int)mpGiObjects->size(); i++) {
errMsg("MVT","i"<<i<<" "<< (*mpGiObjects)[i]->getName() ); // DEBUG
if( (*mpGiObjects)[i]->getGeoInitType() & (FGI_FLUID|FGI_MBNDINFLOW) ){
ntlVec3Gfx ovel = (*mpGiObjects)[i]->getInitialVelocity();
if( normNoSqrt(ovel) > normNoSqrt(max) ) { max = ovel; }
//errMsg("IVT","i"<<i<<" "<< (*mpGiObjects)[i]->getInitialVelocity() ); // DEBUG
//ntlVec3Gfx objMaxVel = obj->calculateMaxVel(sourceTime,targetTime);
ntlVec3Gfx orgvel = (*mpGiObjects)[i]->calculateMaxVel( simtime, simtime+stepsize );
if( normNoSqrt(orgvel) > normNoSqrt(max) ) { max = orgvel; }
//errMsg("MVT","i"<<i<<" a"<< (*mpGiObjects)[i]->getInitialVelocity(simtime)<<" o"<<orgvel ); // DEBUG
// TODO check if inflow and simtime
ntlVec3Gfx inivel = (*mpGiObjects)[i]->getInitialVelocity(simtime);
if( normNoSqrt(inivel) > normNoSqrt(max) ) { max = inivel; }
}
}
//errMsg("IVT","max "<<" "<< max ); // DEBUG
// unused !? mGiInsideCnt.resize( mpGiObjects->size() );
errMsg("MVT","max "<<" "<< max ); // DEBUG
return max;
}

View File

@@ -29,11 +29,10 @@
#include "utilities.h"
#include "ntl_bsptree.h"
#include "ntl_geometryobject.h"
#include "ntl_rndstream.h"
#include "parametrizer.h"
#include "attributes.h"
#include "particletracer.h"
#include "isosurface.h"
class ParticleTracer;
// use which fp-precision for LBM? 1=float, 2=double
#ifdef PRECISION_LBM_SINGLE
@@ -67,6 +66,17 @@ typedef ntlVec3d LbmVec;
#endif
// default to 3dim
#ifndef LBMDIM
#define LBMDIM 3
#endif // LBMDIM
#if LBMDIM==2
#define LBM_DFNUM 9
#else
#define LBM_DFNUM 19
#endif
// conversions (lbm and parametrizer)
template<class T> inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); }
template<class T> inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); }
@@ -75,40 +85,73 @@ template<class T> inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2])
// bubble id type
typedef int BubbleId;
// for both short int/char
// basic cell type distinctions
#define CFUnused (1<< 0)
#define CFEmpty (1<< 1)
#define CFBnd (1<< 2)
#define CFBndNoslip (1<< 3)
#define CFBndFreeslip (1<< 4)
#define CFBndPartslip (1<< 5)
#define CFMbndInflow (1<< 3)
#define CFMbndOutflow (1<< 4)
#define CFFluid (1<< 5)
#define CFInter (1<< 6)
// additional for fluid (needed separately for adaptive grids)
#define CFNoBndFluid (1<< 7)
#define CFNoDelete (1<< 8)
// additional bnd add flags
#define CFBndNoslip (1<< 9)
#define CFBndFreeslip (1<<10)
#define CFBndPartslip (1<<11)
#define CFBndMoving (1<<12)
// additional for fluid/interface
// force symmetry for flag reinit
#define CFNoInterpolSrc (1<< 6)
#define CFFluid (1<< 7)
#define CFInter (1<< 8)
#define CFNoNbFluid (1<< 9)
#define CFNoNbEmpty (1<<10)
#define CFNoDelete (1<<11)
#define CFNoBndFluid (1<<12)
#define CFNoInterpolSrc (1<< 9)
#define CFNoNbFluid (1<<10)
#define CFNoNbEmpty (1<<11)
//! refinement tags
// cell treated normally on coarser grids
#define CFGrNorm (1<<13)
// border cells to be interpolated from finer grid
#define CFGrFromFine (1<<14)
#define CFGrFromCoarse (1<<15)
#define CFGrCoarseInited (1<<16)
// 32k aux border marker
#define CFGrToFine (1<<17)
#define CFMbndInflow (1<<18)
#define CFMbndOutflow (1<<19)
#define CFGrNorm (1<< 9)
#define CFGrCoarseInited (1<<10)
// debug/helper type
#define CFIgnore (1<<20)
// (the following values shouldnt overlap to ensure
// proper coarsening)
// border cells to be interpolated from finer grid
#define CFGrFromFine (1<<13)
// 32k aux border marker
#define CFGrToFine (1<<14)
// also needed on finest level
#define CFGrFromCoarse (1<<15)
// additional refinement tags (coarse grids only?)
// */
// above 24 is used to encode in/outflow object type
#define CFPersistMask (0xFF000000 | CFMbndInflow | CFMbndOutflow)
/*
// TEST
// additional bnd add flags
#define CFBndNoslip (1<< 9)
#define CFBndFreeslip (1<<10)
#define CFBndPartslip (1<<11)
#define CFBndMoving (1<<12)
// additional for fluid/interface
// force symmetry for flag reinit
#define CFNoInterpolSrc (1<<13)
#define CFNoNbFluid (1<<14)
#define CFNoNbEmpty (1<<15)
// additional refinement tags (coarse grids only?)
// cell treated normally on coarser grids
#define CFGrNorm (1<<16)
// border cells to be interpolated from finer grid
#define CFGrFromFine (1<<17)
#define CFGrFromCoarse (1<<18)
#define CFGrCoarseInited (1<<19)
// 32k aux border marker
#define CFGrToFine (1<<20)
// TEST */
// nk
#define CFInvalid (CellFlagType)(1<<31)
@@ -129,14 +172,12 @@ typedef int BubbleId;
// max. no. of cell values for 3d
#define dTotalNum 22
/*****************************************************************************/
/*! a single lbm cell */
/* the template is only needed for
* dimension dependend constants e.g.
* number of df's in model */
template<typename D>
class LbmCellTemplate {
class LbmCellContents {
public:
LbmFloat df[ 27 ]; // be on the safe side here...
LbmFloat rho;
@@ -145,52 +186,8 @@ class LbmCellTemplate {
CellFlagType flag;
BubbleId bubble;
LbmFloat ffrac;
//! test if a flag is set
inline bool test(CellFlagType t) {
return ((flag & t)==t);
}
//! test if any of the given flags is set
inline bool testAny(CellFlagType t) {
return ((flag & t)!=0);
}
//! test if the cell is empty
inline bool isEmpty() {
return (flag == CFEmpty);
}
//! init default values for a certain flag type
inline void initDefaults(CellFlagType type) {
flag = type;
vel = LbmVec(0.0);
for(int l=0; l<D::cDfNum;l++) df[l] = D::dfEquil[l];
if(type & CFFluid) {
rho = mass = ffrac = 1.0;
bubble = -1;
}
else if(type & CFInter) {
rho = mass = ffrac = 0.0;
bubble = 0;
}
else if(type & CFBnd) {
rho = mass = ffrac = 0.0;
bubble = -1;
}
else if(type & CFEmpty) {
rho = mass = ffrac = 0.0;
bubble = 0;
} else {
// ?
rho = mass = ffrac = 0.0;
bubble = -1;
}
}
//TODO add init method?
};
/* struct for the coordinates of a cell in the grid */
typedef struct {
int x,y,z;
@@ -218,13 +215,6 @@ typedef struct {
#define FLUIDDISPGrid 6
#define FLUIDDISPSurface 7
//! settings for a debug display
typedef struct fluidDispSettings_T {
int type; // what to display
bool on; // display enabled?
float scale; // additional scale param
} fluidDispSettings;
/*****************************************************************************/
@@ -265,11 +255,12 @@ class LbmSolverInterface
virtual ~LbmSolverInterface() { };
//! id string of solver
virtual string getIdString() = 0;
//! dimension of solver
virtual int getDimension() = 0;
/*! finish the init with config file values (allocate arrays...) */
virtual bool initializeSolver() =0; //( ntlTree *tree, vector<ntlGeometryObject*> *objects ) = 0;
virtual bool initializeSolver() =0;
/*! notify object that dump is in progress (e.g. for field dump) */
virtual void notifySolverOfDump(int frameNr,char *frameNrStr,string outfilename) = 0;
/*! parse a boundary flag string */
CellFlagType readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed);
@@ -292,7 +283,7 @@ class LbmSolverInterface
#if LBM_USE_GUI==1
/*! show simulation info */
virtual void debugDisplay(fluidDispSettings *) = 0;
virtual void debugDisplay(int) = 0;
#endif
/*! init tree for certain geometry init */
@@ -305,8 +296,8 @@ class LbmSolverInterface
const gfxReal halfCellsize, bool &thinHit, bool recurse);
/*! set render globals, for scene/tree access */
void setRenderGlobals(ntlRenderGlobals *glob) { mpGlob = glob; };
/*! get max. velocity of all objects to initialize as fluid regions */
ntlVec3Gfx getGeoMaxInitialVelocity();
/*! get max. velocity of all objects to initialize as fluid regions, and of all moving objects */
ntlVec3Gfx getGeoMaxMovementVelocity(LbmFloat simtime, LbmFloat stepsize);
/* rt interface functions */
unsigned int getIsoVertexCount() { return mpIso->getIsoVertexCount(); }
@@ -374,6 +365,20 @@ class LbmSolverInterface
//! set desired refinement
inline void setRefinementDesired(int set){ mRefinementDesired = set; }
//! set/get dump velocities flag
inline void setDumpVelocities(bool set) { mDumpVelocities = set; }
inline bool getDumpVelocities() const { return mDumpVelocities; }
//! set/get particle generation prob.
inline void setGenerateParticles(LbmFloat set) { mPartGenProb = set; }
inline LbmFloat getGenerateParticles() const { return mPartGenProb; }
//! set/get dump velocities flag
inline void setDomainBound(std::string set) { mDomainBound = set; }
inline std::string getDomainBound() const { return mDomainBound; }
//! set/get dump velocities flag
inline void setDomainPartSlip(LbmFloat set) { mDomainPartSlipValue = set; }
inline LbmFloat getDomainPartSlip() const { return mDomainPartSlipValue; }
// cell iterator interface
@@ -399,18 +404,19 @@ class LbmSolverInterface
virtual LbmVec getCellVelocity ( CellIdentifierInterface*,int ) = 0;
/*! get equilibrium distribution functions */
virtual LbmFloat getEquilDf ( int ) = 0;
/*! get number of distribution functions */
virtual int getDfNum ( ) = 0;
/*! redundant cell functions */
virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir) = 0;
virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set) = 0;
virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set) = 0;
virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set) = 0;
/*! get velocity directly from position */
virtual ntlVec3Gfx getVelocityAt(float x, float y, float z) = 0;
// gui/output debugging functions
#if LBM_USE_GUI==1
virtual void debugDisplayNode(fluidDispSettings *dispset, CellIdentifier cell ) = 0;
virtual void lbmDebugDisplay(fluidDispSettings *dispset) = 0;
virtual void debugDisplayNode(int dispset, CellIdentifier cell ) = 0;
virtual void lbmDebugDisplay(int dispset) = 0;
virtual void lbmMarkedCellDisplay() = 0;
#endif // LBM_USE_GUI==1
virtual void debugPrintNodeInfo(CellIdentifier cell, int forceSet=-1) = 0;
@@ -484,11 +490,6 @@ class LbmSolverInterface
/*! string for node info debugging output */
string mNodeInfoString;
/*! an own random stream */
ntlRandomStream mRandom;
// geo init vars
// TODO deprecate SimulationObject vars
@@ -534,355 +535,28 @@ class LbmSolverInterface
float mSmoothSurface;
float mSmoothNormals;
//! particle generation probability
LbmFloat mPartGenProb;
//! dump velocities?
bool mDumpVelocities;
// list for marked cells
vector<CellIdentifierInterface *> mMarkedCells;
int mMarkedCellIndex;
//! domain boundary free/no slip type
std::string mDomainBound;
//! part slip value for domain
LbmFloat mDomainPartSlipValue;
//! test vars
// strength of applied force
LbmFloat mTForceStrength;
};
//! shorten static const definitions
#define STCON static const
/*****************************************************************************/
/*! class for solver templating - 3D implementation */
class LbmD3Q19 {
public:
// constructor, init interface
LbmD3Q19() {};
// virtual destructor
virtual ~LbmD3Q19() {};
//! id string of solver
string getIdString() { return string("3D"); }
//! how many dimensions?
STCON int cDimension;
// Wi factors for collide step
STCON LbmFloat cCollenZero;
STCON LbmFloat cCollenOne;
STCON LbmFloat cCollenSqrtTwo;
//! threshold value for filled/emptied cells
STCON LbmFloat cMagicNr2;
STCON LbmFloat cMagicNr2Neg;
STCON LbmFloat cMagicNr;
STCON LbmFloat cMagicNrNeg;
//! size of a single set of distribution functions
STCON int cDfNum;
//! direction vector contain vecs for all spatial dirs, even if not used for LBM model
STCON int cDirNum;
//! distribution functions directions
typedef enum {
cDirInv= -1,
cDirC = 0,
cDirN = 1,
cDirS = 2,
cDirE = 3,
cDirW = 4,
cDirT = 5,
cDirB = 6,
cDirNE = 7,
cDirNW = 8,
cDirSE = 9,
cDirSW = 10,
cDirNT = 11,
cDirNB = 12,
cDirST = 13,
cDirSB = 14,
cDirET = 15,
cDirEB = 16,
cDirWT = 17,
cDirWB = 18
} dfDir;
/* Vector Order 3D:
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
* 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1
* 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1
* 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1
*/
/*! name of the dist. function
only for nicer output */
STCON char* dfString[ 19 ];
/*! index of normal dist func, not used so far?... */
STCON int dfNorm[ 19 ];
/*! index of inverse dist func, not fast, but useful... */
STCON int dfInv[ 19 ];
/*! index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefX[ 19 ];
/*! index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefY[ 19 ];
/*! index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefZ[ 19 ];
/*! dist func vectors */
STCON int dfVecX[ 27 ];
STCON int dfVecY[ 27 ];
STCON int dfVecZ[ 27 ];
/*! arrays as before with doubles */
STCON LbmFloat dfDvecX[ 27 ];
STCON LbmFloat dfDvecY[ 27 ];
STCON LbmFloat dfDvecZ[ 27 ];
/*! principal directions */
STCON int princDirX[ 2*3 ];
STCON int princDirY[ 2*3 ];
STCON int princDirZ[ 2*3 ];
/*! vector lengths */
STCON LbmFloat dfLength[ 19 ];
/*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
static LbmFloat dfEquil[ 19 ];
/*! arrays for les model coefficients */
static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ];
static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ];
}; // LbmData3D
/*****************************************************************************/
//! class for solver templating - 2D implementation
class LbmD2Q9 {
public:
// constructor, init interface
LbmD2Q9() {};
// virtual destructor
virtual ~LbmD2Q9() {};
//! id string of solver
string getIdString() { return string("2D"); }
//! how many dimensions?
STCON int cDimension;
//! Wi factors for collide step
STCON LbmFloat cCollenZero;
STCON LbmFloat cCollenOne;
STCON LbmFloat cCollenSqrtTwo;
//! threshold value for filled/emptied cells
STCON LbmFloat cMagicNr2;
STCON LbmFloat cMagicNr2Neg;
STCON LbmFloat cMagicNr;
STCON LbmFloat cMagicNrNeg;
//! size of a single set of distribution functions
STCON int cDfNum;
STCON int cDirNum;
//! distribution functions directions
typedef enum {
cDirInv= -1,
cDirC = 0,
cDirN = 1,
cDirS = 2,
cDirE = 3,
cDirW = 4,
cDirNE = 5,
cDirNW = 6,
cDirSE = 7,
cDirSW = 8
} dfDir;
/* Vector Order 2D:
* 0 1 2 3 4 5 6 7 8
* 0, 0,0, 1,-1, 1,-1,1,-1
* 0, 1,-1, 0,0, 1,1,-1,-1 */
/* name of the dist. function
only for nicer output */
STCON char* dfString[ 9 ];
/* index of normal dist func, not used so far?... */
STCON int dfNorm[ 9 ];
/* index of inverse dist func, not fast, but useful... */
STCON int dfInv[ 9 ];
/* index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefX[ 9 ];
/* index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefY[ 9 ];
/* index of x reflected dist func for free slip, not valid for all DFs... */
STCON int dfRefZ[ 9 ];
/* dist func vectors */
STCON int dfVecX[ 9 ];
STCON int dfVecY[ 9 ];
/* Z, 2D values are all 0! */
STCON int dfVecZ[ 9 ];
/* arrays as before with doubles */
STCON LbmFloat dfDvecX[ 9 ];
STCON LbmFloat dfDvecY[ 9 ];
/* Z, 2D values are all 0! */
STCON LbmFloat dfDvecZ[ 9 ];
/*! principal directions */
STCON int princDirX[ 2*2 ];
STCON int princDirY[ 2*2 ];
STCON int princDirZ[ 2*2 ];
/* vector lengths */
STCON LbmFloat dfLength[ 9 ];
/* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
static LbmFloat dfEquil[ 9 ];
/*! arrays for les model coefficients */
static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ];
static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ];
}; // LbmData3D
// lbmdimensions
// not needed hereafter
#undef STCON
/*****************************************************************************/
//! class for solver templating - lbgk (srt) model implementation
template<class DQ>
class LbmModelLBGK : public DQ , public LbmSolverInterface {
public:
/*! type for cells contents, needed for cell id interface */
typedef DQ LbmCellContents;
/*! type for cells */
typedef LbmCellTemplate< LbmCellContents > LbmCell;
// constructor
LbmModelLBGK() : DQ(), LbmSolverInterface() {};
// virtual destructor
virtual ~LbmModelLBGK() {};
//! id string of solver
string getIdString() { return DQ::getIdString() + string("lbgk]"); }
/*! calculate length of velocity vector */
static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) {
return ((ux)*DQ::dfDvecX[l]+(uy)*DQ::dfDvecY[l]+(uz)*DQ::dfDvecZ[l]);
};
/*! calculate equilibrium DF for given values */
static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) {
LbmFloat tmp = getVelVecLen(l,ux,uy,uz);
return( DQ::dfLength[l] *(
+ rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz))
+ 3.0 *tmp
+ 9.0/2.0 *(tmp*tmp) )
);
};
/*! relaxation LES functions */
inline LbmFloat getLesNoneqTensorCoeff(
LbmFloat df[],
LbmFloat feq[] ) {
LbmFloat Qo = 0.0;
for(int m=0; m< ((DQ::cDimension*DQ::cDimension)-DQ::cDimension)/2 ; m++) {
LbmFloat qadd = 0.0;
for(int l=1; l<DQ::cDfNum; l++) {
if(DQ::lesCoeffOffdiag[m][l]==0.0) continue;
qadd += DQ::lesCoeffOffdiag[m][l]*(df[l]-feq[l]);
}
Qo += (qadd*qadd);
}
Qo *= 2.0; // off diag twice
for(int m=0; m<DQ::cDimension; m++) {
LbmFloat qadd = 0.0;
for(int l=1; l<DQ::cDfNum; l++) {
if(DQ::lesCoeffDiag[m][l]==0.0) continue;
qadd += DQ::lesCoeffDiag[m][l]*(df[l]-feq[l]);
}
Qo += (qadd*qadd);
}
Qo = sqrt(Qo);
return Qo;
}
inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) {
const LbmFloat tau = 1.0/omega;
const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0);
const LbmFloat C = csmago;
const LbmFloat Csqr = C*C;
LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr);
return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) );
}
// "normal" collision
inline void collideArrays(LbmFloat df[],
LbmFloat &outrho, // out only!
// velocity modifiers (returns actual velocity!)
LbmFloat &mux, LbmFloat &muy, LbmFloat &muz,
LbmFloat omega, LbmFloat csmago,
LbmFloat *newOmegaRet, LbmFloat *newQoRet
) {
LbmFloat rho=df[0];
LbmFloat ux = mux;
LbmFloat uy = muy;
LbmFloat uz = muz;
for(int l=1; l<DQ::cDfNum; l++) {
rho += df[l];
ux += (DQ::dfDvecX[l]*df[l]);
uy += (DQ::dfDvecY[l]*df[l]);
uz += (DQ::dfDvecZ[l]*df[l]);
}
LbmFloat feq[19];
for(int l=0; l<DQ::cDfNum; l++) {
feq[l] = getCollideEq(l,rho,ux,uy,uz);
}
LbmFloat omegaNew;
LbmFloat Qo = 0.0;
if(csmago>0.0) {
Qo = getLesNoneqTensorCoeff(df,feq);
omegaNew = getLesOmega(omega,csmago,Qo);
} else {
omegaNew = omega; // smago off...
}
if(newOmegaRet) *newOmegaRet = omegaNew; // return value for stats
if(newQoRet) *newQoRet = Qo; // return value of non-eq. stress tensor
for(int l=0; l<DQ::cDfNum; l++) {
df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l];
}
mux = ux;
muy = uy;
muz = uz;
outrho = rho;
};
}; // LBGK
#ifdef LBMMODEL_DEFINED
// force compiler error!
ERROR - Dont include several LBM models at once...
#endif
#define LBMMODEL_DEFINED 1
typedef LbmModelLBGK< LbmD2Q9 > LbmBGK2D;
typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D;
// helper function to create consistent grid resolutions
void initGridSizes(int &mSizex, int &mSizey, int &mSizez,
ntlVec3Gfx &mvGeoStart, ntlVec3Gfx &mvGeoEnd,

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,110 @@
*
*****************************************************************************/
#if FSGR_STRICT_DEBUG==1
#define CAUSE_PANIC { this->mPanic=1; /* *((int*)(0x0)) = 1; crash*/ }
#else // FSGR_STRICT_DEBUG==1
#define CAUSE_PANIC { this->mPanic=1; } /*set flag*/
#endif // FSGR_STRICT_DEBUG==1
#if LBM_INCLUDE_TESTSOLVERS!=1
// off for non testing
#define PRECOLLIDE_MODS(rho,ux,uy,uz)
#else // LBM_INCLUDE_TESTSOLVERS!=1
#define PRECOLLIDE_GETPOS \
LbmVec( \
((this->mvGeoEnd[0]-this->mvGeoStart[0])/(LbmFloat)this->mSizex) * (LbmFloat)i + this->mvGeoStart[0], \
((this->mvGeoEnd[1]-this->mvGeoStart[1])/(LbmFloat)this->mSizey) * (LbmFloat)j + this->mvGeoStart[1], \
((this->mvGeoEnd[2]-this->mvGeoStart[2])/(LbmFloat)this->mSizez) * (LbmFloat)k + this->mvGeoStart[2] \
)
// debug modifications of collide vars (testing)
#define PRECOLLIDE_MODS(rho,ux,uy,uz) \
if( (this->mTForceStrength>0.) && (RFLAG(0,i,j,k, mLevel[0].setCurr)&CFNoBndFluid) ) { \
LbmVec pos = PRECOLLIDE_GETPOS; \
LbmVec vel(ux,uy,uz); \
mpTest->mControlParts.modifyVelocity(pos,vel); /* */\
if((i==16)&&(j==10)){ /*debugMarkCell(0,16,10,0);*/ errMsg("FTDEB"," at "<<PRINT_IJK<<" targ:"<<vel<<",len:"<<norm(vel)<<", org:"<<ntlVec3Gfx(ux,uy,uz) ); }\
ux = vel[0]; uy=vel[1]; uz=vel[2]; \
/* test acutal values...? */ \
}
/* end PRECOLLIDE_MODS */
// debug modifications of collide vars (testing)
#define _PRECOLLIDE_MODS(rho,ux,uy,uz) \
if(this->mTForceStrength>0.) { \
LbmVec u(ux,uy,uz); \
LbmVec pos = PRECOLLIDE_GETPOS; \
LbmVec targv = u; const int lev=0; \
mpTest->mControlParts.modifyVelocity(pos,targv); /* */\
LbmVec devia = (targv-u); \
LbmVec set; \
set = u + (devia/this->mOmega) * this->mTForceStrength; /* */\
set = u + targv*this->mTForceStrength; /* */\
ux = set[0]; uy=set[1]; uz=set[2]; \
if(j==10){ errMsg("FTDEB"," at "<<PRINT_IJK<<" targ"<<targv<<","<<norm(targv)<<" set:"<<set<<","<<norm(set) ); }\
}
/* end PRECOLLIDE_MODS */
#endif // LBM_INCLUDE_TESTSOLVERS!=1
/*
\
if((0) && (j>=0.01*this->mSizey) && (j<0.9*this->mSizey)) { \
if((1) && (i>=0.5*this->mSizex) && (i<0.6*this->mSizex)) { \
LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \
LbmVec u(ux,uy,uz); LbmVec t(1., 0., 0.); \
ux = len*t[0]; uy=len*t[1]; uz=len*t[2]; \
} \
if((1) && (i>=0.65*this->mSizex) && (i<0.75*this->mSizex)) { \
LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \
LbmVec u(ux,uy,uz); LbmVec t(0., 1., 0.); \
ux = len*t[0]; uy=len*t[1]; uz=len*t[2]; \
} \
} \
\
if((0) && (j>=0.0*this->mSizey) && (j<1.0 *this->mSizey)) { \
if((1) && (i>=0.6 *this->mSizex) && (i<0.7 *this->mSizex)) { \
LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \
LbmVec u(ux,uy,uz); \
LbmVec t(0., 1., 0.); \
LbmFloat devia = norm(u-t); \
// 0.0001-strong, 0.000001-small,
t = u - (devia/this->mOmega) * this->mTForceStrength; \
// ux = len*t[0]; uy=len*t[1]; uz=len*t[2];
ux = t[0]; uy=t[1]; uz=t[2]; \
//ux= uy= uz= 0.0;
//errMsg("DDDD"," at "<<PRINT_IJK);
} \
} \
if(0) { \
LbmFloat len = sqrtf(ux*ux + uy*uy + uz*uz); \
LbmVec u(ux,uy,uz); \
LbmVec p(i/(LbmFloat)this->mSizex, j/(LbmFloat)this->mSizey, k/(LbmFloat)this->mSizez); \
LbmVec cp(0.5, 0.5, 0.5); \
LbmVec delt = cp - p; \
LbmFloat dist = norm(delt); \
normalize(delt); \
LbmVec tang = cross(delt, LbmVec(0.,0.,1.)); \
normalize(tang); \
const LbmFloat falloff = 5.0; \
LbmVec targv = tang*1.0 * 1.0/(1.0+falloff*dist); \
LbmVec devia = (targv-u); \
LbmFloat devial = norm(devia); \
LbmVec set; \
set = u +targv * this->mTForceStrength; \
set = u + (devia/this->mOmega) * this->mTForceStrength; \
ux = set[0]; uy=set[1]; uz=set[2]; \
if(j==10){ errMsg("FTDEB"," at "<<PRINT_IJK<<" dist:"<<delt<<","<<dist<<" targ"<<targv<<","<<norm(targv)<<" set:"<<set<<","<<norm(set) ); }\
} \
*/
/******************************************************************************
* normal relaxation
@@ -165,20 +269,20 @@
// treatment of freeslip reflection
// used both for OPT and nonOPT
#define DEFAULT_STREAM_FREESLIP(l,invl,mnbf) \
/*const int inv_l = D::dfInv[l];*/ \
/*const int inv_l = this->dfInv[l];*/ \
int nb1 = 0, nb2 = 0; /* is neighbor in this direction an obstacle? */\
LbmFloat newval = 0.0; /* new value for m[l], differs for free/part slip */\
const int dx = D::dfVecX[invl], dy = D::dfVecY[invl], dz = D::dfVecZ[invl]; \
const int dx = this->dfVecX[invl], dy = this->dfVecY[invl], dz = this->dfVecZ[invl]; \
if(dz==0) { \
nb1 = !(RFLAG(lev, i, j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \
nb2 = !(RFLAG(lev, i+dx,j, k, SRCS(lev))&(CFFluid|CFInter)); \
if((nb1)&&(!nb2)) { \
/* x reflection */\
newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \
newval = QCELL(lev, i+dx,j,k,SRCS(lev), this->dfRefX[l]); \
} else \
if((!nb1)&&(nb2)) { \
/* y reflection */\
newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \
newval = QCELL(lev, i,j+dy,k,SRCS(lev), this->dfRefY[l]); \
} else { \
/* normal no slip in all other cases */\
newval = QCELL(lev, i,j,k,SRCS(lev), invl); \
@@ -189,11 +293,11 @@
nb2 = !(RFLAG(lev, i+dx,j,k, SRCS(lev))&(CFFluid|CFInter)); \
if((nb1)&&(!nb2)) { \
/* x reflection */\
newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \
newval = QCELL(lev, i+dx,j,k,SRCS(lev), this->dfRefX[l]); \
} else \
if((!nb1)&&(nb2)) { \
/* z reflection */\
newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \
newval = QCELL(lev, i,j,k+dz,SRCS(lev), this->dfRefZ[l]); \
} else { \
/* normal no slip in all other cases */\
newval = ( QCELL(lev, i,j,k,SRCS(lev), invl) ); \
@@ -205,11 +309,11 @@
nb2 = !(RFLAG(lev, i,j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \
if((nb1)&&(!nb2)) { \
/* y reflection */\
newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \
newval = QCELL(lev, i,j+dy,k,SRCS(lev), this->dfRefY[l]); \
} else \
if((!nb1)&&(nb2)) { \
/* z reflection */\
newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \
newval = QCELL(lev, i,j,k+dz,SRCS(lev), this->dfRefZ[l]); \
} else { \
/* normal no slip in all other cases */\
newval = ( QCELL(lev, i,j,k,SRCS(lev), invl) ); \
@@ -217,7 +321,7 @@
} \
if(mnbf & CFBndPartslip) { /* part slip interpolation */ \
const LbmFloat partv = mObjectPartslips[(int)(mnbf>>24)]; \
m[l] = RAC(ccel, D::dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \
m[l] = RAC(ccel, this->dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \
} else {\
m[l] = newval; /* normal free slip*/\
}\
@@ -228,20 +332,22 @@
#if FSGR_STRICT_DEBUG==1
#define MARKCELLCHECK \
debugMarkCell(lev,i,j,k); D::mPanic=1;
#define STREAMCHECK(ni,nj,nk,nl) \
if((m[l] < -1.0) || (m[l]>1.0)) {\
errMsg("STREAMCHECK","Invalid streamed DF l"<<l<<" value:"<<m[l]<<" at "<<PRINT_IJK<<" from "<<PRINT_VEC(ni,nj,nk)<<" nl"<<(nl)<<\
debugMarkCell(lev,i,j,k); CAUSE_PANIC;
#define STREAMCHECK(id,ni,nj,nk,nl) \
if((m[nl] < -1.0) || (m[nl]>1.0)) {\
errMsg("STREAMCHECK","ID"<<id<<" Invalid streamed DF nl"<<nl<<" value:"<<m[nl]<<" at "<<PRINT_IJK<<" from "<<PRINT_VEC(ni,nj,nk)<<" nl"<<(nl)<<\
" nfc"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setCurr)<<" nfo"<< RFLAG(lev, ni,nj,nk, mLevel[lev].setOther) ); \
/*FORDF0{ errMsg("STREAMCHECK"," at "<<PRINT_IJK<<" df "<<l<<"="<<m[l] ); } */ \
MARKCELLCHECK; \
}
#define COLLCHECK \
if( (rho>2.0) || (rho<-1.0) || (ABS(ux)>1.0) || (ABS(uy)>1.0) |(ABS(uz)>1.0) ) {\
errMsg("COLLCHECK","Invalid collision values r:"<<rho<<" u:"PRINT_VEC(ux,uy,uz)<<" at? "<<PRINT_IJK ); \
/*FORDF0{ errMsg("COLLCHECK"," at? "<<PRINT_IJK<<" df "<<l<<"="<<m[l] ); }*/ \
MARKCELLCHECK; \
}
#else
#define STREAMCHECK(ni,nj,nk,nl)
#define STREAMCHECK(id, ni,nj,nk,nl)
#define COLLCHECK
#endif
@@ -249,121 +355,38 @@
#define DEFAULT_STREAM \
m[dC] = RAC(ccel,dC); \
STREAMCHECK(1, i,j,k, dC); \
FORDF1 { \
CellFlagType nbf = nbflag[ D::dfInv[l] ];\
CellFlagType nbf = nbflag[ this->dfInv[l] ];\
if(nbf & CFBnd) { \
if(nbf & CFBndNoslip) { \
/* no slip, default */ \
m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip */ \
m[l] = RAC(ccel, this->dfInv[l] ); /* noslip */ \
if(nbf&CFBndMoving) m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); /* obs. speed*/ \
STREAMCHECK(2, i,j,k, l); \
} else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \
/* free slip */ \
if(l<=LBMDIM*2) { \
m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip for <dim*2 */ \
m[l] = RAC(ccel, this->dfInv[l] ); STREAMCHECK(3, i,j,k, l); /* noslip for <dim*2 */ \
} else { \
const int inv_l = D::dfInv[l]; \
DEFAULT_STREAM_FREESLIP(l,inv_l,nbf); \
} /* l>2*dim free slip */ \
\
const int inv_l = this->dfInv[l]; \
DEFAULT_STREAM_FREESLIP(l,inv_l,nbf); \
} /* l>2*dim free slip */ \
\
} /* type reflect */\
else {\
errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<D::dfInv[l] ); \
errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<this->dfInv[l] ); \
} \
} else { \
m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \
STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \
STREAMCHECK(4, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \
} \
}
#define _________________DEFAULT_STREAM \
m[dC] = RAC(ccel,dC); \
FORDF1 { \
CellFlagType nbf = nbflag[ D::dfInv[l] ];\
if(nbf & CFBnd) { \
if(nbf & CFBndNoslip) { \
/* no slip, default */ \
m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip */ \
} else if(nbf & (CFBndFreeslip|CFBndPartslip)) { \
/* free slip */ \
if(l<=LBMDIM*2) { \
m[l] = RAC(ccel, D::dfInv[l] ); STREAMCHECK(i,j,k, D::dfInv[l]); /* noslip for <dim*2 */ \
} else { \
const int inv_l = D::dfInv[l]; \
int debug_srcl = -1; \
int nb1 = 0, nb2 = 0; /* is neighbor in this direction an obstacle? */\
LbmFloat newval = 0.0; /* new value for m[l], differs for free/part slip */\
const int dx = D::dfVecX[inv_l], dy = D::dfVecY[inv_l], dz = D::dfVecZ[inv_l]; \
\
if(dz==0) { \
nb1 = !(RFLAG(lev, i, j+dy,k, SRCS(lev))&(CFFluid|CFInter)); /* FIXME add noslip|free|part here */ \
nb2 = !(RFLAG(lev, i+dx,j, k, SRCS(lev))&(CFFluid|CFInter)); \
if((nb1)&&(!nb2)) { \
/* x reflection */\
newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \
debug_srcl = D::dfRefX[l]; \
} else \
if((!nb1)&&(nb2)) { \
/* y reflection */\
newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \
debug_srcl = D::dfRefY[l]; \
} else { \
/* normal no slip in all other cases */\
newval = QCELL(lev, i,j,k,SRCS(lev), inv_l); \
debug_srcl = inv_l; \
} \
} else /* z=0 */\
if(dy==0) { \
nb1 = !(RFLAG(lev, i,j,k+dz, SRCS(lev))&(CFFluid|CFInter)); \
nb2 = !(RFLAG(lev, i+dx,j,k, SRCS(lev))&(CFFluid|CFInter)); \
if((nb1)&&(!nb2)) { \
/* x reflection */\
newval = QCELL(lev, i+dx,j,k,SRCS(lev), D::dfRefX[l]); \
} else \
if((!nb1)&&(nb2)) { \
/* z reflection */\
newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \
} else { \
/* normal no slip in all other cases */\
newval = ( QCELL(lev, i,j,k,SRCS(lev), inv_l) ); \
} \
/* end y=0 */ \
} else { \
/* x=0 */\
nb1 = !(RFLAG(lev, i,j,k+dz, SRCS(lev))&(CFFluid|CFInter)); \
nb2 = !(RFLAG(lev, i,j+dy,k, SRCS(lev))&(CFFluid|CFInter)); \
if((nb1)&&(!nb2)) { \
/* y reflection */\
newval = QCELL(lev, i,j+dy,k,SRCS(lev), D::dfRefY[l]); \
} else \
if((!nb1)&&(nb2)) { \
/* z reflection */\
newval = QCELL(lev, i,j,k+dz,SRCS(lev), D::dfRefZ[l]); \
} else { \
/* normal no slip in all other cases */\
newval = ( QCELL(lev, i,j,k,SRCS(lev), inv_l) ); \
} \
} \
if(nbf & CFBndPartslip) { /* part slip interpolation */ \
const LbmFloat partv = mObjectPartslips[(int)(nbf>>24)]; \
m[l] = RAC(ccel, D::dfInv[l] ) * partv + newval * (1.0-partv); /* part slip */ \
} else {\
m[l] = newval; /* normal free slip*/\
}\
/*if(RFLAG(lev, i,j,k, SRCS(lev))&CFInter) errMsg("FS","at "<<PRINT_IJK<<",l"<<l<<" nb1"<<nb1<<" nb2"<<nb2<<" dx"<<PRINT_VEC(dx,dy,dz)<<",srcl"<<debug_srcl<<" -> "<<newval );*/ \
} /* l>2*dim free slip */ \
\
} /* type reflect */\
else {\
errMsg("LbmFsgrSolver","Invalid Bnd type at "<<PRINT_IJK<<" f"<<convertCellFlagType2String(nbf)<<",nbdir"<<D::dfInv[l] ); \
} \
} else { \
m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); \
STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \
} \
}
// careful ux,uy,uz need to be inited before!
#define DEFAULT_COLLIDE \
D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet, &lcsmqo ); \
this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago, &mDebugOmegaRet, &lcsmqo ); \
CSMOMEGA_STATS(lev,mDebugOmegaRet); \
FORDF0 { RAC(tcel,l) = m[l]; } \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
@@ -372,13 +395,13 @@
m[0] = RAC(ccel,0); \
FORDF1 { /* df0 is set later on... */ \
/* FIXME CHECK INV ? */\
if(RFLAG_NBINV(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \
if(RFLAG_NBINV(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); CAUSE_PANIC; \
} else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \
STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \
STREAMCHECK(8, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \
} \
rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \
rho=m[0]; \
ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \
D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \
this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \
CSMOMEGA_STATS(lev,mDebugOmegaRet); \
FORDF0 { RAC(tcel,l) = m[l]; } \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
@@ -387,6 +410,20 @@
#else // 3D, opt OPT3D==true
// handle mov. obj
#if FSGR_STRICT_DEBUG==1
#define LBMDS_ADDMOV(linv,l) if(nbflag[linv]&CFBndMoving){ \
if(QCELL_NBINV(lev, i, j, k, SRCS(lev), l,dFlux)== (mSimulationTime+this->mpParam->getTimestep()) ) { \
m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); /* obs. speed*/ \
} else { \
CAUSE_PANIC; errMsg("INVALID_MOV_OBJ_TIME"," at "<<PRINT_IJK<<" from l"<<l<<" t="<<mSimulationTime<<" ct="<<QCELL_NBINV(lev, i, j, k, SRCS(lev), l,dFlux)); \
} \
}
#else // FSGR_STRICT_DEBUG==1
#define LBMDS_ADDMOV(linv,l) if(nbflag[linv]&CFBndMoving){ m[l]+=QCELL_NBINV(lev, i, j, k, SRCS(lev), l,l); } /* obs. speed*/
#endif // FSGR_STRICT_DEBUG==1
// default stream opt3d add moving bc val
#define DEFAULT_STREAM \
m[dC] = RAC(ccel,dC); \
/* explicit streaming */ \
@@ -400,26 +437,26 @@
m[dET] = CSRC_ET; m[dEB] = CSRC_EB; m[dWT] = CSRC_WT; m[dWB] = CSRC_WB; \
} else { \
/* explicit streaming, normal velocity always zero for obstacles */ \
if(nbflag[dS ]&CFBnd) { m[dN ] = RAC(ccel,dS ); } else { m[dN ] = CSRC_N ; } \
if(nbflag[dN ]&CFBnd) { m[dS ] = RAC(ccel,dN ); } else { m[dS ] = CSRC_S ; } \
if(nbflag[dW ]&CFBnd) { m[dE ] = RAC(ccel,dW ); } else { m[dE ] = CSRC_E ; } \
if(nbflag[dE ]&CFBnd) { m[dW ] = RAC(ccel,dE ); } else { m[dW ] = CSRC_W ; } \
if(nbflag[dB ]&CFBnd) { m[dT ] = RAC(ccel,dB ); } else { m[dT ] = CSRC_T ; } \
if(nbflag[dT ]&CFBnd) { m[dB ] = RAC(ccel,dT ); } else { m[dB ] = CSRC_B ; } \
if(nbflag[dS ]&CFBnd) { m[dN ] = RAC(ccel,dS ); LBMDS_ADDMOV(dS ,dN ); } else { m[dN ] = CSRC_N ; } \
if(nbflag[dN ]&CFBnd) { m[dS ] = RAC(ccel,dN ); LBMDS_ADDMOV(dN ,dS ); } else { m[dS ] = CSRC_S ; } \
if(nbflag[dW ]&CFBnd) { m[dE ] = RAC(ccel,dW ); LBMDS_ADDMOV(dW ,dE ); } else { m[dE ] = CSRC_E ; } \
if(nbflag[dE ]&CFBnd) { m[dW ] = RAC(ccel,dE ); LBMDS_ADDMOV(dE ,dW ); } else { m[dW ] = CSRC_W ; } \
if(nbflag[dB ]&CFBnd) { m[dT ] = RAC(ccel,dB ); LBMDS_ADDMOV(dB ,dT ); } else { m[dT ] = CSRC_T ; } \
if(nbflag[dT ]&CFBnd) { m[dB ] = RAC(ccel,dT ); LBMDS_ADDMOV(dT ,dB ); } else { m[dB ] = CSRC_B ; } \
\
/* also treat free slip here */ \
if(nbflag[dSW]&CFBnd) { if(nbflag[dSW]&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,nbflag[dSW]);} } else { m[dNE] = CSRC_NE; } \
if(nbflag[dSE]&CFBnd) { if(nbflag[dSE]&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,nbflag[dSE]);} } else { m[dNW] = CSRC_NW; } \
if(nbflag[dNW]&CFBnd) { if(nbflag[dNW]&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,nbflag[dNW]);} } else { m[dSE] = CSRC_SE; } \
if(nbflag[dNE]&CFBnd) { if(nbflag[dNE]&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,nbflag[dNE]);} } else { m[dSW] = CSRC_SW; } \
if(nbflag[dSB]&CFBnd) { if(nbflag[dSB]&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,nbflag[dSB]);} } else { m[dNT] = CSRC_NT; } \
if(nbflag[dST]&CFBnd) { if(nbflag[dST]&CFBndNoslip){ m[dNB] = RAC(ccel,dST); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,nbflag[dST]);} } else { m[dNB] = CSRC_NB; } \
if(nbflag[dNB]&CFBnd) { if(nbflag[dNB]&CFBndNoslip){ m[dST] = RAC(ccel,dNB); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,nbflag[dNB]);} } else { m[dST] = CSRC_ST; } \
if(nbflag[dNT]&CFBnd) { if(nbflag[dNT]&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,nbflag[dNT]);} } else { m[dSB] = CSRC_SB; } \
if(nbflag[dWB]&CFBnd) { if(nbflag[dWB]&CFBndNoslip){ m[dET] = RAC(ccel,dWB); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,nbflag[dWB]);} } else { m[dET] = CSRC_ET; } \
if(nbflag[dWT]&CFBnd) { if(nbflag[dWT]&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,nbflag[dWT]);} } else { m[dEB] = CSRC_EB; } \
if(nbflag[dEB]&CFBnd) { if(nbflag[dEB]&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,nbflag[dEB]);} } else { m[dWT] = CSRC_WT; } \
if(nbflag[dET]&CFBnd) { if(nbflag[dET]&CFBndNoslip){ m[dWB] = RAC(ccel,dET); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,nbflag[dET]);} } else { m[dWB] = CSRC_WB; } \
if(nbflag[dSW]&CFBnd) { if(nbflag[dSW]&CFBndNoslip){ m[dNE] = RAC(ccel,dSW); LBMDS_ADDMOV(dSW,dNE); }else{ DEFAULT_STREAM_FREESLIP(dNE,dSW,nbflag[dSW]);} } else { m[dNE] = CSRC_NE; } \
if(nbflag[dSE]&CFBnd) { if(nbflag[dSE]&CFBndNoslip){ m[dNW] = RAC(ccel,dSE); LBMDS_ADDMOV(dSE,dNW); }else{ DEFAULT_STREAM_FREESLIP(dNW,dSE,nbflag[dSE]);} } else { m[dNW] = CSRC_NW; } \
if(nbflag[dNW]&CFBnd) { if(nbflag[dNW]&CFBndNoslip){ m[dSE] = RAC(ccel,dNW); LBMDS_ADDMOV(dNW,dSE); }else{ DEFAULT_STREAM_FREESLIP(dSE,dNW,nbflag[dNW]);} } else { m[dSE] = CSRC_SE; } \
if(nbflag[dNE]&CFBnd) { if(nbflag[dNE]&CFBndNoslip){ m[dSW] = RAC(ccel,dNE); LBMDS_ADDMOV(dNE,dSW); }else{ DEFAULT_STREAM_FREESLIP(dSW,dNE,nbflag[dNE]);} } else { m[dSW] = CSRC_SW; } \
if(nbflag[dSB]&CFBnd) { if(nbflag[dSB]&CFBndNoslip){ m[dNT] = RAC(ccel,dSB); LBMDS_ADDMOV(dSB,dNT); }else{ DEFAULT_STREAM_FREESLIP(dNT,dSB,nbflag[dSB]);} } else { m[dNT] = CSRC_NT; } \
if(nbflag[dST]&CFBnd) { if(nbflag[dST]&CFBndNoslip){ m[dNB] = RAC(ccel,dST); LBMDS_ADDMOV(dST,dNB); }else{ DEFAULT_STREAM_FREESLIP(dNB,dST,nbflag[dST]);} } else { m[dNB] = CSRC_NB; } \
if(nbflag[dNB]&CFBnd) { if(nbflag[dNB]&CFBndNoslip){ m[dST] = RAC(ccel,dNB); LBMDS_ADDMOV(dNB,dST); }else{ DEFAULT_STREAM_FREESLIP(dST,dNB,nbflag[dNB]);} } else { m[dST] = CSRC_ST; } \
if(nbflag[dNT]&CFBnd) { if(nbflag[dNT]&CFBndNoslip){ m[dSB] = RAC(ccel,dNT); LBMDS_ADDMOV(dNT,dSB); }else{ DEFAULT_STREAM_FREESLIP(dSB,dNT,nbflag[dNT]);} } else { m[dSB] = CSRC_SB; } \
if(nbflag[dWB]&CFBnd) { if(nbflag[dWB]&CFBndNoslip){ m[dET] = RAC(ccel,dWB); LBMDS_ADDMOV(dWB,dET); }else{ DEFAULT_STREAM_FREESLIP(dET,dWB,nbflag[dWB]);} } else { m[dET] = CSRC_ET; } \
if(nbflag[dWT]&CFBnd) { if(nbflag[dWT]&CFBndNoslip){ m[dEB] = RAC(ccel,dWT); LBMDS_ADDMOV(dWT,dEB); }else{ DEFAULT_STREAM_FREESLIP(dEB,dWT,nbflag[dWT]);} } else { m[dEB] = CSRC_EB; } \
if(nbflag[dEB]&CFBnd) { if(nbflag[dEB]&CFBndNoslip){ m[dWT] = RAC(ccel,dEB); LBMDS_ADDMOV(dEB,dWT); }else{ DEFAULT_STREAM_FREESLIP(dWT,dEB,nbflag[dEB]);} } else { m[dWT] = CSRC_WT; } \
if(nbflag[dET]&CFBnd) { if(nbflag[dET]&CFBndNoslip){ m[dWB] = RAC(ccel,dET); LBMDS_ADDMOV(dET,dWB); }else{ DEFAULT_STREAM_FREESLIP(dWB,dET,nbflag[dET]);} } else { m[dWB] = CSRC_WB; } \
}
@@ -522,9 +559,10 @@
+ MSRC_ST - MSRC_SB \
+ MSRC_ET - MSRC_EB \
+ MSRC_WT - MSRC_WB ; \
PRECOLLIDE_MODS(rho,ux,uy,uz); \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
COLL_CALCULATE_DFEQ(lcsmeq); \
COLL_CALCULATE_NONEQTENSOR(lev, MSRC_)\
COLL_CALCULATE_NONEQTENSOR(lev, MSRC_); \
COLL_CALCULATE_CSMOMEGAVAL(lev, lcsmomega); \
CSMOMEGA_STATS(lev,lcsmomega); \
\
@@ -579,6 +617,7 @@
+ MSRC_ST - MSRC_SB \
+ MSRC_ET - MSRC_EB \
+ MSRC_WT - MSRC_WB ; \
PRECOLLIDE_MODS(rho,ux,uy,uz); \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
\
RAC(tcel,dC ) = (1.0-OMEGA(lev))*MSRC_C + OMEGA(lev)*EQC ; \
@@ -624,6 +663,7 @@
+ MSRC_NT + MSRC_NB - MSRC_ST - MSRC_SB + mLevel[lev].gravity[1]; \
uz = MSRC_T - MSRC_B + MSRC_NT - MSRC_NB + MSRC_ST - MSRC_SB \
+ MSRC_ET - MSRC_EB + MSRC_WT - MSRC_WB + mLevel[lev].gravity[2]; \
PRECOLLIDE_MODS(rho,ux,uy,uz); \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
COLL_CALCULATE_DFEQ(lcsmeq); \
COLL_CALCULATE_NONEQTENSOR(lev, MSRC_) \
@@ -664,6 +704,7 @@
+ CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \
uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \
+ CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \
PRECOLLIDE_MODS(rho,ux,uy,uz); \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
COLL_CALCULATE_DFEQ(lcsmeq); \
COLL_CALCULATE_NONEQTENSOR(lev, CSRC_) \
@@ -703,6 +744,7 @@
+ CSRC_NT + CSRC_NB - CSRC_ST - CSRC_SB + mLevel[lev].gravity[1]; \
uz = CSRC_T - CSRC_B + CSRC_NT - CSRC_NB + CSRC_ST - CSRC_SB \
+ CSRC_ET - CSRC_EB + CSRC_WT - CSRC_WB + mLevel[lev].gravity[2]; \
PRECOLLIDE_MODS(rho,ux,uy,uz); \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
RAC(tcel,dC ) = (1.0-OMEGA(lev))*CSRC_C + OMEGA(lev)*EQC ; \
RAC(tcel,dN ) = (1.0-OMEGA(lev))*CSRC_N + OMEGA(lev)*EQN ; \
@@ -734,13 +776,12 @@
#define OPTIMIZED_STREAMCOLLIDE_DEBUG \
m[0] = RAC(ccel,0); \
FORDF1 { /* df0 is set later on... */ \
if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \
if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); CAUSE_PANIC;\
} else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \
STREAMCHECK(i+D::dfVecX[D::dfInv[l]], j+D::dfVecY[D::dfInv[l]],k+D::dfVecZ[D::dfInv[l]], l); \
STREAMCHECK(9, i+this->dfVecX[this->dfInv[l]], j+this->dfVecY[this->dfInv[l]],k+this->dfVecZ[this->dfInv[l]], l); \
} \
rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \
ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \
D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \
this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \
CSMOMEGA_STATS(lev,mDebugOmegaRet); \
FORDF0 { RAC(tcel,l) = m[l]; } \
usqr = 1.5 * (ux*ux + uy*uy + uz*uz); \
@@ -752,13 +793,12 @@
/*DEBUG \
m[0] = RAC(ccel,0); \
FORDF1 { \
if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl"); D::mPanic=1; \
if(RFLAG_NB(lev, i,j,k,SRCS(lev),l)&CFBnd) { errMsg("???", "bnd-err-nobndfl");CAUSE_PANIC; \
} else { m[l] = QCELL_NBINV(lev, i, j, k, SRCS(lev), l, l); } \
} \
errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lcsmomega ); \
rho=m[0]; ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \
ux = mLevel[lev].gravity[0]; uy = mLevel[lev].gravity[1]; uz = mLevel[lev].gravity[2]; \
D::collideArrays( m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \
this->collideArrays(i,j,k, m, rho,ux,uy,uz, OMEGA(lev), mLevel[lev].lcsmago , &mDebugOmegaRet, &lcsmqo ); \
CSMOMEGA_STATS(lev,mDebugOmegaRet); \
*/
#if USE_LES==1
@@ -811,7 +851,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
((( (at))>0.0) && (!(QCELL((alev), (ai),(aj),(ak),mLevel[(alev)].setOther, l) > -1.0 ))) ){ \
errMsg("INVDFSCHECK", " l"<<(alev)<<" "<<PRINT_VEC((ai),(aj),(ak))<<" fc:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )<<" fo:"<<RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )<<" dfl"<<l ); \
debugMarkCell((alev), (ai),(aj),(ak));\
D::mPanic = 1; \
CAUSE_PANIC; \
}
// end ADD_INT_DFSCHECK
#define ADD_INT_FLAGCHECK(alev, ai,aj,ak, at, afac) \
@@ -821,7 +861,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
" fc:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setCurr )) <<\
" fold:"<< convertCellFlagType2String(RFLAG((alev), (ai),(aj),(ak),mLevel[(alev)].setOther )) ); \
debugMarkCell((alev), (ai),(aj),(ak));\
D::mPanic = 1; \
CAUSE_PANIC; \
}
// end ADD_INT_DFSCHECK
@@ -833,7 +873,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
if( (RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) != (CFFluid|CFGrFromCoarse)) ){\
errMsg("INTFLAGUNU_CHECK", PRINT_VEC(i,j,k)<<" child not unused at l"<<(lev+1)<<" "<<PRINT_VEC((ix),(iy),(iz))<<" flag: "<< RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) ); \
debugMarkCell((lev+1), (ix),(iy),(iz));\
D::mPanic = 1; \
CAUSE_PANIC; \
}\
RFLAG(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr) |= CFGrCoarseInited; \
// INTUNUTCHECK
@@ -841,7 +881,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
if( QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) <= 0.0 ){\
errMsg("INVDFCCELLCHECK", "caseId:"<<caseId<<" "<<PRINT_VEC(i,j,k)<<" child inter at "<<PRINT_VEC((ix),(iy),(iz))<<" invalid df "<<l<<" = "<< QCELL(lev+1, (ix),(iy),(iz), mLevel[lev+1].setCurr, l) ); \
debugMarkCell((lev+1), (ix),(iy),(iz));\
D::mPanic = 1; \
CAUSE_PANIC; \
}\
// INTSTRICTCHECK
@@ -858,11 +898,11 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
{ /*LbmFloat rho,ux,uy,uz;*/ \
rho = ux=uy=uz=0.0; \
FORDF0{ LbmFloat m = QCELL(lev,i,j,k, dstSet, l); \
rho += m; ux += (D::dfDvecX[l]*m); uy += (D::dfDvecY[l]*m); uz += (D::dfDvecZ[l]*m); \
if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<<PRINT_IJK<<" m"<<l<<":"<< m ); D::mPanic=1; }\
rho += m; ux += (this->dfDvecX[l]*m); uy += (this->dfDvecY[l]*m); uz += (this->dfDvecZ[l]*m); \
if(ABS(m)>1.0) { errMsg("interpolateCellFromCoarse", "ICFC_DFCHECK cell "<<PRINT_IJK<<" m"<<l<<":"<< m );CAUSE_PANIC;}\
/*errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" df"<<l<<":"<<m );*/ \
} \
/*if(D::mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); }*/ \
/*if(this->mPanic) { errMsg("interpolateCellFromCoarse", "ICFC_DFOUT cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); }*/ \
if(markNbs) errMsg("interpolateCellFromCoarse", " cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); \
/*errMsg("interpolateCellFromCoarse", "ICFC_DFDEBUG cell "<<PRINT_IJK<<" rho:"<<rho<<" u:"<<PRINT_VEC(ux,uy,uz)<<" b"<<PRINT_VEC(betx,bety,betz) ); */\
} \
@@ -872,7 +912,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
/* might also have CFGrCoarseInited (shouldnt be a problem here)*/ \
errMsg("interpolateCellFromCoarse", "CHECK cell not CFGrFromCoarse? "<<PRINT_IJK<<" flag:"<< RFLAG(lev,i,j,k, dstSet)<<" fstr:"<<convertCellFlagType2String( RFLAG(lev,i,j,k, dstSet) )); \
/* FIXME check this warning...? return; this can happen !? */ \
/*D::mPanic = 1;*/ \
/*CAUSE_PANIC;*/ \
} \
// end INTDEBOUT
#else // FSGR_STRICT_DEBUG==1
@@ -894,15 +934,15 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
ADD_INT_DFSCHECK(alev, ai,aj,ak, at, afac, l); \
df *= (afac); \
rho += df; \
ux += (D::dfDvecX[l]*df); \
uy += (D::dfDvecY[l]*df); \
uz += (D::dfDvecZ[l]*df); \
ux += (this->dfDvecX[l]*df); \
uy += (this->dfDvecY[l]*df); \
uz += (this->dfDvecZ[l]*df); \
intDf[l] += df; \
}
// write interpolated dfs back to cell (correct non-eq. parts)
#define IDF_WRITEBACK_ \
FORDF0{ \
LbmFloat eq = D::getCollideEq(l, rho,ux,uy,uz);\
LbmFloat eq = getCollideEq(l, rho,ux,uy,uz);\
QCELL(lev,i,j,k, dstSet, l) = (eq+ (intDf[l]-eq)*mDfScaleDown);\
} \
/* check that all values are ok */ \
@@ -913,18 +953,18 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
LbmFloat feq[LBM_DFNUM]; \
LbmFloat dfScale = mDfScaleDown; \
FORDF0{ \
feq[l] = D::getCollideEq(l, rho,ux,uy,uz); \
feq[l] = getCollideEq(l, rho,ux,uy,uz); \
} \
if(mLevel[lev ].lcsmago>0.0) {\
LbmFloat Qo = D::getLesNoneqTensorCoeff(intDf,feq); \
omegaDst = D::getLesOmega(mLevel[lev+0].omega,mLevel[lev+0].lcsmago,Qo); \
omegaSrc = D::getLesOmega(mLevel[lev-1].omega,mLevel[lev-1].lcsmago,Qo); \
LbmFloat Qo = this->getLesNoneqTensorCoeff(intDf,feq); \
omegaDst = this->getLesOmega(mLevel[lev+0].omega,mLevel[lev+0].lcsmago,Qo); \
omegaSrc = this->getLesOmega(mLevel[lev-1].omega,mLevel[lev-1].lcsmago,Qo); \
} else {\
omegaDst = mLevel[lev+0].omega; \
omegaSrc = mLevel[lev-1].omega;\
} \
\
dfScale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); \
dfScale = (mLevel[lev+0].timestep/mLevel[lev-1].timestep)* (1.0/omegaDst-1.0)/ (1.0/omegaSrc-1.0); \
FORDF0{ \
/*errMsg("SMAGO"," org"<<mDfScaleDown<<" n"<<dfScale<<" qc"<< QCELL(lev,i,j,k, dstSet, l)<<" idf"<<intDf[l]<<" eq"<<feq[l] ); */ \
QCELL(lev,i,j,k, dstSet, l) = (feq[l]+ (intDf[l]-feq[l])*dfScale);\
@@ -1015,7 +1055,7 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
COLL_CALCULATE_CSMOMEGAVAL(lev+0, lcsmDstOmega); \
COLL_CALCULATE_CSMOMEGAVAL(lev-1, lcsmSrcOmega); \
\
lcsmdfscale = (mLevel[lev+0].stepsize/mLevel[lev-1].stepsize)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \
lcsmdfscale = (mLevel[lev+0].timestep/mLevel[lev-1].timestep)* (1.0/lcsmDstOmega-1.0)/ (1.0/lcsmSrcOmega-1.0); \
RAC(dstcell, dC ) = (lcsmeq[dC ] + (intDf[dC ]-lcsmeq[dC ] )*lcsmdfscale);\
RAC(dstcell, dN ) = (lcsmeq[dN ] + (intDf[dN ]-lcsmeq[dN ] )*lcsmdfscale);\
RAC(dstcell, dS ) = (lcsmeq[dS ] + (intDf[dS ]-lcsmeq[dS ] )*lcsmdfscale);\
@@ -1070,3 +1110,104 @@ errMsg("T","QSDM at %d,%d,%d lcsmqo=%25.15f, lcsmomega=%f \n", i,j,k, lcsmqo,lc
#endif// OPT3D==0
/******************************************************************************/
/*! relaxation LES functions */
/******************************************************************************/
inline LbmFloat LbmFsgrSolver::getLesNoneqTensorCoeff(
LbmFloat df[],
LbmFloat feq[] ) {
LbmFloat Qo = 0.0;
for(int m=0; m< ((LBMDIM*LBMDIM)-LBMDIM)/2 ; m++) {
LbmFloat qadd = 0.0;
for(int l=1; l<this->cDfNum; l++) {
if(this->lesCoeffOffdiag[m][l]==0.0) continue;
qadd += this->lesCoeffOffdiag[m][l]*(df[l]-feq[l]);
}
Qo += (qadd*qadd);
}
Qo *= 2.0; // off diag twice
for(int m=0; m<LBMDIM; m++) {
LbmFloat qadd = 0.0;
for(int l=1; l<this->cDfNum; l++) {
if(this->lesCoeffDiag[m][l]==0.0) continue;
qadd += this->lesCoeffDiag[m][l]*(df[l]-feq[l]);
}
Qo += (qadd*qadd);
}
Qo = sqrt(Qo);
return Qo;
};
inline LbmFloat LbmFsgrSolver::getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) {
const LbmFloat tau = 1.0/omega;
const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0);
const LbmFloat C = csmago;
const LbmFloat Csqr = C*C;
LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr);
return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) );
}
#define DEBUG_CALCPRINTCELL(str,df) {\
LbmFloat rho=df[0], ux=0., uy=0., uz=0.; \
for(int l=1; l<this->cDfNum; l++) { \
rho += df[l]; \
ux += (this->dfDvecX[l]*df[l]); \
uy += (this->dfDvecY[l]*df[l]); \
uz += (this->dfDvecZ[l]*df[l]); \
} \
errMsg("DEBUG_CALCPRINTCELL",">"<<str<<" rho="<<rho<<" vel="<<ntlVec3Gfx(ux,uy,uz) ); \
} /* END DEBUG_CALCPRINTCELL */
// "normal" collision
inline void LbmFsgrSolver::collideArrays(
int i, int j, int k, // position - more for debugging
LbmFloat df[],
LbmFloat &outrho, // out only!
// velocity modifiers (returns actual velocity!)
LbmFloat &mux, LbmFloat &muy, LbmFloat &muz,
LbmFloat omega, LbmFloat csmago,
LbmFloat *newOmegaRet, LbmFloat *newQoRet
) {
LbmFloat rho=df[0];
LbmFloat ux = mux;
LbmFloat uy = muy;
LbmFloat uz = muz;
for(int l=1; l<this->cDfNum; l++) {
rho += df[l];
ux += (this->dfDvecX[l]*df[l]);
uy += (this->dfDvecY[l]*df[l]);
uz += (this->dfDvecZ[l]*df[l]);
}
PRECOLLIDE_MODS(rho,ux,uy,uz);
LbmFloat feq[19];
for(int l=0; l<this->cDfNum; l++) {
feq[l] = getCollideEq(l,rho,ux,uy,uz);
}
LbmFloat omegaNew;
LbmFloat Qo = 0.0;
if(csmago>0.0) {
Qo = getLesNoneqTensorCoeff(df,feq);
omegaNew = getLesOmega(omega,csmago,Qo);
} else {
omegaNew = omega; // smago off...
}
if(newOmegaRet) *newOmegaRet = omegaNew; // return value for stats
if(newQoRet) *newQoRet = Qo; // return value of non-eq. stress tensor
for(int l=0; l<this->cDfNum; l++) {
df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l];
}
if((i==16)&&(j==10)) DEBUG_CALCPRINTCELL( "2dcoll "<<PRINT_IJK, df);
mux = ux;
muy = uy;
muz = uz;
outrho = rho;
};

File diff suppressed because it is too large Load Diff

View File

@@ -30,8 +30,8 @@ extern "C" void simulateThreadIncreaseFrame(void);
extern "C" SDL_mutex *globalBakeLock;
// global state variables
extern "C" int globalBakeState;
extern "C" int globalBakeFrame;
#endif // ELBEEM_BLENDER==1
//extern "C" int globalBakeFrame; not needed...?
#endif // ELBEEM_PLUGIN==1
#include "utilities.h"
@@ -184,8 +184,9 @@ myTime_t getTime()
string getTimeString(myTime_t usecs) {
std::ostringstream ret;
//myTime_t us = usecs % 1000;
myTime_t ms = usecs / (60*1000);
myTime_t ss = (usecs / 1000) - (ms*60);
myTime_t ms = (myTime_t)( (double)usecs / (60.0*1000.0) );
myTime_t ss = (myTime_t)( ((double)usecs / 1000.0) - ((double)ms*60.0) );
int ps = (int)( ((double)usecs - (double)ss*1000.0)/10.0 );
//ret.setf(ios::showpoint|ios::fixed);
//ret.precision(5); ret.width(7);
@@ -193,7 +194,13 @@ string getTimeString(myTime_t usecs) {
if(ms>0) {
ret << ms<<"m"<< ss<<"s" ;
} else {
ret << ss<<"s" ;
if(ps>0) {
ret << ss<<".";
if(ps<10) { ret <<"0"; }
ret <<ps<<"s" ;
} else {
ret << ss<<"s" ;
}
}
return ret.str();
}
@@ -368,6 +375,7 @@ double elbeemEstimateMemreq(int res,
#if ELBEEM_BLENDER==1
// Blender state sync
void setGlobalBakeState(int set) {
SDL_mutexP(globalBakeLock);
globalBakeState = set;

View File

@@ -27,13 +27,13 @@ bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, string checker);
/* debugging outputs , debug level 0 (off) to 10 (max) */
#ifdef ELBEEM_BLENDER
#ifdef ELBEEM_PLUGIN
#define DEBUG 0
void setGlobalBakeState(int set);
int getGlobalBakeState(void);
#else // ELBEEM_BLENDER
#else // ELBEEM_PLUGIN
#define DEBUG 10
#endif // ELBEEM_BLENDER
#endif // ELBEEM_PLUGIN
extern "C" int gDebugLevel;
// state of the simulation world

View File

@@ -555,26 +555,46 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]
mdm->freeNors = 0;
mdm->freeVerts = 0;
if (vertCos) {
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
(ob->fluidsimSettings->meshSurface) &&
(me->totvert == ((Mesh *)(ob->fluidsimSettings->meshSurface))->totvert) ) {
// dont recompute for fluidsim mesh, use from readBobjgz
// TODO? check for modifiers!?
int i;
/* copy the original verts to preserve flag settings; if this is too
* costly, must at least use MEM_callocN to clear flags */
mdm->verts = MEM_dupallocN( me->mvert );
for (i=0; i<me->totvert; i++) {
VECCOPY(mdm->verts[i].co, vertCos[i]);
}
mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
mdm->freeNors = 1;
mdm->freeVerts = 1;
for (i=0; i<me->totvert; i++) {
MVert *mv= &mdm->verts[i];
MVert *fsv;
fsv = &ob->fluidsimSettings->meshSurfNormals[i];
VECCOPY(mv->no, fsv->no);
//mv->no[0]= 30000; mv->no[1]= mv->no[2]= 0; // DEBUG fixed test normals
}
} else {
// recompute normally
if (vertCos) {
int i;
/* copy the original verts to preserve flag settings; if this is too
* costly, must at least use MEM_callocN to clear flags */
mdm->verts = MEM_dupallocN( me->mvert );
for (i=0; i<me->totvert; i++) {
VECCOPY(mdm->verts[i].co, vertCos[i]);
}
mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
mdm->freeNors = 1;
mdm->freeVerts = 1;
} else {
// XXX this is kinda hacky because we shouldn't really be editing
// the mesh here, however, we can't just call mesh_build_faceNormals(ob)
// because in the case when a key is applied to a mesh the vertex normals
// would never be correctly computed.
mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
mdm->freeNors = 1;
}
mesh_calc_normals(mdm->verts, me->totvert, me->mface, me->totface, &mdm->nors);
mdm->freeNors = 1;
}
} // fs TEST
return (DerivedMesh*) mdm;
}
@@ -2072,8 +2092,9 @@ void writeBobjgz(char *filename, struct Object *ob)
wri = dlm->totvert;
gzwrite(gzf, &wri, sizeof(wri));
for(i=0; i<wri;i++) {
VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
Mat4MulVecfl(ob->obmat, vec);
VECCOPY(vec, dlm->mvert[i].co);
//VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
//Mat4MulVecfl(ob->obmat, vec);
for(j=0; j<3; j++) {
wrf = vec[j];
gzwrite(gzf, &wrf, sizeof( wrf ));
@@ -2087,7 +2108,8 @@ void writeBobjgz(char *filename, struct Object *ob)
for(i=0; i<wri;i++) {
VECCOPY(vec, dlm->mvert[i].no);
// FIXME divide? mv->no[0]= (short)(no[0]*32767.0);
Mat3MulVecfl(rotmat, vec);
//VECCOPY(vec, dlm->mvert[i].no);
//Mat3MulVecfl(rotmat, vec);
Normalise(vec);
for(j=0; j<3; j++) {
wrf = vec[j];
@@ -2130,8 +2152,63 @@ void writeBobjgz(char *filename, struct Object *ob)
dm->release(dm);
}
void initElbeemMesh(struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles)
{
DispListMesh *dlm = NULL;
DerivedMesh *dm = NULL;
MFace *mface = NULL;
int countTris=0, i;
float *verts;
int *tris;
dm = mesh_create_derived_render(ob);
if(!dm) { *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
dlm = dm->convertToDispListMesh(dm, 1);
if(!dlm) { dm->release(dm); *numVertices = *numTriangles = 0; *triangles=NULL; *vertices=NULL; }
mface = dlm->mface;
*numVertices = dlm->totvert;
verts = MEM_callocN( dlm->totvert*3*sizeof(float), "elbeemmesh_vertices");
for(i=0; i<dlm->totvert; i++) {
VECCOPY( &verts[i*3], dlm->mvert[i].co);
}
*vertices = verts;
for(i=0; i<dlm->totface; i++) {
countTris++;
if(mface[i].v4) { countTris++; }
}
*numTriangles = countTris;
tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
countTris = 0;
for(i=0; i<dlm->totface; i++) {
int face[4];
face[0] = mface[i].v1;
face[1] = mface[i].v2;
face[2] = mface[i].v3;
face[3] = mface[i].v4;
tris[countTris*3+0] = face[0];
tris[countTris*3+1] = face[1];
tris[countTris*3+2] = face[2];
countTris++;
if(face[3]) {
tris[countTris*3+0] = face[0];
tris[countTris*3+1] = face[2];
tris[countTris*3+2] = face[3];
countTris++;
}
}
*triangles = tris;
if(dlm) displistmesh_free(dlm);
dm->release(dm);
}
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
{
int wri,i,j;
char debugStrBuffer[256];
@@ -2211,9 +2288,13 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
for(i=0; i<newmesh->totvert;i++) {
for(j=0; j<3; j++) {
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
newmesh->mvert[i].no[j] = wrf*32767.0;
newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
//newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
}
//fprintf(stderr," DEBDPCN nm%d, %d = %d,%d,%d \n",
//(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
}
//fprintf(stderr," DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
/* compute no. of triangles */
@@ -2258,6 +2339,61 @@ Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
return newmesh;
}
/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
void readVelgz(char *filename, Object *srcob)
{
char debugStrBuffer[256];
int wri, i, j;
float wrf;
gzFile gzf;
MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
int len = strlen(filename);
Mesh *mesh = srcob->data;
// mesh and vverts have to be valid from loading...
// clean up in any case
for(i=0; i<mesh->totvert;i++) {
for(j=0; j<3; j++) {
vverts[i].co[j] = 0.;
}
}
if(srcob->fluidsimSettings->typeFlags&OB_FSDOMAIN_NOVECGEN) return;
if(len<7) {
//printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
return;
}
// .bobj.gz , correct filename
// 87654321
filename[len-6] = 'v';
filename[len-5] = 'e';
filename[len-4] = 'l';
snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer);
gzf = gzopen(filename, "rb");
if (!gzf) {
//printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
return;
}
gzread(gzf, &wri, sizeof( wri ));
if(wri != mesh->totvert) {
//printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
return;
}
for(i=0; i<mesh->totvert;i++) {
for(j=0; j<3; j++) {
gzread(gzf, &wrf, sizeof( wrf ));
vverts[i].co[j] = wrf;
}
//if(i<20) fprintf(stderr, "GZ_VELload %d = %f,%f,%f \n",i,vverts[i].co[0],vverts[i].co[1],vverts[i].co[2]); // DEBUG
}
gzclose(gzf);
}
/* ***************************** fluidsim derived mesh ***************************** */
@@ -2297,6 +2433,9 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
if(srcob->data == srcob->fluidsimSettings->meshSurface)
srcob->data = srcob->fluidsimSettings->orgMesh;
srcob->fluidsimSettings->meshSurface = NULL;
if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
srcob->fluidsimSettings->meshSurfNormals = NULL;
}
// init bounding box
@@ -2305,7 +2444,7 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
lastBB[0] = bbSize[0]; // TEST
lastBB[1] = bbSize[1];
lastBB[2] = bbSize[2];
fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize);
fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
// check free fsmesh... TODO
if(!useRenderParams) {
@@ -2314,7 +2453,8 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
displaymode = srcob->fluidsimSettings->renderDisplayMode;
}
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n",
srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
elbeemDebugOut(debugStrBuffer); // debug
strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
@@ -2335,7 +2475,11 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile); // debug
elbeemDebugOut(debugStrBuffer); // debug
mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh );
if(displaymode!=2) { // dont add bounding box for final
mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
} else {
mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
}
if(!mesh) {
// display org. object upon failure
srcob->data = srcob->fluidsimSettings->orgMesh;
@@ -2347,13 +2491,27 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
}
srcob->fluidsimSettings->meshSurface = mesh;
srcob->data = mesh;
srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
// load vertex velocities, if they exist...
// TODO? use generate flag as loading flag as well?
// warning, needs original .bobj.gz mesh loading filename
if(displaymode==3) {
readVelgz(targetFile, srcob);
} else {
// no data for preview, only clear...
int i,j;
for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }}
}
//fprintf(stderr,"LOADFLM DEBXHCH fs=%d 3:%d,%d,%d \n", (int)mesh, ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[0], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[1], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[2]);
return;
}
/* helper function */
/* init axis aligned BB for mesh object */
void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
/*RET*/ float start[3], /*RET*/ float size[3] )
/*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
{
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
float bbex=1.0, bbey=1.0, bbez=1.0;
@@ -2388,6 +2546,25 @@ void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
size[1] = bbey-bbsy;
size[2] = bbez-bbsz;
}
// init bounding box mesh?
if(bbmesh) {
int i,j;
Mesh *newmesh = NULL;
if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
else { newmesh = *bbmesh; }
newmesh->totvert = 8;
if(!newmesh->mvert) newmesh->mvert = MEM_callocN(sizeof(MVert)*newmesh->totvert, "fluidsimBBMesh_bobjvertices");
for(i=0; i<8; i++) {
for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j];
}
newmesh->totface = 6;
if(!newmesh->mface) newmesh->mface = MEM_callocN(sizeof(MFace)*newmesh->totface, "fluidsimBBMesh_bobjfaces");
*bbmesh = newmesh;
}
}

View File

@@ -1610,8 +1610,8 @@ static void dag_object_time_update_flags(Object *ob)
}
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings)) {
// fluidsimSettings might not be initialized during load...
if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
ob->recalc |= OB_RECALC_DATA; // NT
if(ob->fluidsimSettings->type & (OB_FLUIDSIM_DOMAIN|OB_FLUIDSIM_PARTICLE)) {
ob->recalc |= OB_RECALC_DATA; // NT FSPARTICLE
}
}
break;

View File

@@ -51,6 +51,11 @@
#include "DNA_object_force.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
// FSPARTICLE
#include "DNA_object_fluidsim.h"
#include "LBM_fluidsim.h"
#include <zlib.h>
#include <string.h>
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
@@ -1594,6 +1599,7 @@ void build_particle_system(Object *ob)
float *volengths= NULL, *folengths= NULL;
int deform=0, a, totpart, paf_sta, paf_end;
int waitcursor_set= 0, totvert, totface, curface, curvert;
int readMask =0, activeParts;
/* return conditions */
if(ob->type!=OB_MESH) return;
@@ -1604,6 +1610,104 @@ void build_particle_system(Object *ob)
if(paf->keys) MEM_freeN(paf->keys); /* free as early as possible, for returns */
paf->keys= NULL;
// FSPARTICLE all own created...
if( (1) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(ob->fluidsimSettings) &&
(ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) {
char *suffix = "fluidsurface_particles_#";
char *suffix2 = ".gz";
char filename[256];
int curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
int j, numFileParts;
gzFile gzf;
float vel[3];
if(ob==G.obedit) { // off...
paf->totpart = 1;
return;
}
// ok, start loading
strcpy(filename, ob->fluidsimSettings->surfdataPath);
strcat(filename, suffix);
BLI_convertstringcode(filename, G.sce, curFrame); // fixed #frame-no
strcat(filename, suffix2);
gzf = gzopen(filename, "rb");
if (!gzf) {
//char debugStrBuffer[256];
//define win32... snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s'\n", filename);
//elbeemDebugOut(debugStrBuffer);
paf->totpart = 1;
return;
}
gzread(gzf, &totpart, sizeof(totpart));
numFileParts = totpart;
totpart = (G.rendering)?totpart:(paf->disp*totpart)/100;
paf->totpart= totpart;
paf->totkey= 1;
/* initialize particles */
new_particle(paf);// ?
ftime = 0.0;
dtime= 0.0f;
// set up reading mask
//for(j=1; j<=4; j++ ){ if(ob->fluidsimSettings->guiDisplayMode&j) readMask |= (1<<j); }
readMask = ob->fluidsimSettings->guiDisplayMode;
activeParts=0;
// FIXME only allocate needed ones?
//fprintf(stderr,"FSPARTICLE debug set %s , tot%d mask=%d \n", filename, totpart, readMask );
for(a=0; a<totpart; a++, ftime+=dtime) {
int ptype=0;
short shsize=0;
float convertSize=0.0;
gzread(gzf, &ptype, sizeof( ptype ));
//if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d t=%d , mask=%d , active%d\n", filename, a, ptype, readMask, activeParts );
if(ptype&readMask) {
activeParts++;
pa= new_particle(paf);
pa->time= ftime;
pa->lifetime= ftime + G.scene->r.efra +1.0;
pa->co[0] = 0.0;
pa->co[1] =
pa->co[2] = 1.0*(float)a / (float)totpart;
pa->no[0] = pa->no[1] = pa->no[2] = 0.0;
pa->mat_nr= paf->omat;
gzread(gzf, &convertSize, sizeof( float ));
// convert range of 1.0-10.0 to shorts 1000-10000)
shsize = (short)(convertSize*1000.0);
pa->rt = shsize;
//if(a<200) fprintf(stderr,"SREAD %f %d %d \n",convertSize,shsize,pa->rt);
for(j=0; j<3; j++) {
float wrf;
gzread(gzf, &wrf, sizeof( wrf ));
pa->co[j] = wrf;
//fprintf(stderr,"Rj%d ",j);
}
for(j=0; j<3; j++) {
float wrf;
gzread(gzf, &wrf, sizeof( wrf ));
vel[j] = wrf;
}
} else {
// skip...
for(j=0; j<2*3+1; j++) {
float wrf; gzread(gzf, &wrf, sizeof( wrf ));
}
}
//fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime );
}
gzclose( gzf );
totpart = paf->totpart = activeParts;
//fprintf(stderr,"PARTOBH debug %s %d \n", ob->id.name, totpart); // DEBUG
return;
}
if(paf->end < paf->sta) return;
if( (paf->flag & PAF_OFACE) && (paf->flag & PAF_FACE)==0) return;

View File

@@ -171,6 +171,13 @@ int snd_ar[SND_TOTIPO]= {
SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN
};
int fluidsim_ar[FLUIDSIM_TOTIPO]= {
FLUIDSIM_VISC, FLUIDSIM_TIME,
FLUIDSIM_GRAV_X , FLUIDSIM_GRAV_Y , FLUIDSIM_GRAV_Z ,
FLUIDSIM_VEL_X , FLUIDSIM_VEL_Y , FLUIDSIM_VEL_Z ,
FLUIDSIM_ACTIVE
};
float frame_to_float(int cfra) /* see also bsystem_time in object.c */

View File

@@ -2371,6 +2371,10 @@ static void lib_link_object(FileData *fd, Main *main)
act= act->next;
}
if(ob->fluidsimSettings) {
ob->fluidsimSettings->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
}
lib_link_scriptlink(fd, &ob->id, &ob->scriptlink);
lib_link_modifiers(fd, ob);
}

View File

@@ -58,6 +58,7 @@ char *getname_cu_ei(int nr);
char *getname_la_ei(int nr);
char *getname_cam_ei(int nr);
char *getname_snd_ei(int nr);
char *getname_fluidsim_ei(int nr);
struct EditIpo *get_active_editipo(void);

View File

@@ -252,8 +252,9 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
/* Fluidsim button defines */
#define B_FLUIDSIM_BAKE 1450
#define B_FLUIDSIM_SELDIR 1451
#define B_FLUIDSIM_SELDIR 1451
#define B_FLUIDSIM_FORCEREDRAW 1452
#define B_FLUIDSIM_MAKEPART 1453
#define B_GROUP_RELINK 1460

View File

@@ -127,6 +127,7 @@ typedef struct Library {
#define ID_AR MAKE_ID2('A', 'R')
#define ID_AC MAKE_ID2('A', 'C')
#define ID_SCRIPT MAKE_ID2('P', 'Y')
#define ID_FLUIDSIM MAKE_ID2('F', 'S')
#define ID_NT MAKE_ID2('N', 'T')
/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */

View File

@@ -326,6 +326,26 @@ typedef short IPO_Channel;
#define CO_ROLL 9
*/
/* ******************** */
/* fluidsim ipos NT */
#define FLUIDSIM_TOTIPO 9
#define FLUIDSIM_TOTNAM 9
#define FLUIDSIM_VISC 1
#define FLUIDSIM_TIME 2
#define FLUIDSIM_GRAV_X 3
#define FLUIDSIM_GRAV_Y 4
#define FLUIDSIM_GRAV_Z 5
#define FLUIDSIM_VEL_X 6
#define FLUIDSIM_VEL_Y 7
#define FLUIDSIM_VEL_Z 8
#define FLUIDSIM_ACTIVE 9
/* these are IpoCurve specific */
/* **************** IPO ********************* */

View File

@@ -33,12 +33,15 @@
#ifndef DNA_OBJECT_FLUIDSIM_H
#define DNA_OBJECT_FLUIDSIM_H
#include "DNA_ID.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Mesh;
struct Ipo;
struct MVert;
typedef struct FluidsimSettings {
/* domain,fluid or obstacle */
@@ -87,6 +90,24 @@ typedef struct FluidsimSettings {
/* store start coords of axis aligned bounding box together with size */
/* values are inited during derived mesh display */
float bbStart[3], bbSize[3];
/* animated params */
struct Ipo *ipo;
/* additional flags depending on the type, lower short contains flags
* to check validity, higher short additional flags */
int typeFlags;
/* boundary "stickiness" for part slip values */
float partSlipValue;
/* particle generation - on if >0, then determines amount */
float generateParticles, dummy;
/* particle display - size scaling, and alpha influence */
float particleInfSize, particleInfAlpha;
/* save fluidsurface normals in mvert.no, and surface vertex velocities (if available) in mvert.co */
struct MVert *meshSurfNormals;
} FluidsimSettings;
/* ob->fluidsimSettings defines */
@@ -96,6 +117,24 @@ typedef struct FluidsimSettings {
#define OB_FLUIDSIM_OBSTACLE 8
#define OB_FLUIDSIM_INFLOW 16
#define OB_FLUIDSIM_OUTFLOW 32
#define OB_FLUIDSIM_PARTICLE 64
#define OB_TYPEFLAG_START 16
#define OB_FSGEO_THIN (1<<(OB_TYPEFLAG_START+1))
#define OB_FSBND_NOSLIP (1<<(OB_TYPEFLAG_START+2))
#define OB_FSBND_PARTSLIP (1<<(OB_TYPEFLAG_START+3))
#define OB_FSBND_FREESLIP (1<<(OB_TYPEFLAG_START+4))
#define OB_FSINFLOW_LOCALCOORD (1<<(OB_TYPEFLAG_START+5))
#define OB_FSDOMAIN_NOVECGEN (1<<(OB_TYPEFLAG_START+6))
// guiDisplayMode particle flags
#define OB_FSDOM_GEOM 1
#define OB_FSDOM_PREVIEW 2
#define OB_FSDOM_FINAL 3
#define OB_FSPART_BUBBLE (1<<1)
#define OB_FSPART_DROP (1<<2)
#define OB_FSPART_NEWPART (1<<3)
#define OB_FSPART_FLOAT (1<<4)
#ifdef __cplusplus
}

View File

@@ -56,6 +56,7 @@
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_object_fluidsim.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_view3d_types.h"
@@ -447,6 +448,104 @@ static void calc_vertexnormals(Render *re, int startvert, int startvlak, int do_
}
}
// NT same as calc_vertexnormals, but dont modify the existing vertex normals
// only recalculate other render data. If this is at some point used for other things than fluidsim,
// this could be made on option for the normal calc_vertexnormals
static void calc_fluidsimnormals(Render *re, int startvert, int startvlak, int do_tangent)
{
int a;
/* dont clear vertex normals here */
// OFF for(a=startvert; a<re->totvert; a++) { VertRen *ver= RE_findOrAddVert(re, a); ver->n[0]=ver->n[1]=ver->n[2]= 0.0; }
/* calculate cos of angles and point-masses, use as weight factor to add face normal to vertex */
for(a=startvlak; a<re->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(re, a);
if(vlr->flag & ME_SMOOTH) {
VertRen *adrve1= vlr->v1;
VertRen *adrve2= vlr->v2;
VertRen *adrve3= vlr->v3;
VertRen *adrve4= vlr->v4;
float n1[3], n2[3], n3[3], n4[3];
float fac1, fac2, fac3, fac4=0.0f;
VecSubf(n1, adrve2->co, adrve1->co);
Normalise(n1);
VecSubf(n2, adrve3->co, adrve2->co);
Normalise(n2);
if(adrve4==NULL) {
VecSubf(n3, adrve1->co, adrve3->co);
Normalise(n3);
fac1= saacos(-n1[0]*n3[0]-n1[1]*n3[1]-n1[2]*n3[2]);
fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
}
else {
VecSubf(n3, adrve4->co, adrve3->co);
Normalise(n3);
VecSubf(n4, adrve1->co, adrve4->co);
Normalise(n4);
fac1= saacos(-n4[0]*n1[0]-n4[1]*n1[1]-n4[2]*n1[2]);
fac2= saacos(-n1[0]*n2[0]-n1[1]*n2[1]-n1[2]*n2[2]);
fac3= saacos(-n2[0]*n3[0]-n2[1]*n3[1]-n2[2]*n3[2]);
fac4= saacos(-n3[0]*n4[0]-n3[1]*n4[1]-n3[2]*n4[2]);
if(!(vlr->flag & R_NOPUNOFLIP)) {
if( contrpuntnormr(vlr->n, adrve4->n) ) fac4= -fac4;
}
}
if(do_tangent)
calc_tangent_vector(re, vlr, fac1, fac2, fac3, fac4);
}
}
/* do solid faces */
for(a=startvlak; a<re->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(re, a);
if((vlr->flag & ME_SMOOTH)==0) {
float *f1= vlr->v1->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
f1= vlr->v2->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
f1= vlr->v3->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
if(vlr->v4) {
f1= vlr->v4->n;
if(f1[0]==0.0 && f1[1]==0.0 && f1[2]==0.0) VECCOPY(f1, vlr->n);
}
}
}
/* normalise vertex normals */
for(a=startvert; a<re->totvert; a++) {
VertRen *ver= RE_findOrAddVert(re, a);
Normalise(ver->n);
if(do_tangent) {
float *tav= RE_vertren_get_tangent(re, ver, 0);
if(tav) Normalise(tav);
}
}
/* vertex normal (puno) switch flags for during render */
for(a=startvlak; a<re->totvlak; a++) {
VlakRen *vlr= RE_findOrAddVlak(re, a);
if((vlr->flag & R_NOPUNOFLIP)==0) {
VertRen *adrve1= vlr->v1;
VertRen *adrve2= vlr->v2;
VertRen *adrve3= vlr->v3;
VertRen *adrve4= vlr->v4;
vlr->puno &= ~15;
if ((vlr->n[0]*adrve1->n[0]+vlr->n[1]*adrve1->n[1]+vlr->n[2]*adrve1->n[2])<0.0) vlr->puno= 1;
if ((vlr->n[0]*adrve2->n[0]+vlr->n[1]*adrve2->n[1]+vlr->n[2]*adrve2->n[2])<0.0) vlr->puno+= 2;
if ((vlr->n[0]*adrve3->n[0]+vlr->n[1]*adrve3->n[1]+vlr->n[2]*adrve3->n[2])<0.0) vlr->puno+= 4;
if(adrve4) {
if((vlr->n[0]*adrve4->n[0]+vlr->n[1]*adrve4->n[1]+vlr->n[2]*adrve4->n[2])<0.0) vlr->puno+= 8;
}
}
}
}
/* ------------------------------------------------------------------------- */
/* Autosmoothing: */
/* ------------------------------------------------------------------------- */
@@ -742,6 +841,12 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
float xn, yn, zn, imat[3][3], tmat[4][4], mat[4][4], hasize, stime, ptime, ctime, vec[3], vec1[3], view[3], nor[3];
int a, mat_nr=1, seed;
int useFluidsimParticles = 0; // FSPARTICLE
float haloScale = 1.0; //NT scale halos
float iniAlpha = 0.0; // restore material alpha
pa= paf->keys;
if(pa==NULL || paf->disp!=100) {
build_particle_system(ob);
@@ -767,6 +872,10 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
else ptime= 0.0;
ctime= bsystem_time(ob, 0, (float)re->scene->r.cfra, ptime);
seed= ma->seed1;
if( (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE)) {
useFluidsimParticles = 1;
iniAlpha = ma->alpha;
}
for(a=0; a<paf->totpart; a++, pa+=paf->totkey, seed++) {
@@ -810,7 +919,16 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
execute_ipo((ID *)ma, ma->ipo);
}
hasize= ma->hasize;
//NT scale halos FSPARTICLE
if(useFluidsimParticles) {
// rescale to 1.0-10.0, then div by 5 afterwards, gives values in range 0.2-2.0
double fspsize = ((double)pa->rt / 1000.0f) / 5.0 ;
haloScale = (float)pow(fspsize, (double)ob->fluidsimSettings->particleInfSize);
ma->alpha = iniAlpha / (float)pow( fspsize, (double)ob->fluidsimSettings->particleInfAlpha);
if(ma->alpha>1.) ma->alpha = 1.;
}
hasize= ma->hasize * haloScale;
if(ma->mode & MA_HALOPUNO) {
xn= pa->no[0];
@@ -852,6 +970,8 @@ static void render_particle_system(Render *re, Object *ob, PartEff *paf)
MEM_freeN(paf->keys);
paf->keys= NULL;
}
if(useFluidsimParticles) { ma->alpha = iniAlpha; }// FSPARTICLE restore...
}
@@ -1442,6 +1562,7 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
float *orco=0;
int a, a1, ok, need_orco=0, need_stress=0, need_tangent=0, totvlako, totverto, vertofs;
int end, do_autosmooth=0, totvert = 0, dm_needsfree;
int useFluidmeshNormals = 0; // NT fluidsim, use smoothed normals?
me= ob->data;
@@ -1494,6 +1615,12 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
if(dm==NULL) return; /* in case duplicated object fails? */
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) &&
(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)&&
(ob->fluidsimSettings->meshSurface) ) {
useFluidmeshNormals = 1;
}
dlm = dm->convertToDispListMesh(dm, 1);
mvert= dlm->mvert;
@@ -1514,6 +1641,16 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
if(do_autosmooth==0) /* autosmooth on original unrotated data to prevent differences between frames */
MTC_Mat4MulVecfl(mat, ver->co);
if(useFluidmeshNormals) {
xn = mvert->no[0]/ 32767.0;
yn = mvert->no[1]/ 32767.0;
zn = mvert->no[2]/ 32767.0;
/* transfor to cam space */
ver->n[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
ver->n[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
ver->n[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
} // useFluidmeshNormals
if(orco) {
ver->orco= orco;
orco+=3;
@@ -1705,7 +1842,12 @@ static void init_render_mesh(Render *re, Object *ob, int only_verts)
autosmooth(re, mat, totverto, totvlako, me->smoothresh);
}
calc_vertexnormals(re, totverto, totvlako, need_tangent);
if(useFluidmeshNormals) {
// do not recalculate, only init render data
calc_fluidsimnormals(re, totverto, totvlako, need_tangent);
} else {
calc_vertexnormals(re, totverto, totvlako, need_tangent);
}
if(need_stress)
calc_edge_stress(re, me, totverto, totvlako);
@@ -3126,9 +3268,84 @@ static void calculate_speedvectors(Render *re, float *vectors, int startvert, in
speed[0]= zco[0];
speed[1]= zco[1];
}
}
}
static int load_fluidsimspeedvectors(Render *re, float *vectors, int startvert, int endvert, int step, Object *fsob)
{
VertRen *ver= NULL;
float *speed, div, zco[2];
float zmulx= re->winx/2, zmuly= re->winy/2, len;
float winsq= re->winx*re->winy, winroot= sqrt(winsq);
int a, j;
float hoco[4], fsvec[4], camco[4];
float mat[4][4];
float imat[4][4];
MVert *vverts;
/* only one step needed */
if(step) return 1;
Mat4CpyMat4(mat, re->viewmat);
MTC_Mat4Invert(imat, mat);
/* set first vertex OK */
a= startvert-1;
ver= re->vertnodes[a>>8].vert + (a & 255);
if( (!fsob->fluidsimSettings) || (!fsob->fluidsimSettings->meshSurfNormals) ) return 0;
vverts = fsob->fluidsimSettings->meshSurfNormals;
//fprintf(stderr, "GZ_VEL obj '%s', calc load_fluidsimspeedvectors\n",fsob->id.name); // NT DEBUG
if( endvert-startvert != fsob->fluidsimSettings->meshSurface->totvert ) {
//fprintf(stderr, "load_fluidsimspeedvectors - modified fluidsim mesh, not using speed vectors (%d,%d)...\n", endvert-startvert , fsob->fluidsimSettings->meshSurface->totvert); // DEBUG
return 0;
}
for(a=startvert; a<endvert; a++, vectors+=2) {
if((a & 255)==0)
ver= re->vertnodes[a>>8].vert;
else
ver++;
// get fluid velocity
fsvec[3] = 0.;
//fsvec[0] = fsvec[1] = fsvec[2] = fsvec[3] = 0.; fsvec[2] = 2.; // NT fixed test
for(j=0;j<3;j++) fsvec[j] = vverts[a-startvert].co[j];
// transform (=rotate) to cam space
camco[0]= imat[0][0]*fsvec[0] + imat[0][1]*fsvec[1] + imat[0][2]*fsvec[2];
camco[1]= imat[1][0]*fsvec[0] + imat[1][1]*fsvec[1] + imat[1][2]*fsvec[2];
camco[2]= imat[2][0]*fsvec[0] + imat[2][1]*fsvec[1] + imat[2][2]*fsvec[2];
// get homogenous coordinates
projectverto(camco, re->winmat, hoco);
/* now map hocos to screenspace, uses very primitive clip still */
// use ho[3] of original vertex, xy component of vel. direction
if(ver->ho[3]<0.1f) div= 10.0f;
else div= 1.0f/ver->ho[3];
zco[0]= zmulx*hoco[0]*div;
zco[1]= zmuly*hoco[1]*div;
// maximize speed as usual
len= zco[0]*zco[0] + zco[1]*zco[1];
if(len > winsq) {
len= winroot/sqrt(len);
zco[0]*= len; zco[1]*= len;
}
speed= RE_vertren_get_winspeed(re, ver, 1);
// set both to the same value
speed[0]= speed[2]= zco[0];
speed[1]= speed[3]= zco[1];
//if(a<20) fprintf(stderr,"speed %d %f,%f | camco %f,%f,%f | hoco %f,%f,%f,%f \n", a, speed[0], speed[1], camco[0],camco[1], camco[2], hoco[0],hoco[1], hoco[2],hoco[3]); // NT DEBUG
}
return 1;
}
/* makes copy per object of all vectors */
/* result should be that we can free entire database */
static void copy_dbase_object_vectors(Render *re, ListBase *lb)
@@ -3236,13 +3453,21 @@ void RE_Database_FromScene_Vectors(Render *re, Scene *sce)
// printf("speed table: missing object %s\n", obren->ob->id.name+2);
continue;
}
/* check if both have same amounts of vertices */
if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) {
printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
continue;
}
calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step);
// NT check for fluidsim special treatment
if((obren->ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obren->ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN)) {
// use preloaded per vertex simulation data , only does calculation for step=1
// NOTE/FIXME - velocities and meshes loaded unnecessarily often during the database_fromscene_vectors calls...
load_fluidsimspeedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step, obren->ob);
} else {
/* check if both have same amounts of vertices */
if(obren->endvert-obren->startvert != oldobren->endvert-oldobren->startvert) {
printf("Warning: object %s has different amount of vertices on other frame\n", obren->ob->id.name+2);
continue;
}
calculate_speedvectors(re, oldobren->vectors, obren->startvert, obren->endvert, step);
} // not fluidsim
}
}
}

View File

@@ -1377,6 +1377,27 @@ void do_object_panels(unsigned short event)
/* write config files (currently no simulation) */
fluidsimBake(ob);
break;
case B_FLUIDSIM_MAKEPART:
ob= OBACT;
{
PartEff *paf= NULL;
/* prepare fluidsim particle display */
// simplified delete effect, create new - recalc some particles...
if(ob==NULL || ob->type!=OB_MESH) break;
ob->fluidsimSettings->type = 0;
// reset type, and init particle system once normally
eff= ob->effect.first;
//if((eff) && (eff->flag & SELECT)) { BLI_remlink(&ob->effect, eff); free_effect(eff); }
if(!eff){ copy_act_effect(ob); DAG_scene_sort(G.scene); }
paf = give_parteff(ob);
paf->totpart = 1000; paf->sta = paf->end = 1.0; // generate some particles...
build_particle_system(ob);
ob->fluidsimSettings->type = OB_FLUIDSIM_PARTICLE;
}
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSOBJECT, 0);
break;
case B_FLUIDSIM_SELDIR: {
ScrArea *sa = closest_bigger_area();
ob= OBACT;
@@ -2290,6 +2311,7 @@ static void object_panel_fluidsim(Object *ob)
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Inflow", 90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_INFLOW, 20.0, 4.0, "Object adds fluid to the simulation.");
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Outflow", 160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OUTFLOW, 20.0, 5.0, "Object removes fluid from the simulation.");
uiDefButS(block, ROW, B_FLUIDSIM_MAKEPART ,"Particle", 230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_PARTICLE,20.0, 3.0, "Object is a fixed obstacle.");
uiBlockEndAlign(block);
yline -= lineHeight;
yline -= 2*separateHeight;
@@ -2304,7 +2326,11 @@ static void object_panel_fluidsim(Object *ob)
elbeemEstimateMemreq(fss->resolutionxyz,
ob->fluidsimSettings->bbSize[0],ob->fluidsimSettings->bbSize[1],ob->fluidsimSettings->bbSize[2], fss->maxRefine, memString);
uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>", 0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options.");
//uiDefButBitS(block, TOG, 1, REDRAWBUTSOBJECT, "Advanced>>", 0,yline, 75,objHeight, &fss->show_advancedoptions, 0, 0, 0, 0, "Show advanced domain options.");
uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Std", 0,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 0, 20.0, 0, "Show standard domain options.");
uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Adv", 25,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 1, 20.0, 1, "Show advanced domain options.");
uiDefButS(block, ROW, REDRAWBUTSOBJECT, "Bnd", 50,yline, 25,objHeight, &fss->show_advancedoptions, 16.0, 2, 20.0, 2, "Show domain boundary options.");
uiDefBut(block, BUT, B_FLUIDSIM_BAKE, "BAKE",90, yline,210,objHeight, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame.");
yline -= lineHeight;
yline -= 2*separateHeight;
@@ -2324,6 +2350,7 @@ static void object_panel_fluidsim(Object *ob)
yline -= lineHeight;
yline -= 2*separateHeight;
if((fss->guiDisplayMode<1) || (fss->guiDisplayMode>3)){ fss->guiDisplayMode=2; } // can be changed by particle setting
uiDefBut(block, LABEL, 0, "Disp.-Qual.:", 0,yline, 90,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButS(block, MENU, B_FLUIDSIM_FORCEREDRAW, "GuiDisplayMode%t|Geometry %x1|Preview %x2|Final %x3",
90,yline,105,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh in the blender gui.");
@@ -2335,7 +2362,7 @@ static void object_panel_fluidsim(Object *ob)
uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select Directory (and/or filename prefix) to store baked fluid simulation files in");
uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter Directory (and/or filename prefix) to store baked fluid simulation files in");
// FIXME what is the 79.0 above?
} else {
} else if(fss->show_advancedoptions == 1) {
// advanced options
uiBlockBeginAlign(block);
uiDefBut(block, LABEL, 0, "Gravity:", 0, yline, 90,objHeight, NULL, 0.0, 0, 0, 0, "");
@@ -2362,7 +2389,7 @@ static void object_panel_fluidsim(Object *ob)
yline -= 1*separateHeight;
uiDefBut(block, LABEL, 0, "Realworld-size:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->realsize, 0.001, 1.0, 10, 0, "Size of the simulation domain in meters.");
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->realsize, 0.001, 10.0, 10, 0, "Size of the simulation domain in meters.");
yline -= lineHeight;
yline -= 2*separateHeight;
@@ -2374,6 +2401,31 @@ static void object_panel_fluidsim(Object *ob)
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->gstar, 0.001, 0.10, 10,0, "Allowed compressibility due to gravitational force for standing fluid (directly affects simulation step size).");
yline -= lineHeight;
} else if(fss->show_advancedoptions == 2) {
// copied from obstacle...
//yline -= lineHeight + 5;
uiDefBut(block, LABEL, 0, "Domain boundary type settings:", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
yline -= lineHeight;
uiBlockBeginAlign(block);
uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 00, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_NOSLIP, 20.0, 1.0, "Obstacle causes zero normal and tangential velocity (=sticky). Default for all. Only option for moving objects.");
uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Part", 100, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_PARTSLIP, 20.0, 2.0, "Mix between no-slip and free-slip. Non moving objects only!");
uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Free", 200, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_FREESLIP, 20.0, 3.0, "Obstacle only causes zero normal velocity (=not sticky). Non moving objects only!");
uiBlockEndAlign(block);
yline -= lineHeight;
if(fss->typeFlags&OB_FSBND_PARTSLIP) {
uiDefBut(block, LABEL, 0, "PartSlipValue:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->partSlipValue, 0.0, 0.1, 10,0, ".");
yline -= lineHeight;
}
uiDefBut(block, LABEL, 0, "Generate Particles:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 200, yline,100,objHeight, &fss->generateParticles, 0.0, 10.0, 10,0, "Amount of particles to generate (0=off, 1=normal, >1=more).");
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Generate&Use SpeedVecs:", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitI(block, TOG, OB_FSDOMAIN_NOVECGEN, REDRAWBUTSOBJECT, "Disable", 200, yline,100,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Default is to generate and use fluidsim vertex speed vectors, this option switches calculation off during bake, and disables loading.");
yline -= lineHeight;
// copied from obstacle...
}
}
else if(
@@ -2390,14 +2442,63 @@ static void object_panel_fluidsim(Object *ob)
uiDefButF(block, NUM, B_DIFF, "Z:", 200, yline, 100,objHeight, &fss->iniVelz, -1000.1, 1000.1, 10, 0, "Fluid velocity in Z direction");
uiBlockEndAlign(block);
yline -= lineHeight;
if(fss->type == OB_FLUIDSIM_INFLOW) {
uiDefBut(block, LABEL, 0, "Local Inflow Coords", 0,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButBitI(block, TOG, OB_FSINFLOW_LOCALCOORD, REDRAWBUTSOBJECT, "Enable", 200, yline,100,objHeight, &fss->typeFlags, 0, 0, 0, 0, "Use local coordinates for inflow (e.g. for rotating objects).");
yline -= lineHeight;
}
}
else if(
(fss->type == OB_FLUIDSIM_OBSTACLE)
|| (fss->type == OB_FLUIDSIM_OUTFLOW)
) {
else if( (fss->type == OB_FLUIDSIM_OUTFLOW) ) {
yline -= lineHeight + 5;
uiDefBut(block, LABEL, 0, "No additional settings as of now...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
}
else if( (fss->type == OB_FLUIDSIM_OBSTACLE) ) {
yline -= lineHeight + 5;
uiBlockBeginAlign(block);
uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Noslip", 00, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_NOSLIP, 20.0, 1.0, "Obstacle causes zero normal and tangential velocity (=sticky). Default for all. Only option for moving objects.");
uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Part", 100, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_PARTSLIP, 20.0, 2.0, "Mix between no-slip and free-slip. Non moving objects only!");
uiDefButI(block, ROW, REDRAWBUTSOBJECT ,"Free", 200, yline,100,objHeight, &fss->typeFlags, 15.0, OB_FSBND_FREESLIP, 20.0, 3.0, "Obstacle only causes zero normal velocity (=not sticky). Non moving objects only!");
uiBlockEndAlign(block);
yline -= lineHeight;
if(fss->typeFlags&OB_FSBND_PARTSLIP) {
uiDefBut(block, LABEL, 0, "PartSlipValue:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->partSlipValue, 0.0, 0.1, 10,0, ".");
yline -= lineHeight;
}
yline -= lineHeight;
}
else if(fss->type == OB_FLUIDSIM_PARTICLE) {
if(fss->guiDisplayMode==0) fss->guiDisplayMode=2; // default drops
uiDefBut(block, LABEL, 0, "Part.-Type:", 0,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
// TODO make toggle buttons
//uiDefButS(block, MENU, B_FLUIDSIM_FORCEREDRAW, "Gui%t|Bubble %x2|Drop %x4|Newparts %x8|Float %x16",
//100,yline,200,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "Which type of particles to display.");
//uiDefButS(block, MENU, B_DIFF, "Render%t|Geometry %x1|Preview %x2|Final %x3",
//195,yline,105,objHeight, &fss->renderDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh for rendering.");
uiDefBut(block, LABEL, 0, "Drops", 100,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
fss->guiDisplayMode = 4; // fix to drops for now
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Size Influence:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->particleInfSize, 0.0, 2.0, 10,0, "Amount of particle size scaling: 0=off (all same size), 1=full (range 0.2-2.0), >1=stronger.");
yline -= lineHeight;
uiDefBut(block, LABEL, 0, "Alpha Influence:", 0,yline,150,objHeight, NULL, 0.0, 0, 0, 0, "");
uiDefButF(block, NUM, B_DIFF, "", 150, yline,150,objHeight, &fss->particleInfAlpha, 0.0, 2.0, 10,0, "Amount of particle alpha change, inverse of size influence: 0=off (all same alpha), 1=full (large particles get lower alphas, smaller ones higher values).");
yline -= lineHeight;
yline -= 1*separateHeight;
// FSPARTICLE also select input files
uiDefIconBut(block, BUT, B_FLUIDSIM_SELDIR, ICON_FILESEL, 0, yline, 20, objHeight, 0, 0, 0, 0, 0, "Select Directory (and/or filename prefix) to store baked fluid simulation files in");
uiDefBut(block, TEX, B_FLUIDSIM_FORCEREDRAW,"", 20, yline, 280, objHeight, fss->surfdataPath, 0.0,79.0, 0, 0, "Enter Directory (and/or filename prefix) to store baked fluid simulation files in");
yline -= lineHeight;
}
else {
yline -= lineHeight + 5;

View File

@@ -67,6 +67,8 @@
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
// FSPARTICLE
#include "DNA_object_fluidsim.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
@@ -2502,7 +2504,10 @@ static void draw_particle_system(Object *ob, PartEff *paf)
int a, totpart;
pa= paf->keys;
if(pa==NULL) {
// FSPARTICLE always rebuild fluid particle system upon change...
if( (pa==NULL)
|| ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE))
) {
build_particle_system(ob);
pa= paf->keys;
if(pa==NULL) return;
@@ -2558,7 +2563,10 @@ static void draw_static_particle_system(Object *ob, PartEff *paf, int dt)
int a, use_norm=0, totpart;
pa= paf->keys;
if(pa==NULL) {
// FSPARTICLE always rebuild upon change...
if( (pa==NULL)
|| ( (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings) && (ob->fluidsimSettings->type == OB_FLUIDSIM_PARTICLE))
) {
build_particle_system(ob);
pa= paf->keys;
if(pa==NULL) return;

View File

@@ -60,6 +60,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
@@ -122,6 +123,7 @@ extern int snd_ar[];
extern int ac_ar[];
extern int co_ar[];
extern int te_ar[];
extern int fluidsim_ar[]; // NT
/* forwards */
#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
@@ -426,6 +428,32 @@ static void make_ob_editipo(Object *ob, SpaceIpo *si)
}
ei++;
}
//fprintf(stderr,"FSIMAKE_OPBJ call %d \n", si->totipo);
}
// copied from make_seq_editipo
static void make_fluidsim_editipo(SpaceIpo *si) // NT
{
EditIpo *ei;
int a;
char *name;
ei= si->editipo= MEM_callocN(FLUIDSIM_TOTIPO*sizeof(EditIpo), "fluidsim_editipo");
si->totipo = FLUIDSIM_TOTIPO;
for(a=0; a<FLUIDSIM_TOTIPO; a++) {
//fprintf(stderr,"FSINAME %d %d \n",a,fluidsim_ar[a], (int)(getname_fluidsim_ei(fluidsim_ar[a])) );
name = getname_fluidsim_ei(fluidsim_ar[a]);
strcpy(ei->name, name);
ei->adrcode= fluidsim_ar[a];
ei->col= ipo_rainbow(a, FLUIDSIM_TOTIPO);
ei->icu= find_ipocurve(si->ipo, ei->adrcode);
if(ei->icu) {
ei->flag = ei->icu->flag;
}
//else { ei->flag |= IPO_VISIBLE; }
//fprintf(stderr,"FSIMAKE eif%d,icuf%d icu%d %d|%d\n", ei->flag,ei->icu->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
//fprintf(stderr,"FSIMAKE eif%d icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
ei++;
}
}
@@ -886,6 +914,12 @@ static void make_editipo(void)
ob->ipowin= ID_PO;
}
}
else if(G.sipo->blocktype==ID_FLUIDSIM) {
if (ob) { // NT
ob->ipowin= ID_FLUIDSIM;
make_fluidsim_editipo(G.sipo);
}
}
if(G.sipo->editipo==0) return;
@@ -1059,6 +1093,13 @@ static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname
// if(sound) *ipo= sound->ipo;
// }
}
else if(blocktype==ID_FLUIDSIM) {
if(ob && ( ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
FluidsimSettings *fss= ob->fluidsimSettings;
*from= (ID *)ob;
if(fss) *ipo= fss->ipo;
}
}
}
/* called on each redraw, check if editipo data has to be remade */
@@ -1674,6 +1715,17 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname)
}
return NULL;
}
else if(blocktype== ID_FLUIDSIM) {
Object *ob= (Object *)from;
if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
FluidsimSettings *fss= ob->fluidsimSettings;
if(fss->ipo==NULL) {
fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM);
//fprintf(stderr,"FSIPO NEW!\n");
}
return fss->ipo;
}
}
}
break;
case ID_MA:

View File

@@ -93,6 +93,7 @@ char *snd_ic_names[SND_TOTNAM] = { "Vol", "Pitch", "Pan", "Atten" };
char *ac_ic_names[AC_TOTNAM] = {"LocX", "LocY", "LocZ", "SizeX", "SizeY",
"SizeZ", "QuatW", "QuatX", "QuatY", "QuatZ"};
char *ic_name_empty[1] ={ "" };
char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time", "GravX","GravY","GravZ", "VelX","VelY","VelZ", "Active" };
char *getname_ac_ei(int nr)
{
@@ -198,6 +199,12 @@ char *getname_snd_ei(int nr)
return ic_name_empty[0];
}
char *getname_fluidsim_ei(int nr)
{
if(nr <= FLUIDSIM_TOTIPO) return fluidsim_ic_names[nr-1];
return ic_name_empty[0];
}
void boundbox_ipocurve(IpoCurve *icu)
{

View File

@@ -178,6 +178,7 @@ void swap_visible_editipo(void)
}
}
else ei->flag &= ~IPO_VISIBLE;
printf("FSISWAP %d, icu%d %d|%d\n", ei->flag, (int)ei->icu, IPO_VISIBLE,IPO_SELECT);
ei++;
}

File diff suppressed because it is too large Load Diff

View File

@@ -53,6 +53,7 @@
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_object_fluidsim.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
@@ -141,6 +142,14 @@ void spaceipo_assign_ipo(SpaceIpo *si, Ipo *ipo)
conchan->ipo= ipo;
}
}
else if(si->blocktype==ID_FLUIDSIM) { // NT
if( (ob->fluidsimSettings) &&
(ob->fluidsimSettings->ipo) ) {
// decrement users counter
ob->fluidsimSettings->ipo->id.us--;
}
ob->fluidsimSettings->ipo = ipo;
}
else if(si->blocktype==ID_OB) {
if(ob->ipo)
ob->ipo->id.us--;
@@ -798,6 +807,9 @@ static char *ipo_modeselect_pup(void)
#ifdef __CON_IPO
str += sprintf(str,formatstring, "Constraint",ID_CO, ICON_CONSTRAINT);
#endif
if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
str += sprintf(str,formatstring,"Fluidsim",ID_FLUIDSIM, ICON_WORLD);
}
}
str += sprintf(str,formatstring, "Sequence",ID_SEQ, ICON_SEQUENCE);
@@ -1135,6 +1147,8 @@ void ipo_buttons(void)
icon = ICON_SEQUENCE;
else if(G.sipo->blocktype == ID_TE)
icon = ICON_TEXTURE;
else if(G.sipo->blocktype == ID_FLUIDSIM)
icon = ICON_WORLD;
uiDefIconTextButS(block, MENU, B_IPOMAIN, icon, ipo_modeselect_pup(), xco,0,100,20, &(G.sipo->blocktype), 0, 0, 0, 0, "Show IPO type");