Blender V2.61 - r43446
|
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