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 * main renderer class 00010 * 00011 *****************************************************************************/ 00012 00013 00014 #include "utilities.h" 00015 #include "ntl_ray.h" 00016 #include "ntl_world.h" 00017 #include "ntl_geometryobject.h" 00018 #include "ntl_geometryshader.h" 00019 00020 00021 /* Minimum value for refl/refr to be traced */ 00022 #define RAY_THRESHOLD 0.001 00023 00024 #if GFX_PRECISION==1 00025 // float values 00027 #define RAY_MINCONTRIB (1e-04) 00028 00029 #else 00030 // double values 00032 #define RAY_MINCONTRIB (1e-05) 00033 00034 #endif 00035 00036 00037 00038 00039 00040 /****************************************************************************** 00041 * Constructor 00042 *****************************************************************************/ 00043 ntlRay::ntlRay( void ) 00044 : mOrigin(0.0) 00045 , mDirection(0.0) 00046 , mvNormal(0.0) 00047 , mDepth(0) 00048 , mpGlob(NULL) 00049 , mIsRefracted(0) 00050 { 00051 errFatal("ntlRay::ntlRay()","Don't use uninitialized rays !", SIMWORLD_GENERICERROR); 00052 return; 00053 } 00054 00055 00056 /****************************************************************************** 00057 * Copy - Constructor 00058 *****************************************************************************/ 00059 ntlRay::ntlRay( const ntlRay &r ) 00060 { 00061 // copy it! initialization is not enough! 00062 mOrigin = r.mOrigin; 00063 mDirection = r.mDirection; 00064 mvNormal = r.mvNormal; 00065 mDepth = r.mDepth; 00066 mIsRefracted = r.mIsRefracted; 00067 mIsReflected = r.mIsReflected; 00068 mContribution = r.mContribution; 00069 mpGlob = r.mpGlob; 00070 00071 // get new ID 00072 if(mpGlob) { 00073 mID = mpGlob->getCounterRays()+1; 00074 mpGlob->setCounterRays( mpGlob->getCounterRays()+1 ); 00075 } else { 00076 mID = 0; 00077 } 00078 } 00079 00080 00081 /****************************************************************************** 00082 * Constructor with explicit parameters and global render object 00083 *****************************************************************************/ 00084 ntlRay::ntlRay(const ntlVec3Gfx &o, const ntlVec3Gfx &d, unsigned int i, gfxReal contrib, ntlRenderGlobals *glob) 00085 : mOrigin( o ) 00086 , mDirection( d ) 00087 , mvNormal(0.0) 00088 , mDepth( i ) 00089 , mContribution( contrib ) 00090 , mpGlob( glob ) 00091 , mIsRefracted( 0 ) 00092 , mIsReflected( 0 ) 00093 { 00094 // get new ID 00095 if(mpGlob) { 00096 mID = mpGlob->getCounterRays()+1; 00097 mpGlob->setCounterRays( mpGlob->getCounterRays()+1 ); 00098 } else { 00099 mID = 0; 00100 } 00101 } 00102 00103 00104 00105 /****************************************************************************** 00106 * Destructor 00107 *****************************************************************************/ 00108 ntlRay::~ntlRay() 00109 { 00110 /* nothing to do... */ 00111 } 00112 00113 00114 00115 /****************************************************************************** 00116 * AABB 00117 *****************************************************************************/ 00118 /* for AABB intersect */ 00119 #define NUMDIM 3 00120 #define RIGHT 0 00121 #define LEFT 1 00122 #define MIDDLE 2 00123 00125 #ifndef ELBEEM_PLUGIN 00126 void ntlRay::intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &retnormal,ntlVec3Gfx &retcoord) const 00127 { 00128 char inside = true; /* inside box? */ 00129 char hit = false; /* ray hits box? */ 00130 int whichPlane; /* intersection plane */ 00131 gfxReal candPlane[NUMDIM]; /* candidate plane */ 00132 gfxReal quadrant[NUMDIM]; /* quadrants */ 00133 gfxReal maxT[NUMDIM]; /* max intersection T for planes */ 00134 ntlVec3Gfx coord; /* intersection point */ 00135 ntlVec3Gfx dir = mDirection; 00136 ntlVec3Gfx origin = mOrigin; 00137 ntlVec3Gfx normal(0.0, 0.0, 0.0); 00138 00139 t = GFX_REAL_MAX; 00140 00141 /* check intersection planes for AABB */ 00142 for(int i=0;i<NUMDIM;i++) { 00143 if(origin[i] < mStart[i]) { 00144 quadrant[i] = LEFT; 00145 candPlane [i] = mStart[i]; 00146 inside = false; 00147 } else if(origin[i] > mEnd[i]) { 00148 quadrant[i] = RIGHT; 00149 candPlane[i] = mEnd[i]; 00150 inside = false; 00151 } else { 00152 quadrant[i] = MIDDLE; 00153 } 00154 } 00155 00156 /* inside AABB? */ 00157 if(!inside) { 00158 /* get t distances to planes */ 00159 /* treat too small direction components as paralell */ 00160 for(int i=0;i<NUMDIM;i++) { 00161 if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) { 00162 maxT[i] = (candPlane[i] - origin[i]) / dir[i]; 00163 } else { 00164 maxT[i] = -1; 00165 } 00166 } 00167 00168 /* largest max t */ 00169 whichPlane = 0; 00170 for(int i=1;i<NUMDIM;i++) { 00171 if(maxT[whichPlane] < maxT[i]) whichPlane = i; 00172 } 00173 00174 /* check final candidate */ 00175 hit = true; 00176 if(maxT[whichPlane] >= 0.0) { 00177 00178 for(int i=0;i<NUMDIM;i++) { 00179 if(whichPlane != i) { 00180 coord[i] = origin[i] + maxT[whichPlane] * dir[i]; 00181 if( (coord[i] < mStart[i]-getVecEpsilon() ) || 00182 (coord[i] > mEnd[i] +getVecEpsilon() ) ) { 00183 /* no hit... */ 00184 hit = false; 00185 } 00186 } 00187 else { 00188 coord[i] = candPlane[i]; 00189 } 00190 } 00191 00192 /* AABB hit... */ 00193 if( hit ) { 00194 t = maxT[whichPlane]; 00195 if(quadrant[whichPlane]==RIGHT) normal[whichPlane] = 1.0; 00196 else normal[whichPlane] = -1.0; 00197 } 00198 } 00199 00200 00201 } else { 00202 /* inside AABB... */ 00203 t = 0.0; 00204 coord = origin; 00205 return; 00206 } 00207 00208 if(t == GFX_REAL_MAX) t = -1.0; 00209 retnormal = normal; 00210 retcoord = coord; 00211 } 00212 00214 void ntlRay::intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &retnormal,ntlVec3Gfx &retcoord) const 00215 { 00216 char hit = false; /* ray hits box? */ 00217 int whichPlane; /* intersection plane */ 00218 gfxReal candPlane[NUMDIM]; /* candidate plane */ 00219 gfxReal quadrant[NUMDIM]; /* quadrants */ 00220 gfxReal maxT[NUMDIM]; /* max intersection T for planes */ 00221 ntlVec3Gfx coord; /* intersection point */ 00222 ntlVec3Gfx dir = mDirection; 00223 ntlVec3Gfx origin = mOrigin; 00224 ntlVec3Gfx normal(0.0, 0.0, 0.0); 00225 00226 t = GFX_REAL_MAX; 00227 for(int i=0;i<NUMDIM;i++) { 00228 if(origin[i] < mStart[i]) { 00229 quadrant[i] = LEFT; 00230 candPlane [i] = mEnd[i]; 00231 } else if(origin[i] > mEnd[i]) { 00232 quadrant[i] = RIGHT; 00233 candPlane[i] = mStart[i]; 00234 } else { 00235 if(dir[i] > 0) { 00236 quadrant[i] = LEFT; 00237 candPlane [i] = mEnd[i]; 00238 } else 00239 if(dir[i] < 0) { 00240 quadrant[i] = RIGHT; 00241 candPlane[i] = mStart[i]; 00242 } else { 00243 quadrant[i] = MIDDLE; 00244 } 00245 } 00246 } 00247 00248 00249 /* get t distances to planes */ 00250 /* treat too small direction components as paralell */ 00251 for(int i=0;i<NUMDIM;i++) { 00252 if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) { 00253 maxT[i] = (candPlane[i] - origin[i]) / dir[i]; 00254 } else { 00255 maxT[i] = GFX_REAL_MAX; 00256 } 00257 } 00258 00259 /* largest max t */ 00260 whichPlane = 0; 00261 for(int i=1;i<NUMDIM;i++) { 00262 if(maxT[whichPlane] > maxT[i]) whichPlane = i; 00263 } 00264 00265 /* check final candidate */ 00266 hit = true; 00267 if(maxT[whichPlane] != GFX_REAL_MAX) { 00268 00269 for(int i=0;i<NUMDIM;i++) { 00270 if(whichPlane != i) { 00271 coord[i] = origin[i] + maxT[whichPlane] * dir[i]; 00272 if( (coord[i] < mStart[i]-getVecEpsilon() ) || 00273 (coord[i] > mEnd[i] +getVecEpsilon() ) ) { 00274 /* no hit... */ 00275 hit = false; 00276 } 00277 } 00278 else { 00279 coord[i] = candPlane[i]; 00280 } 00281 } 00282 00283 /* AABB hit... */ 00284 if( hit ) { 00285 t = maxT[whichPlane]; 00286 00287 if(quadrant[whichPlane]==RIGHT) normal[whichPlane] = 1.0; 00288 else normal[whichPlane] = -1.0; 00289 } 00290 } 00291 00292 00293 if(t == GFX_REAL_MAX) t = -1.0; 00294 retnormal = normal; 00295 retcoord = coord; 00296 } 00297 #endif // ELBEEM_PLUGIN 00298 00300 void ntlRay::intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const 00301 { 00302 char inside = true; /* inside box? */ 00303 char hit = false; /* ray hits box? */ 00304 int whichPlane; /* intersection plane */ 00305 gfxReal candPlane[NUMDIM]; /* candidate plane */ 00306 gfxReal quadrant[NUMDIM]; /* quadrants */ 00307 gfxReal maxT[NUMDIM]; /* max intersection T for planes */ 00308 ntlVec3Gfx coord; /* intersection point */ 00309 ntlVec3Gfx dir = mDirection; 00310 ntlVec3Gfx origin = mOrigin; 00311 gfxReal t = GFX_REAL_MAX; 00312 00313 /* check intersection planes for AABB */ 00314 for(int i=0;i<NUMDIM;i++) { 00315 if(origin[i] < mStart[i]) { 00316 quadrant[i] = LEFT; 00317 candPlane [i] = mStart[i]; 00318 inside = false; 00319 } else if(origin[i] > mEnd[i]) { 00320 quadrant[i] = RIGHT; 00321 candPlane[i] = mEnd[i]; 00322 inside = false; 00323 } else { 00324 /* intersect with backside */ 00325 if(dir[i] > 0) { 00326 quadrant[i] = LEFT; 00327 candPlane [i] = mStart[i]; 00328 } else 00329 if(dir[i] < 0) { 00330 quadrant[i] = RIGHT; 00331 candPlane[i] = mEnd[i]; 00332 } else { 00333 quadrant[i] = MIDDLE; 00334 } 00335 } 00336 } 00337 00338 /* get t distances to planes */ 00339 for(int i=0;i<NUMDIM;i++) { 00340 if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) { 00341 maxT[i] = (candPlane[i] - origin[i]) / dir[i]; 00342 } else { 00343 maxT[i] = GFX_REAL_MAX; 00344 } 00345 } 00346 00347 /* largest max t */ 00348 whichPlane = 0; 00349 for(int i=1;i<NUMDIM;i++) { 00350 if( ((maxT[whichPlane] < maxT[i])&&(maxT[i]!=GFX_REAL_MAX)) || 00351 (maxT[whichPlane]==GFX_REAL_MAX) ) 00352 whichPlane = i; 00353 } 00354 00355 /* check final candidate */ 00356 hit = true; 00357 if(maxT[whichPlane]<GFX_REAL_MAX) { 00358 for(int i=0;i<NUMDIM;i++) { 00359 if(whichPlane != i) { 00360 coord[i] = origin[i] + maxT[whichPlane] * dir[i]; 00361 if( (coord[i] < mStart[i]-getVecEpsilon() ) || 00362 (coord[i] > mEnd[i] +getVecEpsilon() ) ) { 00363 /* no hit... */ 00364 hit = false; 00365 } 00366 } 00367 else { coord[i] = candPlane[i]; } 00368 } 00369 00370 /* AABB hit... */ 00371 if( hit ) { 00372 t = maxT[whichPlane]; 00373 } 00374 } 00375 tmin = t; 00376 00377 /* now the backside */ 00378 t = GFX_REAL_MAX; 00379 for(int i=0;i<NUMDIM;i++) { 00380 if(origin[i] < mStart[i]) { 00381 quadrant[i] = LEFT; 00382 candPlane [i] = mEnd[i]; 00383 } else if(origin[i] > mEnd[i]) { 00384 quadrant[i] = RIGHT; 00385 candPlane[i] = mStart[i]; 00386 } else { 00387 if(dir[i] > 0) { 00388 quadrant[i] = LEFT; 00389 candPlane [i] = mEnd[i]; 00390 } else 00391 if(dir[i] < 0) { 00392 quadrant[i] = RIGHT; 00393 candPlane[i] = mStart[i]; 00394 } else { 00395 quadrant[i] = MIDDLE; 00396 } 00397 } 00398 } 00399 00400 00401 /* get t distances to planes */ 00402 for(int i=0;i<NUMDIM;i++) { 00403 if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) { 00404 maxT[i] = (candPlane[i] - origin[i]) / dir[i]; 00405 } else { 00406 maxT[i] = GFX_REAL_MAX; 00407 } 00408 } 00409 00410 /* smallest max t */ 00411 whichPlane = 0; 00412 for(int i=1;i<NUMDIM;i++) { 00413 if(maxT[whichPlane] > maxT[i]) whichPlane = i; 00414 } 00415 00416 /* check final candidate */ 00417 hit = true; 00418 if(maxT[whichPlane] != GFX_REAL_MAX) { 00419 00420 for(int i=0;i<NUMDIM;i++) { 00421 if(whichPlane != i) { 00422 coord[i] = origin[i] + maxT[whichPlane] * dir[i]; 00423 if( (coord[i] < mStart[i]-getVecEpsilon() ) || 00424 (coord[i] > mEnd[i] +getVecEpsilon() ) ) { 00425 /* no hit... */ 00426 hit = false; 00427 } 00428 } 00429 else { 00430 coord[i] = candPlane[i]; 00431 } 00432 } 00433 00434 /* AABB hit... */ 00435 if( hit ) { 00436 t = maxT[whichPlane]; 00437 } 00438 } 00439 00440 tmax = t; 00441 } 00442 00443 00444 00445 /****************************************************************************** 00446 * Determine color of this ray by tracing through the scene 00447 *****************************************************************************/ 00448 const ntlColor ntlRay::shade() //const 00449 { 00450 #ifndef ELBEEM_PLUGIN 00451 ntlGeometryObject *closest = NULL; 00452 gfxReal minT = GFX_REAL_MAX; 00453 vector<ntlLightObject*> *lightlist = mpGlob->getLightList(); 00454 mpGlob->setCounterShades( mpGlob->getCounterShades()+1 ); 00455 bool intersectionInside = 0; 00456 if(mpGlob->getDebugOut() > 5) errorOut(std::endl<<"New Ray: depth "<<mDepth<<", org "<<mOrigin<<", dir "<<mDirection ); 00457 00458 /* check if this ray contributes enough */ 00459 if(mContribution <= RAY_MINCONTRIB) { 00460 //return ntlColor(0.0); 00461 } 00462 00463 /* find closes object that intersects */ 00464 ntlTriangle *tri = NULL; 00465 ntlVec3Gfx normal; 00466 mpGlob->getRenderScene()->intersectScene(*this, minT, normal, tri, 0); 00467 if(minT>0) { 00468 closest = mpGlob->getRenderScene()->getObject( tri->getObjectId() ); 00469 } 00470 00471 /* object hit... */ 00472 if (closest != NULL) { 00473 00474 ntlVec3Gfx triangleNormal = tri->getNormal(); 00475 if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) errorOut("ntlRay warning: trinagle normal= 0 "); // DEBUG 00476 /* intersection on inside faces? if yes invert normal afterwards */ 00477 gfxReal valDN; // = mDirection | normal; 00478 valDN = dot(mDirection, triangleNormal); 00479 if( valDN > 0.0) { 00480 intersectionInside = 1; 00481 normal = normal * -1.0; 00482 triangleNormal = triangleNormal * -1.0; 00483 } 00484 00485 /* ... -> do reflection */ 00486 ntlVec3Gfx intersectionPosition(mOrigin + (mDirection * (minT)) ); 00487 ntlMaterial *clossurf = closest->getMaterial(); 00488 /*if(mpGlob->getDebugOut() > 5) { 00489 errorOut("Ray hit: at "<<intersectionPosition<<" n:"<<normal<<" dn:"<<valDN<<" ins:"<<intersectionInside<<" cl:"<<((unsigned int)closest) ); 00490 errorOut(" t1:"<<mpGlob->getRenderScene()->getVertex(tri->getPoints()[0])<<" t2:"<<mpGlob->getRenderScene()->getVertex(tri->getPoints()[1])<<" t3:"<<mpGlob->getScene()->getVertex(tri->getPoints()[2]) ); 00491 errorOut(" trin:"<<tri->getNormal() ); 00492 } // debug */ 00493 00494 /* current transparence and reflectivity */ 00495 gfxReal currTrans = clossurf->getTransparence(); 00496 gfxReal currRefl = clossurf->getMirror(); 00497 00498 /* correct intersectopm position */ 00499 intersectionPosition += ( triangleNormal*getVecEpsilon() ); 00500 /* reflection at normal */ 00501 ntlVec3Gfx reflectedDir = getNormalized( reflectVector(mDirection, normal) ); 00502 int badRefl = 0; 00503 if(dot(reflectedDir, triangleNormal)<0.0 ) { 00504 badRefl = 1; 00505 if(mpGlob->getDebugOut() > 5) { errorOut("Ray Bad reflection...!"); } 00506 } 00507 00508 /* refraction direction, depending on in/outside hit */ 00509 ntlVec3Gfx refractedDir; 00510 int refRefl = 0; 00511 /* refraction at normal is handled by inverting normal before */ 00512 gfxReal myRefIndex = 1.0; 00513 if((currTrans>RAY_THRESHOLD)||(clossurf->getFresnel())) { 00514 if(intersectionInside) { 00515 myRefIndex = 1.0/clossurf->getRefracIndex(); 00516 } else { 00517 myRefIndex = clossurf->getRefracIndex(); 00518 } 00519 00520 refractedDir = refractVector(mDirection, normal, myRefIndex , (gfxReal)(1.0) /* global ref index */, refRefl); 00521 } 00522 00523 /* calculate fresnel? */ 00524 if(clossurf->getFresnel()) { 00525 // for total reflection, just set trans to 0 00526 if(refRefl) { 00527 currRefl = 1.0; currTrans = 0.0; 00528 } else { 00529 // calculate fresnel coefficients 00530 clossurf->calculateFresnel( mDirection, normal, myRefIndex, currRefl,currTrans ); 00531 } 00532 } 00533 00534 ntlRay reflectedRay(intersectionPosition, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob); 00535 reflectedRay.setNormal( normal ); 00536 ntlColor currentColor(0.0); 00537 ntlColor highlightColor(0.0); 00538 00539 /* first add reflected ambient color */ 00540 currentColor += (clossurf->getAmbientRefl() * mpGlob->getAmbientLight() ); 00541 00542 /* calculate lighting, not on the insides of objects... */ 00543 if(!intersectionInside) { 00544 for (vector<ntlLightObject*>::iterator iter = lightlist->begin(); 00545 iter != lightlist->end(); 00546 iter++) { 00547 00548 /* let light illuminate point */ 00549 currentColor += (*iter)->illuminatePoint( reflectedRay, closest, highlightColor ); 00550 00551 } // for all lights 00552 } 00553 00554 // recurse ? 00555 if ((mDepth < mpGlob->getRayMaxDepth() )&&(currRefl>RAY_THRESHOLD)) { 00556 00557 if(badRefl) { 00558 ntlVec3Gfx intersectionPosition2; 00559 ntlGeometryObject *closest2 = NULL; 00560 gfxReal minT2 = GFX_REAL_MAX; 00561 ntlTriangle *tri2 = NULL; 00562 ntlVec3Gfx normal2; 00563 00564 ntlVec3Gfx refractionPosition2(mOrigin + (mDirection * minT) ); 00565 refractionPosition2 -= (triangleNormal*getVecEpsilon() ); 00566 00567 ntlRay reflectedRay2 = ntlRay(refractionPosition2, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob); 00568 mpGlob->getRenderScene()->intersectScene(reflectedRay2, minT2, normal2, tri2, 0); 00569 if(minT2>0) { 00570 closest2 = mpGlob->getRenderScene()->getObject( tri2->getObjectId() ); 00571 } 00572 00573 /* object hit... */ 00574 if (closest2 != NULL) { 00575 ntlVec3Gfx triangleNormal2 = tri2->getNormal(); 00576 gfxReal valDN2; 00577 valDN2 = dot(reflectedDir, triangleNormal2); 00578 if( valDN2 > 0.0) { 00579 triangleNormal2 = triangleNormal2 * -1.0; 00580 intersectionPosition2 = ntlVec3Gfx(intersectionPosition + (reflectedDir * (minT2)) ); 00581 /* correct intersection position and create new reflected ray */ 00582 intersectionPosition2 += ( triangleNormal2*getVecEpsilon() ); 00583 reflectedRay = ntlRay(intersectionPosition2, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob); 00584 } else { 00585 // ray seems to work, continue normally ? 00586 } 00587 00588 } 00589 00590 } 00591 00592 // add mirror color multiplied by mirror factor of surface 00593 if(mpGlob->getDebugOut() > 5) errorOut("Reflected ray from depth "<<mDepth<<", dir "<<reflectedDir ); 00594 ntlColor reflectedColor = reflectedRay.shade() * currRefl; 00595 currentColor += reflectedColor; 00596 } 00597 00598 /* Trace another ray on for transparent objects */ 00599 if(currTrans > RAY_THRESHOLD) { 00600 /* position at the other side of the surface, along ray */ 00601 ntlVec3Gfx refraction_position(mOrigin + (mDirection * minT) ); 00602 refraction_position += (mDirection * getVecEpsilon()); 00603 refraction_position -= (triangleNormal*getVecEpsilon() ); 00604 ntlColor refracCol(0.0); /* refracted color */ 00605 00606 /* trace refracted ray */ 00607 ntlRay transRay(refraction_position, refractedDir, mDepth+1, mContribution*currTrans, mpGlob); 00608 transRay.setRefracted(1); 00609 transRay.setNormal( normal ); 00610 if(mDepth < mpGlob->getRayMaxDepth() ) { 00611 // full reflection should make sure refracindex&fresnel are on... 00612 if((0)||(!refRefl)) { 00613 if(mpGlob->getDebugOut() > 5) errorOut("Refracted ray from depth "<<mDepth<<", dir "<<refractedDir ); 00614 refracCol = transRay.shade(); 00615 } else { 00616 //we shouldnt reach this! 00617 if(mpGlob->getDebugOut() > 5) errorOut("Fully reflected ray from depth "<<mDepth<<", dir "<<reflectedDir ); 00618 refracCol = reflectedRay.shade(); 00619 } 00620 } 00621 //errMsg("REFMIR","t"<<currTrans<<" thres"<<RAY_THRESHOLD<<" mirr"<<currRefl<<" refRefl"<<refRefl<<" md"<<mDepth); 00622 00623 /* calculate color */ 00624 // use transadditive setting!? 00625 /* additive transparency "light amplification" */ 00626 //? ntlColor add_col = currentColor + refracCol * currTrans; 00627 /* mix additive and subtractive */ 00628 //? add_col += sub_col; 00629 //? currentColor += (refracCol * currTrans); 00630 00631 /* subtractive transparency, more realistic */ 00632 ntlColor sub_col = (refracCol * currTrans) + ( currentColor * (1.0-currTrans) ); 00633 currentColor = sub_col; 00634 00635 } 00636 00637 /* add highlights (should not be affected by transparence as the diffuse reflections */ 00638 currentColor += highlightColor; 00639 00640 /* attentuate as a last step*/ 00641 /* check if we're on the inside or outside */ 00642 if(intersectionInside) { 00643 gfxReal kr,kg,kb; /* attentuation */ 00644 /* calculate attentuation */ 00645 ntlColor attCol = clossurf->getTransAttCol(); 00646 kr = exp( attCol[0] * minT ); 00647 kg = exp( attCol[1] * minT ); 00648 kb = exp( attCol[2] * minT ); 00649 currentColor = currentColor * ntlColor(kr,kg,kb); 00650 } 00651 00652 /* done... */ 00653 if(mpGlob->getDebugOut() > 5) { errorOut("Ray "<<mDepth<<" color "<<currentColor ); } 00654 return ntlColor(currentColor); 00655 } 00656 00657 #endif // ELBEEM_PLUGIN 00658 /* no object hit -> ray goes to infinity */ 00659 return mpGlob->getBackgroundCol(); 00660 } 00661 00662 00663 00664 /****************************************************************************** 00665 ****************************************************************************** 00666 ****************************************************************************** 00667 * scene implementation 00668 ****************************************************************************** 00669 ****************************************************************************** 00670 *****************************************************************************/ 00671 00672 00673 00674 /****************************************************************************** 00675 * Constructor 00676 *****************************************************************************/ 00677 ntlScene::ntlScene( ntlRenderGlobals *glob, bool del ) : 00678 mpGlob( glob ), mSceneDel(del), 00679 mpTree( NULL ), 00680 mDisplayListId( -1 ), 00681 mSceneBuilt( false ), mFirstInitDone( false ) 00682 { 00683 } 00684 00685 00686 /****************************************************************************** 00687 * Destructor 00688 *****************************************************************************/ 00689 ntlScene::~ntlScene() 00690 { 00691 if(mpTree != NULL) delete mpTree; 00692 00693 // cleanup lists, only if this is the rendering cleanup scene 00694 if(mSceneDel) 00695 { 00696 for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); 00697 iter != mGeos.end(); iter++) { 00698 //errMsg("ntlScene::~ntlScene","Deleting obj "<<(*iter)->getName() ); 00699 delete (*iter); 00700 } 00701 for (vector<ntlLightObject*>::iterator iter = mpGlob->getLightList()->begin(); 00702 iter != mpGlob->getLightList()->end(); iter++) { 00703 delete (*iter); 00704 } 00705 for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin(); 00706 iter != mpGlob->getMaterials()->end(); iter++) { 00707 delete (*iter); 00708 } 00709 } 00710 errMsg("ntlScene::~ntlScene","Deleted, ObjFree:"<<mSceneDel); 00711 } 00712 00713 00714 /****************************************************************************** 00715 * Build the scene arrays (obj, tris etc.) 00716 *****************************************************************************/ 00717 void ntlScene::buildScene(double time,bool firstInit) 00718 { 00719 const bool buildInfo=true; 00720 00721 if(firstInit) { 00722 mObjects.clear(); 00723 /* init geometry array, first all standard objects */ 00724 for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); 00725 iter != mGeos.end(); iter++) { 00726 bool geoinit = false; 00727 int tid = (*iter)->getTypeId(); 00728 if(tid & GEOCLASSTID_OBJECT) { 00729 ntlGeometryObject *geoobj = (ntlGeometryObject*)(*iter); 00730 geoinit = true; 00731 mObjects.push_back( geoobj ); 00732 if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName()<<" Id:"<<geoobj->getObjectId(), 5 ); 00733 } 00734 //if(geoshad) { 00735 if(tid & GEOCLASSTID_SHADER) { 00736 ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); 00737 geoinit = true; 00738 if(!mFirstInitDone) { 00739 // only on first init 00740 geoshad->initializeShader(); 00741 } 00742 for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin(); 00743 siter != geoshad->getObjectsEnd(); 00744 siter++) { 00745 if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName()<<" Id:"<<(*siter)->getObjectId(), 5 ); 00746 mObjects.push_back( (*siter) ); 00747 } 00748 } 00749 00750 if(!geoinit) { 00751 errFatal("ntlScene::BuildScene","Invalid geometry class!", SIMWORLD_INITERROR); 00752 return; 00753 } 00754 } 00755 } 00756 00757 // collect triangles 00758 mTriangles.clear(); 00759 mVertices.clear(); 00760 mVertNormals.clear(); 00761 00762 /* for test mode deactivate transparencies etc. */ 00763 if( mpGlob->getTestMode() ) { 00764 debugOut("ntlScene::buildScene : Test Mode activated!", 2); 00765 // assign random colors to dark materials 00766 int matCounter = 0; 00767 ntlColor stdCols[] = { ntlColor(0,0,1.0), ntlColor(0,1.0,0), ntlColor(1.0,0.7,0) , ntlColor(0.7,0,0.6) }; 00768 int stdColNum = 4; 00769 for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin(); 00770 iter != mpGlob->getMaterials()->end(); iter++) { 00771 (*iter)->setTransparence(0.0); 00772 (*iter)->setMirror(0.0); 00773 (*iter)->setFresnel(false); 00774 // too dark? 00775 if( norm((*iter)->getDiffuseRefl()) <0.01) { 00776 (*iter)->setDiffuseRefl( stdCols[matCounter] ); 00777 matCounter ++; 00778 matCounter = matCounter%stdColNum; 00779 } 00780 } 00781 00782 // restrict output file size to 400 00783 float downscale = 1.0; 00784 if(mpGlob->getResX() > 400){ downscale = 400.0/(float)mpGlob->getResX(); } 00785 if(mpGlob->getResY() > 400){ 00786 float downscale2 = 400.0/(float)mpGlob->getResY(); 00787 if(downscale2<downscale) downscale=downscale2; 00788 } 00789 mpGlob->setResX( (int)(mpGlob->getResX() * downscale) ); 00790 mpGlob->setResY( (int)(mpGlob->getResY() * downscale) ); 00791 00792 } 00793 00794 /* collect triangles from objects */ 00795 int idCnt = 0; // give IDs to objects 00796 bool debugTriCollect = false; 00797 if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Start...",5); 00798 for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); 00799 iter != mObjects.end(); 00800 iter++) { 00801 /* only add visible objects */ 00802 if(firstInit) { 00803 if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Collect init of "<<(*iter)->getName()<<" idCnt:"<<idCnt, 4 ); 00804 (*iter)->initialize( mpGlob ); } 00805 if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Collecting tris from "<<(*iter)->getName(), 4 ); 00806 00807 int vstart = mVertNormals.size(); 00808 (*iter)->setObjectId(idCnt); 00809 (*iter)->getTriangles(time, &mTriangles, &mVertices, &mVertNormals, idCnt); 00810 (*iter)->applyTransformation(time, &mVertices, &mVertNormals, vstart, mVertices.size(), false ); 00811 00812 if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"Done with "<<(*iter)->getName()<<" totTris:"<<mTriangles.size()<<" totVerts:"<<mVertices.size()<<" totNorms:"<<mVertNormals.size(), 4 ); 00813 idCnt ++; 00814 } 00815 if(debugTriCollect) debMsgStd("ntlScene::buildScene",DM_MSG,"End",5); 00816 00817 00818 /* calculate triangle normals, and initialize flags */ 00819 for (vector<ntlTriangle>::iterator iter = mTriangles.begin(); 00820 iter != mTriangles.end(); 00821 iter++) { 00822 00823 // calculate normal from triangle points 00824 ntlVec3Gfx normal = 00825 cross( (ntlVec3Gfx)( (mVertices[(*iter).getPoints()[2]] - mVertices[(*iter).getPoints()[0]]) *-1.0), // BLITZ minus sign right?? 00826 (ntlVec3Gfx)(mVertices[(*iter).getPoints()[1]] - mVertices[(*iter).getPoints()[0]]) ); 00827 normalize(normal); 00828 (*iter).setNormal( normal ); 00829 } 00830 00831 00832 00833 // scene geometry built 00834 mSceneBuilt = true; 00835 00836 // init shaders that require complete geometry 00837 if(!mFirstInitDone) { 00838 // only on first init 00839 for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); 00840 iter != mGeos.end(); iter++) { 00841 if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) { 00842 ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); 00843 if(geoshad->postGeoConstrInit( mpGlob )) { 00844 errFatal("ntlScene::buildScene","Init failed for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); 00845 return; 00846 } 00847 } 00848 } 00849 mFirstInitDone = true; 00850 } 00851 00852 // check unused attributes (for classes and objects!) 00853 for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); iter != mObjects.end(); iter++) { 00854 if((*iter)->getAttributeList()->checkUnusedParams()) { 00855 (*iter)->getAttributeList()->print(); // DEBUG 00856 errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); 00857 return; 00858 } 00859 } 00860 for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); iter != mGeos.end(); iter++) { 00861 if((*iter)->getAttributeList()->checkUnusedParams()) { 00862 (*iter)->getAttributeList()->print(); // DEBUG 00863 errFatal("ntlScene::buildScene","Unused params for object '"<< (*iter)->getName() <<"' !", SIMWORLD_INITERROR ); 00864 return; 00865 } 00866 } 00867 00868 } 00869 00870 /****************************************************************************** 00871 * Prepare the scene triangles and maps for raytracing 00872 *****************************************************************************/ 00873 void ntlScene::prepareScene(double time) 00874 { 00875 /* init triangles... */ 00876 buildScene(time, false); 00877 // what for currently not used ??? 00878 if(mpTree != NULL) delete mpTree; 00879 mpTree = new ntlTree( 00880 # if FSGR_STRICT_DEBUG!=1 00881 mpGlob->getTreeMaxDepth(), mpGlob->getTreeMaxTriangles(), 00882 # else 00883 mpGlob->getTreeMaxDepth()/3*2, mpGlob->getTreeMaxTriangles()*2, 00884 # endif 00885 this, TRI_GEOMETRY ); 00886 00887 //debMsgStd("ntlScene::prepareScene",DM_MSG,"Stats - tris:"<< (int)mTriangles.size()<<" verts:"<<mVertices.size()<<" vnorms:"<<mVertNormals.size(), 5 ); 00888 } 00889 /****************************************************************************** 00890 * Do some memory cleaning, when frame is finished 00891 *****************************************************************************/ 00892 void ntlScene::cleanupScene( void ) 00893 { 00894 mTriangles.clear(); 00895 mVertices.clear(); 00896 mVertNormals.clear(); 00897 00898 if(mpTree != NULL) delete mpTree; 00899 mpTree = NULL; 00900 } 00901 00902 00903 /****************************************************************************** 00904 * Intersect a ray with the scene triangles 00905 *****************************************************************************/ 00906 void ntlScene::intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri,int flags) const 00907 { 00908 distance = -1.0; 00909 mpGlob->setCounterSceneInter( mpGlob->getCounterSceneInter()+1 ); 00910 mpTree->intersect(r, distance, normal, tri, flags, false); 00911 } 00912 00913 00914 00915 00916