Blender  V2.59
ntl_geometryobject.cpp
Go to the documentation of this file.
00001 
00004 /******************************************************************************
00005  *
00006  * El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
00007  * Copyright 2003-2006 Nils Thuerey
00008  *
00009  * a geometry object
00010  * all other geometry objects are derived from this one
00011  *
00012  *****************************************************************************/
00013 
00014 
00015 #include "ntl_geometryobject.h"
00016 #include "ntl_world.h"
00017 #include "ntl_matrices.h"
00018 
00019 // for FGI
00020 #include "elbeem.h"
00021 
00022 #define TRI_UVOFFSET (1./4.)
00023 //#define TRI_UVOFFSET (1./3.)
00024 
00025 
00026 /*****************************************************************************/
00027 /* Default constructor */
00028 /*****************************************************************************/
00029 ntlGeometryObject::ntlGeometryObject() :
00030         mIsInitialized(false), mpMaterial( NULL ),
00031         mMaterialName( "default" ),
00032         mCastShadows( 1 ), mReceiveShadows( 1 ),
00033         mGeoInitType( 0 ), 
00034         mInitialVelocity(0.0), mcInitialVelocity(0.0), mLocalCoordInivel(false),
00035         mGeoInitIntersect(false),
00036         mGeoPartSlipValue(0.0),
00037         mcGeoImpactFactor(1.),
00038         mVolumeInit(VOLUMEINIT_VOLUME),
00039         mInitialPos(0.),
00040         mcTrans(0.), mcRot(0.), mcScale(1.),
00041         mIsAnimated(false),
00042         mMovPoints(), mMovNormals(),
00043         mHaveCachedMov(false),
00044         mCachedMovPoints(), mCachedMovNormals(),
00045         mTriangleDivs1(), mTriangleDivs2(), mTriangleDivs3(),
00046         mMovPntsInited(-100.0), mMaxMovPnt(-1),
00047         mcGeoActive(1.),
00048         mCpsTimeStart(0.), mCpsTimeEnd(1.0), mCpsQuality(10.),
00049         mcAttrFStr(0.),mcAttrFRad(0.), mcVelFStr(0.), mcVelFRad(0.)
00050 { 
00051 };
00052 
00053 
00054 /*****************************************************************************/
00055 /* Default destructor */
00056 /*****************************************************************************/
00057 ntlGeometryObject::~ntlGeometryObject() 
00058 {
00059 }
00060 
00062 bool ntlGeometryObject::getMeshAnimated() {
00063         // off by default, on for e.g. ntlGeometryObjModel
00064         return false; 
00065 }
00066 
00068 bool ntlGeometryObject::checkIsAnimated() {
00069         if(    (mcTrans.accessValues().size()>1)  // VALIDATE
00070             || (mcRot.accessValues().size()>1) 
00071             || (mcScale.accessValues().size()>1) 
00072             || (mcGeoActive.accessValues().size()>1) 
00073                         // mcGeoImpactFactor only needed when moving
00074             || (mcInitialVelocity.accessValues().size()>1) 
00075                 ) {
00076                 mIsAnimated = true;
00077         }
00078 
00079         // fluid objects always have static init!
00080         if(mGeoInitType==FGI_FLUID) {
00081                 mIsAnimated=false;
00082         }
00083         //errMsg("ntlGeometryObject::checkIsAnimated","obj="<<getName()<<" debug: trans:"<<mcTrans.accessValues().size()<<" rot:"<<mcRot.accessValues().size()<<" scale:"<<mcScale.accessValues().size()<<" active:"<<mcGeoActive.accessValues().size()<<" inivel:"<<mcInitialVelocity.accessValues().size()<<". isani?"<<mIsAnimated ); // DEBUG
00084         return mIsAnimated;
00085 }
00086 
00087 /*****************************************************************************/
00088 /* Init attributes etc. of this object */
00089 /*****************************************************************************/
00090 #define GEOINIT_STRINGS  10
00091 static const char *initStringStrs[GEOINIT_STRINGS] = {
00092         "fluid",
00093         "bnd_no","bnd_noslip",
00094         "bnd_free","bnd_freeslip",
00095         "bnd_part","bnd_partslip",
00096         "inflow", "outflow", "control",
00097 };
00098 static int initStringTypes[GEOINIT_STRINGS] = {
00099         FGI_FLUID,
00100         FGI_BNDNO, FGI_BNDNO,
00101         FGI_BNDFREE, FGI_BNDFREE,
00102         FGI_BNDPART, FGI_BNDPART,
00103         FGI_MBNDINFLOW, FGI_MBNDOUTFLOW, 
00104         FGI_CONTROL
00105 };
00106 void ntlGeometryObject::initialize(ntlRenderGlobals *glob) 
00107 {
00108         //debugOut("ntlGeometryObject::initialize: '"<<getName()<<"' ", 10);
00109         // initialize only once...
00110         if(mIsInitialized) return;
00111         
00112         // init material, always necessary
00113         searchMaterial( glob->getMaterials() );
00114         
00115         this->mGeoInitId = mpAttrs->readInt("geoinitid", this->mGeoInitId,"ntlGeometryObject", "mGeoInitId", false);
00116         mGeoInitIntersect = mpAttrs->readInt("geoinit_intersect", mGeoInitIntersect,"ntlGeometryObject", "mGeoInitIntersect", false);
00117         string ginitStr = mpAttrs->readString("geoinittype", "", "ntlGeometryObject", "mGeoInitType", false);
00118         if(this->mGeoInitId>=0) {
00119                 bool gotit = false;
00120                 for(int i=0; i<GEOINIT_STRINGS; i++) {
00121                         if(ginitStr== initStringStrs[i]) {
00122                                 gotit = true;
00123                                 mGeoInitType = initStringTypes[i];
00124                         }
00125                 }
00126 
00127                 if(!gotit) {
00128                         errFatal("ntlGeometryObject::initialize","Obj '"<<mName<<"', Unkown 'geoinittype' value: '"<< ginitStr <<"' ", SIMWORLD_INITERROR);
00129                         return;
00130                 }
00131         }
00132 
00133         int geoActive = mpAttrs->readInt("geoinitactive", 1,"ntlGeometryObject", "geoActive", false);
00134         if(!geoActive) {
00135                 // disable geo init again...
00136                 this->mGeoInitId = -1;
00137         }
00138         mInitialVelocity  = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false));
00139         if(getAttributeList()->exists("initial_velocity") || (!mcInitialVelocity.isInited()) ) {
00140                 mcInitialVelocity = mpAttrs->readChannelVec3f("initial_velocity");
00141         }
00142         // always use channel
00143         if(!mcInitialVelocity.isInited()) { mcInitialVelocity = AnimChannel<ntlVec3Gfx>(mInitialVelocity); }
00144         mLocalCoordInivel = mpAttrs->readBool("geoinit_localinivel", mLocalCoordInivel,"ntlGeometryObject", "mLocalCoordInivel", false);
00145 
00146         mGeoPartSlipValue = mpAttrs->readFloat("geoinit_partslip", mGeoPartSlipValue,"ntlGeometryObject", "mGeoPartSlipValue", false);
00147         bool mOnlyThinInit = false; // deprecated!
00148         mOnlyThinInit     = mpAttrs->readBool("geoinit_onlythin", mOnlyThinInit,"ntlGeometryObject", "mOnlyThinInit", false);
00149         if(mOnlyThinInit) mVolumeInit = VOLUMEINIT_SHELL;
00150         mVolumeInit     = mpAttrs->readInt("geoinit_volumeinit", mVolumeInit,"ntlGeometryObject", "mVolumeInit", false);
00151         if((mVolumeInit<VOLUMEINIT_VOLUME)||(mVolumeInit>VOLUMEINIT_BOTH)) mVolumeInit = VOLUMEINIT_VOLUME;
00152 
00153         // moving obs correction factor
00154         float impactfactor=1.;
00155         impactfactor = (float)mpAttrs->readFloat("impactfactor", impactfactor,"ntlGeometryObject", "impactfactor", false);
00156         if(getAttributeList()->exists("impactfactor") || (!mcGeoImpactFactor.isInited()) ) {
00157                 mcGeoImpactFactor = mpAttrs->readChannelSinglePrecFloat("impactfactor");
00158         }
00159 
00160         // override cfg types
00161         mVisible = mpAttrs->readBool("visible", mVisible,"ntlGeometryObject", "mVisible", false);
00162         mReceiveShadows = mpAttrs->readBool("recv_shad", mReceiveShadows,"ntlGeometryObject", "mReceiveShadows", false);
00163         mCastShadows = mpAttrs->readBool("cast_shad", mCastShadows,"ntlGeometryObject", "mCastShadows", false);
00164 
00165         // read mesh animation channels
00166         ntlVec3d translation(0.0);
00167         translation = mpAttrs->readVec3d("translation", translation,"ntlGeometryObject", "translation", false);
00168         if(getAttributeList()->exists("translation") || (!mcTrans.isInited()) ) {
00169                 mcTrans = mpAttrs->readChannelVec3f("translation");
00170         }
00171         ntlVec3d rotation(0.0);
00172         rotation = mpAttrs->readVec3d("rotation", rotation,"ntlGeometryObject", "rotation", false);
00173         if(getAttributeList()->exists("rotation") || (!mcRot.isInited()) ) {
00174                 mcRot = mpAttrs->readChannelVec3f("rotation");
00175         }
00176         ntlVec3d scale(1.0);
00177         scale = mpAttrs->readVec3d("scale", scale,"ntlGeometryObject", "scale", false);
00178         if(getAttributeList()->exists("scale") || (!mcScale.isInited()) ) {
00179                 mcScale = mpAttrs->readChannelVec3f("scale");
00180         }
00181 
00182         float geoactive=1.;
00183         geoactive = (float)mpAttrs->readFloat("geoactive", geoactive,"ntlGeometryObject", "geoactive", false);
00184         if(getAttributeList()->exists("geoactive") || (!mcGeoActive.isInited()) ) {
00185                 mcGeoActive = mpAttrs->readChannelSinglePrecFloat("geoactive");
00186         }
00187         // always use channel
00188         if(!mcGeoActive.isInited()) { mcGeoActive = AnimChannel<float>(geoactive); }
00189 
00190         checkIsAnimated();
00191 
00192         mIsInitialized = true;
00193         debMsgStd("ntlGeometryObject::initialize",DM_MSG,"GeoObj '"<<this->getName()<<"': visible="<<this->mVisible<<" gid="<<this->mGeoInitId<<" gtype="<<mGeoInitType<<","<<ginitStr<<
00194                         " gvel="<<mInitialVelocity<<" gisect="<<mGeoInitIntersect, 10); // debug
00195 }
00196 
00198 // default action - do nothing...
00199 void ntlGeometryObject::notifyOfDump(int dumtp, int frameNr,char *frameNrStr,string outfilename, double simtime) {
00200   bool debugOut=false;
00201         if(debugOut) debMsgStd("ntlGeometryObject::notifyOfDump",DM_MSG," dt:"<<dumtp<<" obj:"<<this->getName()<<" frame:"<<frameNrStr<<","<<frameNr<<",t"<<simtime<<" to "<<outfilename, 10); // DEBUG
00202 }
00203 
00204 /*****************************************************************************/
00205 /* Search the material for this object from the material list */
00206 /*****************************************************************************/
00207 void ntlGeometryObject::searchMaterial(vector<ntlMaterial *> *mat)
00208 {
00209         /* search the list... */
00210         int i=0;
00211         for (vector<ntlMaterial*>::iterator iter = mat->begin();
00212          iter != mat->end(); iter++) {
00213                 if( mMaterialName == (*iter)->getName() ) {
00214                         //warnMsg("ntlGeometryObject::searchMaterial","for obj '"<<getName()<<"' found - '"<<(*iter)->getName()<<"' "<<i); // DEBUG
00215                         mpMaterial = (*iter);
00216                         return;
00217                 }
00218                 i++;
00219         }
00220         errFatal("ntlGeometryObject::searchMaterial","Unknown material '"<<mMaterialName<<"' ! ", SIMWORLD_INITERROR);
00221         mpMaterial = new ntlMaterial();
00222         return;
00223 }
00224 
00225 /******************************************************************************
00226  * static add triangle function
00227  *****************************************************************************/
00228 void ntlGeometryObject::sceneAddTriangle(
00229                 ntlVec3Gfx  p1,ntlVec3Gfx  p2,ntlVec3Gfx  p3,
00230                 ntlVec3Gfx pn1,ntlVec3Gfx pn2,ntlVec3Gfx pn3,
00231                 ntlVec3Gfx trin, bool smooth,
00232                 vector<ntlTriangle> *triangles,
00233                 vector<ntlVec3Gfx>  *vertices,
00234                 vector<ntlVec3Gfx>  *normals) {
00235         ntlTriangle tri;
00236         int tempVert;
00237   
00238         if(normals->size() != vertices->size()) {
00239                 errFatal("ntlGeometryObject::sceneAddTriangle","For '"<<this->mName<<"': Vertices and normals sizes to not match!!!",SIMWORLD_GENERICERROR);
00240 
00241         } else {
00242                 
00243                 vertices->push_back( p1 ); 
00244                 normals->push_back( pn1 ); 
00245                 tempVert = normals->size()-1;
00246                 tri.getPoints()[0] = tempVert;
00247                 
00248                 vertices->push_back( p2 ); 
00249                 normals->push_back( pn2 ); 
00250                 tempVert = normals->size()-1;
00251                 tri.getPoints()[1] = tempVert;
00252                 
00253                 vertices->push_back( p3 ); 
00254                 normals->push_back( pn3 ); 
00255                 tempVert = normals->size()-1;
00256                 tri.getPoints()[2] = tempVert;
00257                 
00258                 
00259                 /* init flags from ntl_ray.h */
00260                 int flag = 0; 
00261                 if(getVisible()){ flag |= TRI_GEOMETRY; }
00262                 if(getCastShadows() ) { 
00263                         flag |= TRI_CASTSHADOWS; } 
00264                 
00265                 /* init geo init id */
00266                 int geoiId = getGeoInitId(); 
00267                 //if((geoiId > 0) && (mVolumeInit&VOLUMEINIT_VOLUME) && (!mIsAnimated)) { 
00268                 if((geoiId > 0) && (mVolumeInit&VOLUMEINIT_VOLUME)) { 
00269                         flag |= (1<< (geoiId+4)); 
00270                         flag |= mGeoInitType; 
00271                 } 
00272                 /*errMsg("ntlScene::addTriangle","DEBUG flag="<<convertFlags2String(flag) ); */ 
00273                 tri.setFlags( flag );
00274                 
00275                 /* triangle normal missing */
00276                 tri.setNormal( trin );
00277                 tri.setSmoothNormals( smooth );
00278                 tri.setObjectId( this->mObjectId );
00279                 triangles->push_back( tri ); 
00280         } /* normals check*/ 
00281 }
00282 
00283 void ntlGeometryObject::sceneAddTriangleNoVert(int *trips,
00284                 ntlVec3Gfx trin, bool smooth,
00285                 vector<ntlTriangle> *triangles) {
00286         ntlTriangle tri;
00287                 
00288         tri.getPoints()[0] = trips[0];
00289         tri.getPoints()[1] = trips[1];
00290         tri.getPoints()[2] = trips[2];
00291 
00292         // same as normal sceneAddTriangle
00293 
00294         /* init flags from ntl_ray.h */
00295         int flag = 0; 
00296         if(getVisible()){ flag |= TRI_GEOMETRY; }
00297         if(getCastShadows() ) { 
00298                 flag |= TRI_CASTSHADOWS; } 
00299 
00300         /* init geo init id */
00301         int geoiId = getGeoInitId(); 
00302         if((geoiId > 0) && (mVolumeInit&VOLUMEINIT_VOLUME)) { 
00303                 flag |= (1<< (geoiId+4)); 
00304                 flag |= mGeoInitType; 
00305         } 
00306         /*errMsg("ntlScene::addTriangle","DEBUG flag="<<convertFlags2String(flag) ); */ 
00307         tri.setFlags( flag );
00308 
00309         /* triangle normal missing */
00310         tri.setNormal( trin );
00311         tri.setSmoothNormals( smooth );
00312         tri.setObjectId( this->mObjectId );
00313         triangles->push_back( tri ); 
00314 }
00315 
00316 
00317 /******************************************************************************/
00318 /* Init channels from float arrays (for elbeem API) */
00319 /******************************************************************************/
00320 
00321 #define ADD_CHANNEL_VEC(dst,nvals,val) \
00322                 vals.clear(); time.clear(); elbeemSimplifyChannelVec3(val,&nvals); \
00323                 for(int i=0; i<(nvals); i++) { \
00324                         vals.push_back(ntlVec3Gfx((val)[i*4+0], (val)[i*4+1],(val)[i*4+2] )); \
00325                         time.push_back( (val)[i*4+3] ); \
00326                 } \
00327                 (dst) = AnimChannel< ntlVec3Gfx >(vals,time); 
00328 
00329 #define ADD_CHANNEL_FLOAT(dst,nvals,val) \
00330                 valsfloat.clear(); time.clear(); elbeemSimplifyChannelFloat(val,&nvals); \
00331                 for(int i=0; i<(nvals); i++) { \
00332                         valsfloat.push_back( (val)[i*2+0] ); \
00333                         time.push_back( (val)[i*2+1] ); \
00334                 } \
00335                 (dst) = AnimChannel< float >(valsfloat,time); 
00336 
00337 void ntlGeometryObject::initChannels(
00338                 int nTrans, float *trans, int nRot, float *rot, int nScale, float *scale,
00339                 int nAct, float *act, int nIvel, float *ivel,
00340                 int nAttrFStr, float *attrFStr,
00341                 int nAttrFRad, float *attrFRad,
00342                 int nVelFStr, float *velFStr,
00343                 int nVelFRad, float *velFRad
00344                 ) {
00345         const bool debugInitc=true;
00346         if(debugInitc) { debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"nt:"<<nTrans<<" nr:"<<nRot<<" ns:"<<nScale, 10); 
00347                          debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"na:"<<nAct<<" niv:"<<nIvel<<" ", 10); }
00348         vector<ntlVec3Gfx> vals;
00349         vector<float>  valsfloat;
00350         vector<double> time;
00351         if((trans)&&(nTrans>0)) {  ADD_CHANNEL_VEC(mcTrans, nTrans, trans); }
00352         if((rot)&&(nRot>0)) {      ADD_CHANNEL_VEC(mcRot, nRot, rot); }
00353         if((scale)&&(nScale>0)) {  ADD_CHANNEL_VEC(mcScale, nScale, scale); }
00354         if((act)&&(nAct>0)) {      ADD_CHANNEL_FLOAT(mcGeoActive, nAct, act); }
00355         if((ivel)&&(nIvel>0)) {    ADD_CHANNEL_VEC(mcInitialVelocity, nIvel, ivel); }
00356         
00357         /* fluid control channels */
00358         if((attrFStr)&&(nAttrFStr>0)) { ADD_CHANNEL_FLOAT(mcAttrFStr, nAttrFStr, attrFStr); }
00359         if((attrFRad)&&(nAttrFRad>0)) { ADD_CHANNEL_FLOAT(mcAttrFRad, nAttrFRad, attrFRad); }
00360         if((velFStr)&&(nVelFStr>0)) {   ADD_CHANNEL_FLOAT(mcVelFStr, nAct, velFStr); }
00361         if((velFRad)&&(nVelFRad>0)) {   ADD_CHANNEL_FLOAT(mcVelFRad, nVelFRad, velFRad); }
00362 
00363         checkIsAnimated();
00364         
00365         if(debugInitc) { 
00366                 debMsgStd("ntlGeometryObject::initChannels",DM_MSG,getName()<<
00367                                 " nt:"<<mcTrans.accessValues().size()<<" nr:"<<mcRot.accessValues().size()<<
00368                                 " ns:"<<mcScale.accessValues().size()<<" isAnim:"<<mIsAnimated, 10); }
00369 
00370         if(debugInitc) {
00371                 std::ostringstream ostr;
00372                 ostr << "trans: ";
00373                 for(size_t i=0; i<mcTrans.accessValues().size(); i++) {
00374                         ostr<<" "<<mcTrans.accessValues()[i]<<"@"<<mcTrans.accessTimes()[i]<<" ";
00375                 } ostr<<";   ";
00376                 ostr<<"rot: ";
00377                 for(size_t i=0; i<mcRot.accessValues().size(); i++) {
00378                         ostr<<" "<<mcRot.accessValues()[i]<<"@"<<mcRot.accessTimes()[i]<<" ";
00379                 } ostr<<";   ";
00380                 ostr<<"scale: ";
00381                 for(size_t i=0; i<mcScale.accessValues().size(); i++) {
00382                         ostr<<" "<<mcScale.accessValues()[i]<<"@"<<mcScale.accessTimes()[i]<<" ";
00383                 } ostr<<";   ";
00384                 ostr<<"act: ";
00385                 for(size_t i=0; i<mcGeoActive.accessValues().size(); i++) {
00386                         ostr<<" "<<mcGeoActive.accessValues()[i]<<"@"<<mcGeoActive.accessTimes()[i]<<" ";
00387                 } ostr<<";   ";
00388                 ostr<<"ivel: ";
00389                 for(size_t i=0; i<mcInitialVelocity.accessValues().size(); i++) {
00390                         ostr<<" "<<mcInitialVelocity.accessValues()[i]<<"@"<<mcInitialVelocity.accessTimes()[i]<<" ";
00391                 } ostr<<";   ";
00392                 debMsgStd("ntlGeometryObject::initChannels",DM_MSG,"Inited "<<ostr.str(),10);
00393         }
00394 }
00395 #undef ADD_CHANNEL
00396 
00397 
00398 /*****************************************************************************/
00399 /* apply object translation at time t*/
00400 /*****************************************************************************/
00401 void ntlGeometryObject::applyTransformation(double t, vector<ntlVec3Gfx> *verts, vector<ntlVec3Gfx> *norms, int vstart, int vend, int forceTrafo) {
00402         if(    (mcTrans.accessValues().size()>1)  // VALIDATE
00403             || (mcRot.accessValues().size()>1) 
00404             || (mcScale.accessValues().size()>1) 
00405             || (forceTrafo)
00406             || (!mHaveCachedMov)
00407                 ) {
00408                 // transformation is animated, continue
00409                 ntlVec3Gfx pos = getTranslation(t); 
00410                 ntlVec3Gfx scale = mcScale.get(t);
00411                 ntlVec3Gfx rot = mcRot.get(t);
00412                 ntlMat4Gfx rotMat;
00413                 rotMat.initRotationXYZ(rot[0],rot[1],rot[2]);
00414                 pos += mInitialPos;
00415                 errMsg("ntlGeometryObject::applyTransformation","obj="<<getName()<<" t"<<pos<<" r"<<rot<<" s"<<scale);
00416                 for(int i=vstart; i<vend; i++) {
00417                         (*verts)[i] *= scale;
00418                         (*verts)[i] = rotMat * (*verts)[i];
00419                         (*verts)[i] += pos;
00420                         //if(i<10) errMsg("ntlGeometryObject::applyTransformation"," v"<<i<<"/"<<vend<<"="<<(*verts)[i]);
00421                 }
00422                 if(norms) {
00423                         for(int i=vstart; i<vend; i++) {
00424                                 (*norms)[i] = rotMat * (*norms)[i];
00425                         }
00426                 }
00427         } else {
00428                 // not animated, cached points were already returned
00429                 errMsg ("ntlGeometryObject::applyTransformation","Object "<<getName()<<" used cached points ");
00430         }
00431 }
00432 
00434 void ntlGeometryObject::calcTriangleDivs(vector<ntlVec3Gfx> &verts, vector<ntlTriangle> &tris, gfxReal fsTri) {
00435         mTriangleDivs1.resize( tris.size() );
00436         mTriangleDivs2.resize( tris.size() );
00437         mTriangleDivs3.resize( tris.size() );
00438 
00439         //fsTri *= 2.; // DEBUG! , wrong init!
00440 
00441         for(size_t i=0; i<tris.size(); i++) {
00442                 const ntlVec3Gfx p0 = verts[ tris[i].getPoints()[0] ];
00443                 const ntlVec3Gfx p1 = verts[ tris[i].getPoints()[1] ];
00444                 const ntlVec3Gfx p2 = verts[ tris[i].getPoints()[2] ];
00445                 const ntlVec3Gfx side1 = p1 - p0;
00446                 const ntlVec3Gfx side2 = p2 - p0;
00447                 const ntlVec3Gfx side3 = p1 - p2;
00448                 int divs1=0, divs2=0, divs3=0;
00449                 if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
00450                 if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
00451 
00452                 mTriangleDivs1[i] = divs1;
00453                 mTriangleDivs2[i] = divs2;
00454                 mTriangleDivs3[i] = divs3;
00455         }
00456 }
00457 
00459 void ntlGeometryObject::initMovingPoints(double time, gfxReal featureSize) {
00460         if((mMovPntsInited==featureSize)&&(!getMeshAnimated())) return;
00461         const bool debugMoinit=false;
00462 
00463         vector<ntlTriangle> triangles; 
00464         vector<ntlVec3Gfx> vertices; 
00465         vector<ntlVec3Gfx> vnormals; 
00466         int objectId = 1;
00467         this->getTriangles(time, &triangles,&vertices,&vnormals,objectId);
00468         
00469         mMovPoints.clear();
00470         mMovNormals.clear();
00471         if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" has v:"<<vertices.size()<<" t:"<<triangles.size() );
00472         // no points?
00473         if(vertices.size()<1) {
00474                 mMaxMovPnt=-1;
00475                 return; 
00476         }
00477         ntlVec3f maxscale = channelFindMaxVf(mcScale);
00478         float maxpart = ABS(maxscale[0]);
00479         if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
00480         if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
00481         float scaleFac = 1.0/(maxpart);
00482         // TODO - better reinit from time to time?
00483         const gfxReal fsTri = featureSize*0.5 *scaleFac;
00484         if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","maxscale:"<<maxpart<<" featureSize:"<<featureSize<<" fsTri:"<<fsTri );
00485 
00486         if(mTriangleDivs1.size()!=triangles.size()) {
00487                 calcTriangleDivs(vertices,triangles,fsTri);
00488         }
00489 
00490         // debug: count points to init
00491         /*if(debugMoinit) {
00492                 errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" estimating...");
00493                 int countp=vertices.size()*2;
00494                 for(size_t i=0; i<triangles.size(); i++) {
00495                         ntlVec3Gfx p0 = vertices[ triangles[i].getPoints()[0] ];
00496                         ntlVec3Gfx side1 = vertices[ triangles[i].getPoints()[1] ] - p0;
00497                         ntlVec3Gfx side2 = vertices[ triangles[i].getPoints()[2] ] - p0;
00498                         int divs1=0, divs2=0;
00499                         if(normNoSqrt(side1) > fsTri*fsTri) { divs1 = (int)(norm(side1)/fsTri); }
00500                         if(normNoSqrt(side2) > fsTri*fsTri) { divs2 = (int)(norm(side2)/fsTri); }
00501                         errMsg("ntlGeometryObject::initMovingPoints","tri:"<<i<<" p:"<<p0<<" s1:"<<side1<<" s2:"<<side2<<" -> "<<divs1<<","<<divs2 );
00502                         if(divs1+divs2 > 0) {
00503                                 for(int u=0; u<=divs1; u++) {
00504                                         for(int v=0; v<=divs2; v++) {
00505                                                 const gfxReal uf = (gfxReal)(u+TRI_UVOFFSET) / (gfxReal)(divs1+0.0);
00506                                                 const gfxReal vf = (gfxReal)(v+TRI_UVOFFSET) / (gfxReal)(divs2+0.0);
00507                                                 if(uf+vf>1.0) continue;
00508                                                 countp+=2;
00509                                         }
00510                                 }
00511                         }
00512                 }
00513                 errMsg("ntlGeometryObject::initMovingPoints","Object "<<getName()<<" requires:"<<countp*2);
00514         } // */
00515 
00516         bool discardInflowBack = false;
00517         if( (mGeoInitType==FGI_MBNDINFLOW) && (mcInitialVelocity.accessValues().size()<1) ) discardInflowBack = true;
00518         discardInflowBack = false; // DEBUG disable for now
00519 
00520 
00521         // init std points
00522         for(size_t i=0; i<vertices.size(); i++) {
00523                 ntlVec3Gfx p = vertices[ i ];
00524                 ntlVec3Gfx n = vnormals[ i ];
00525                 // discard inflow backsides
00526                 //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) {
00527                 if(discardInflowBack) { //if( (mGeoInitType==FGI_MBNDINFLOW) && (!mIsAnimated)) {
00528                         if(dot(mInitialVelocity,n)<0.0) continue;
00529                 }
00530                 mMovPoints.push_back(p);
00531                 mMovNormals.push_back(n);
00532                 if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","std"<<i<<" p"<<p<<" n"<<n<<" ");
00533         }
00534         // init points & refine...
00535         for(size_t i=0; i<triangles.size(); i++) {
00536                 int *trips = triangles[i].getPoints();
00537                 const ntlVec3Gfx p0 = vertices[ trips[0] ];
00538                 const ntlVec3Gfx side1 = vertices[ trips[1] ] - p0;
00539                 const ntlVec3Gfx side2 = vertices[ trips[2] ] - p0;
00540                 int divs1=mTriangleDivs1[i], divs2=mTriangleDivs2[i];
00541                 
00542                 const ntlVec3Gfx trinormOrg = getNormalized(cross(side1,side2));
00543                 const ntlVec3Gfx trinorm = trinormOrg*0.25*featureSize;
00544                 if(discardInflowBack) { 
00545                         if(dot(mInitialVelocity,trinorm)<0.0) continue;
00546                 }
00547                 if(debugMoinit) errMsg("ntlGeometryObject::initMovingPoints","Tri1 "<<vertices[trips[0]]<<","<<vertices[trips[1]]<<","<<vertices[trips[2]]<<" "<<divs1<<","<<divs2 );
00548                 if(divs1+divs2 > 0) {
00549                         for(int u=0; u<=divs1; u++) {
00550                                 for(int v=0; v<=divs2; v++) {
00551                                         const gfxReal uf = (gfxReal)(u+TRI_UVOFFSET) / (gfxReal)(divs1+0.0);
00552                                         const gfxReal vf = (gfxReal)(v+TRI_UVOFFSET) / (gfxReal)(divs2+0.0);
00553                                         if(uf+vf>1.0) continue;
00554                                         ntlVec3Gfx p = 
00555                                                 vertices[ trips[0] ] * (1.0-uf-vf)+
00556                                                 vertices[ trips[1] ] * uf +
00557                                                 vertices[ trips[2] ] * vf;
00558                                         //ntlVec3Gfx n = vnormals[ 
00559                                                 //trips[0] ] * (1.0-uf-vf)+
00560                                                 //vnormals[ trips[1] ]*uf +
00561                                                 //vnormals[ trips[2] ]*vf;
00562                                         //normalize(n);
00563                                         // discard inflow backsides
00564 
00565                                         mMovPoints.push_back(p + trinorm); // NEW!?
00566                                         mMovPoints.push_back(p - trinorm);
00567                                         mMovNormals.push_back(trinormOrg);
00568                                         mMovNormals.push_back(trinormOrg); 
00569                                         //errMsg("TRINORM","p"<<p<<" n"<<n<<" trin"<<trinorm);
00570                                 }
00571                         }
00572                 }
00573         }
00574 
00575         // find max point
00576         mMaxMovPnt = 0;
00577         gfxReal dist = normNoSqrt(mMovPoints[0]);
00578         for(size_t i=0; i<mMovPoints.size(); i++) {
00579                 if(normNoSqrt(mMovPoints[i])>dist) {
00580                         mMaxMovPnt = i;
00581                         dist = normNoSqrt(mMovPoints[0]);
00582                 }
00583         }
00584 
00585         if(    (this->getMeshAnimated())
00586       || (mcTrans.accessValues().size()>1)  // VALIDATE
00587             || (mcRot.accessValues().size()>1) 
00588             || (mcScale.accessValues().size()>1) 
00589                 ) {
00590                 // also do trafo...
00591         } else {
00592                 mCachedMovPoints = mMovPoints;
00593                 mCachedMovNormals = mMovNormals;
00594                 //applyTransformation(time, &mCachedMovPoints, &mCachedMovNormals, 0, mCachedMovPoints.size(), true);
00595                 applyTransformation(time, &mCachedMovPoints, NULL, 0, mCachedMovPoints.size(), true);
00596                 mHaveCachedMov = true;
00597                 debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" cached points ", 7);
00598         }
00599 
00600         mMovPntsInited = featureSize;
00601         debMsgStd("ntlGeometryObject::initMovingPoints",DM_MSG,"Object "<<getName()<<" inited v:"<<vertices.size()<<"->"<<mMovPoints.size() , 5);
00602 }
00606 void ntlGeometryObject::initMovingPointsAnim(
00607                  double srctime, vector<ntlVec3Gfx> &srcmovPoints,
00608                  double dsttime, vector<ntlVec3Gfx> &dstmovPoints,
00609                  vector<ntlVec3Gfx> *dstmovNormals,
00610                  gfxReal featureSize,
00611                  ntlVec3Gfx geostart, ntlVec3Gfx geoend
00612                  ) {
00613         const bool debugMoinit=false;
00614 
00615         vector<ntlTriangle> srctriangles; 
00616         vector<ntlVec3Gfx> srcvertices; 
00617         vector<ntlVec3Gfx> unused_normals; 
00618         vector<ntlTriangle> dsttriangles; 
00619         vector<ntlVec3Gfx> dstvertices; 
00620         vector<ntlVec3Gfx> dstnormals; 
00621         int objectId = 1;
00622         // TODO optimize? , get rid of normals?
00623         unused_normals.clear();
00624         this->getTriangles(srctime, &srctriangles,&srcvertices,&unused_normals,objectId);
00625         unused_normals.clear();
00626         this->getTriangles(dsttime, &dsttriangles,&dstvertices,&dstnormals,objectId);
00627         
00628         srcmovPoints.clear();
00629         dstmovPoints.clear();
00630         if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","Object "<<getName()<<" has srcv:"<<srcvertices.size()<<" srct:"<<srctriangles.size() );
00631         if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","Object "<<getName()<<" has dstv:"<<dstvertices.size()<<" dstt:"<<dsttriangles.size() );
00632         // no points?
00633         if(srcvertices.size()<1) {
00634                 mMaxMovPnt=-1;
00635                 return; 
00636         }
00637         if((srctriangles.size() != dsttriangles.size()) ||
00638            (srcvertices.size() != dstvertices.size()) ) {
00639                 errMsg("ntlGeometryObject::initMovingPointsAnim","Invalid triangle numbers! Aborting...");
00640                 return;
00641         }
00642         ntlVec3f maxscale = channelFindMaxVf(mcScale);
00643         float maxpart = ABS(maxscale[0]);
00644         if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
00645         if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
00646         float scaleFac = 1.0/(maxpart);
00647         // TODO - better reinit from time to time?
00648         const gfxReal fsTri = featureSize*0.5 *scaleFac;
00649         if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","maxscale:"<<maxpart<<" featureSize:"<<featureSize<<" fsTri:"<<fsTri );
00650 
00651         if(mTriangleDivs1.size()!=srctriangles.size()) {
00652                 calcTriangleDivs(srcvertices,srctriangles,fsTri);
00653         }
00654 
00655 
00656         // init std points
00657         for(size_t i=0; i<srcvertices.size(); i++) {
00658                 srcmovPoints.push_back(srcvertices[i]);
00659                 //srcmovNormals.push_back(srcnormals[i]);
00660         }
00661         for(size_t i=0; i<dstvertices.size(); i++) {
00662                 dstmovPoints.push_back(dstvertices[i]);
00663                 if(dstmovNormals) (*dstmovNormals).push_back(dstnormals[i]);
00664         }
00665         if(debugMoinit) errMsg("ntlGeometryObject::initMovingPointsAnim","stats src:"<<srcmovPoints.size()<<" dst:"<<dstmovPoints.size()<<" " );
00666         // init points & refine...
00667         for(size_t i=0; i<srctriangles.size(); i++) {
00668                 const int divs1=mTriangleDivs1[i];
00669                 const int       divs2=mTriangleDivs2[i];
00670                 if(divs1+divs2 > 0) {
00671                         int *srctrips = srctriangles[i].getPoints();
00672                         int *dsttrips = dsttriangles[i].getPoints();
00673                         const ntlVec3Gfx srcp0 =    srcvertices[ srctrips[0] ];
00674                         const ntlVec3Gfx srcside1 = srcvertices[ srctrips[1] ] - srcp0;
00675                         const ntlVec3Gfx srcside2 = srcvertices[ srctrips[2] ] - srcp0;
00676                         const ntlVec3Gfx dstp0 =    dstvertices[ dsttrips[0] ];
00677                         const ntlVec3Gfx dstside1 = dstvertices[ dsttrips[1] ] - dstp0;
00678                         const ntlVec3Gfx dstside2 = dstvertices[ dsttrips[2] ] - dstp0;
00679                         const ntlVec3Gfx src_trinorm    = getNormalized(cross(srcside1,srcside2))*0.25*featureSize;
00680                         const ntlVec3Gfx dst_trinormOrg = getNormalized(cross(dstside1,dstside2));
00681                         const ntlVec3Gfx dst_trinorm    = dst_trinormOrg                         *0.25*featureSize;
00682                         //errMsg("ntlGeometryObject::initMovingPointsAnim","Tri1 "<<srcvertices[srctrips[0]]<<","<<srcvertices[srctrips[1]]<<","<<srcvertices[srctrips[2]]<<" "<<divs1<<","<<divs2 );
00683                         for(int u=0; u<=divs1; u++) {
00684                                 for(int v=0; v<=divs2; v++) {
00685                                         const gfxReal uf = (gfxReal)(u+TRI_UVOFFSET) / (gfxReal)(divs1+0.0);
00686                                         const gfxReal vf = (gfxReal)(v+TRI_UVOFFSET) / (gfxReal)(divs2+0.0);
00687                                         if(uf+vf>1.0) continue;
00688                                         ntlVec3Gfx srcp = 
00689                                                 srcvertices[ srctrips[0] ] * (1.0-uf-vf)+
00690                                                 srcvertices[ srctrips[1] ] * uf +
00691                                                 srcvertices[ srctrips[2] ] * vf;
00692                                         ntlVec3Gfx dstp = 
00693                                                 dstvertices[ dsttrips[0] ] * (1.0-uf-vf)+
00694                                                 dstvertices[ dsttrips[1] ] * uf +
00695                                                 dstvertices[ dsttrips[2] ] * vf;
00696 
00697                                         // cutoffDomain
00698                                         if((srcp[0]<geostart[0]) && (dstp[0]<geostart[0])) continue;
00699                                         if((srcp[1]<geostart[1]) && (dstp[1]<geostart[1])) continue;
00700                                         if((srcp[2]<geostart[2]) && (dstp[2]<geostart[2])) continue;
00701                                         if((srcp[0]>geoend[0]  ) && (dstp[0]>geoend[0]  )) continue;
00702                                         if((srcp[1]>geoend[1]  ) && (dstp[1]>geoend[1]  )) continue;
00703                                         if((srcp[2]>geoend[2]  ) && (dstp[2]>geoend[2]  )) continue;
00704                                         
00705                                         srcmovPoints.push_back(srcp+src_trinorm); // SURFENHTEST
00706                                         srcmovPoints.push_back(srcp-src_trinorm);
00707 
00708                                         dstmovPoints.push_back(dstp+dst_trinorm); // SURFENHTEST
00709                                         dstmovPoints.push_back(dstp-dst_trinorm);
00710                                         if(dstmovNormals) {
00711                                                 (*dstmovNormals).push_back(dst_trinormOrg);
00712                                                 (*dstmovNormals).push_back(dst_trinormOrg); }
00713                                 }
00714                         }
00715                 }
00716         }
00717 
00718         // find max point not necessary
00719         debMsgStd("ntlGeometryObject::initMovingPointsAnim",DM_MSG,"Object "<<getName()<<" inited v:"<<srcvertices.size()<<"->"<<srcmovPoints.size()<<","<<dstmovPoints.size() , 5);
00720 }
00721 
00723 void ntlGeometryObject::getMovingPoints(vector<ntlVec3Gfx> &ret, vector<ntlVec3Gfx> *norms) {
00724         if(mHaveCachedMov) {
00725                 ret = mCachedMovPoints;
00726                 if(norms) { 
00727                         *norms = mCachedMovNormals; 
00728                         //errMsg("ntlGeometryObject","getMovingPoints - Normals currently unused!");
00729                 }
00730                 //errMsg ("ntlGeometryObject::getMovingPoints","Object "<<getName()<<" used cached points "); // DEBUG
00731                 return;
00732         }
00733 
00734         ret = mMovPoints;
00735         if(norms) { 
00736                 //errMsg("ntlGeometryObject","getMovingPoints - Normals currently unused!");
00737                 *norms = mMovNormals; 
00738         }
00739 }
00740 
00741 
00743 ntlVec3Gfx ntlGeometryObject::calculateMaxVel(double t1, double t2) {
00744         ntlVec3Gfx vel(0.);
00745         if(mMaxMovPnt<0) return vel;
00746                 
00747         vector<ntlVec3Gfx> verts1,verts2;
00748         verts1.push_back(mMovPoints[mMaxMovPnt]);
00749         verts2 = verts1;
00750         applyTransformation(t1,&verts1,NULL, 0,verts1.size(), true);
00751         applyTransformation(t2,&verts2,NULL, 0,verts2.size(), true);
00752 
00753         vel = (verts2[0]-verts1[0]); // /(t2-t1);
00754         //errMsg("ntlGeometryObject::calculateMaxVel","t1="<<t1<<" t2="<<t2<<" p1="<<verts1[0]<<" p2="<<verts2[0]<<" v="<<vel);
00755         return vel;
00756 }
00757 
00759 ntlVec3Gfx ntlGeometryObject::getTranslation(double t) {
00760         ntlVec3Gfx pos = mcTrans.get(t);
00761   // DEBUG CP_FORCECIRCLEINIT 1
00762         /*if( 
00763                         (mName.compare(string("0__ts1"))==0) ||
00764                         (mName.compare(string("1__ts1"))==0) ||
00765                         (mName.compare(string("2__ts1"))==0) ||
00766                         (mName.compare(string("3__ts1"))==0) ||
00767                         (mName.compare(string("4__ts1"))==0) ||
00768                         (mName.compare(string("5__ts1"))==0) ||
00769                         (mName.compare(string("6__ts1"))==0) ||
00770                         (mName.compare(string("7__ts1"))==0) ||
00771                         (mName.compare(string("8__ts1"))==0) ||
00772                         (mName.compare(string("9__ts1"))==0) 
00773                         ) { int j=mName[0]-'0';
00774                         ntlVec3Gfx ppos(0.); { // DEBUG
00775                         const float tscale=10.;
00776                         const float tprevo = 0.33;
00777                         const ntlVec3Gfx   toff(50,50,0);
00778                         const ntlVec3Gfx oscale(30,30,0);
00779                         ppos[0] =  cos(tscale* t - tprevo*(float)j + M_PI -0.1) * oscale[0] + toff[0];
00780                         ppos[1] = -sin(tscale* t - tprevo*(float)j + M_PI -0.1) * oscale[1] + toff[1];
00781                         ppos[2] =                               toff[2]; } // DEBUG
00782                         pos = ppos;
00783                         pos[2] = 0.15;
00784         }
00785   // DEBUG CP_FORCECIRCLEINIT 1 */
00786         return pos;
00787 }
00789 float ntlGeometryObject::getGeoActive(double t) {
00790         float act = mcGeoActive.get(t); // if <= 0.0 -> off
00791         return act;
00792 }
00793 
00794 void ntlGeometryObject::setInitialVelocity(ntlVec3Gfx set) { 
00795         mInitialVelocity=set; 
00796         mcInitialVelocity = AnimChannel<ntlVec3Gfx>(set); 
00797 }
00798 ntlVec3Gfx ntlGeometryObject::getInitialVelocity(double t) { 
00799         ntlVec3Gfx v =  mcInitialVelocity.get(t); //return mInitialVelocity; 
00800         if(!mLocalCoordInivel) return v;
00801 
00802         ntlVec3Gfx rot = mcRot.get(t);
00803         ntlMat4Gfx rotMat;
00804         rotMat.initRotationXYZ(rot[0],rot[1],rot[2]);
00805         v = rotMat * v;
00806         return v;
00807 }
00808         
00809