00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045
00046 #include "OSGShadowStage.h"
00047
00048 #include "OSGShadowStageData.h"
00049
00050 #include "OSGGeometry.h"
00051 #include "OSGMaterialGroup.h"
00052 #include "OSGMultiPassMaterial.h"
00053
00054 #include "OSGSpotLight.h"
00055 #include "OSGDirectionalLight.h"
00056 #include "OSGMatrixUtility.h"
00057
00058 #include "OSGPerspectiveCamera.h"
00059 #include "OSGMatrixCamera.h"
00060 #include "OSGMultiCore.h"
00061
00062 #define OSG_HAS_STDMAP
00063 #define OSG_HAS_PERSPMAP
00064 #define OSG_HAS_DITHERMAP
00065 #define OSG_HAS_PCFMAP
00066 #define OSG_HAS_PCSSMAP
00067 #define OSG_HAS_VARMAP
00068
00069 #ifdef OSG_HAS_STDMAP
00070 #include "OSGStdShadowMapHandler.h"
00071 #endif
00072 #ifdef OSG_HAS_PERSPMAP
00073 #include "OSGPerspectiveShadowMapHandler.h"
00074 #endif
00075 #ifdef OSG_HAS_DITHERMAP
00076 #include "OSGDitherShadowMapHandler.h"
00077 #endif
00078 #ifdef OSG_HAS_PCFMAP
00079 #include "OSGPCFShadowMapHandler.h"
00080 #endif
00081 #ifdef OSG_HAS_PCSSMAP
00082 #include "OSGPCSSShadowMapHandler.h"
00083 #endif
00084 #ifdef OSG_HAS_VARMAP
00085 #include "OSGVarianceShadowMapHandler.h"
00086 #endif
00087
00088 #include "OSGRenderAction.h"
00089 #include <boost/bind.hpp>
00090 #include "OSGTextureBuffer.h"
00091
00092
00093
00094 OSG_USING_NAMESPACE
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 UInt32 ShadowStage::_extSHL = Window::invalidExtensionID;
00105 UInt32 ShadowStage::_extDepthTexture = Window::invalidExtensionID;
00106 UInt32 ShadowStage::_extShadows = Window::invalidExtensionID;
00107 UInt32 ShadowStage::_extFramebufferObject = Window::invalidExtensionID;
00108 UInt32 ShadowStage::_extDrawBuffers = Window::invalidExtensionID;
00109
00110 UInt32 ShadowStage::FuncIdGenMipmaps = Window::invalidFunctionID;
00111
00112
00113
00114
00115
00116 void ShadowStage::initMethod(InitPhase ePhase)
00117 {
00118 Inherited::initMethod(ePhase);
00119
00120 if(ePhase == TypeObject::SystemPost)
00121 {
00122 RenderAction::registerEnterDefault(
00123 ShadowStage::getClassType(),
00124 reinterpret_cast<Action::Callback>(&ShadowStage::renderEnter));
00125
00126 RenderAction::registerLeaveDefault(
00127 ShadowStage::getClassType(),
00128 reinterpret_cast<Action::Callback>(&ShadowStage::renderLeave));
00129
00130 _extSHL =
00131 Window::registerExtension("GL_ARB_shading_language_100");
00132
00133 _extDepthTexture =
00134 Window::registerExtension("GL_ARB_depth_texture");
00135
00136 _extShadows =
00137 Window::registerExtension("GL_ARB_shadow");
00138
00139 _extFramebufferObject =
00140 Window::registerExtension("GL_EXT_framebuffer_object");
00141
00142 _extDrawBuffers =
00143 Window::registerExtension("GL_ARB_draw_buffers");
00144
00145
00146 FuncIdGenMipmaps =
00147 Window::registerFunction(OSG_DLSYM_UNDERSCORE"glGenerateMipmapEXT",
00148 _extFramebufferObject);
00149 }
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 ShadowStage::ShadowStage(void) :
00164 Inherited ( ),
00165 _trigger_update(false),
00166 _occlusionQuery(0 )
00167 {
00168 }
00169
00170 ShadowStage::ShadowStage(const ShadowStage &source) :
00171 Inherited (source ),
00172 _trigger_update(source._trigger_update),
00173 _occlusionQuery(source._occlusionQuery)
00174 {
00175
00176 }
00177
00178 ShadowStage::~ShadowStage(void)
00179 {
00180 }
00181
00182
00183
00184 void ShadowStage::changed(ConstFieldMaskArg whichField,
00185 UInt32 origin,
00186 BitVector details )
00187 {
00188 if(whichField & LightNodesFieldMask)
00189 {
00190 #if 0
00191 FDEBUG(("ShadowStage::changed : light nodes changed.\n"));
00192 _lights.clear();
00193 for(UInt32 i = 0;i < getMFLightNodes()->size();++i)
00194 _lights.push_back(
00195 std::make_pair(
00196 getLightNodes(i),
00197 dynamic_cast<Light *>(getLightNodes(i)->getCore())));
00198 #endif
00199 }
00200
00201 if(whichField & MapAutoUpdateFieldMask)
00202 {
00203 _trigger_update = true;
00204 }
00205
00206 if(whichField & AutoSearchForLightsFieldMask)
00207 {
00208 if(getAutoSearchForLights())
00209 {
00210 FNOTICE(("auto light search mode on\n"));
00211 }
00212 else
00213 {
00214 FNOTICE(("auto light search mode off\n"));
00215 }
00216 }
00217
00218 if(whichField & ShadowSmoothnessFieldMask)
00219 {
00220 if(getShadowSmoothness() < 0.0)
00221 {
00222 FNOTICE(("No ShadowSmoothness < 0 allowed!\n"));
00223 setShadowSmoothness(0.0);
00224 }
00225 if(getShadowSmoothness() > 1.0)
00226 {
00227 FNOTICE(("No ShadowSmoothness > 1.0 allowed!\n"));
00228 setShadowSmoothness(1.0);
00229 }
00230 FNOTICE(("ShadowSmoothness set to %f\n", getShadowSmoothness()));
00231 }
00232
00233 Inherited::changed(whichField, origin, details);
00234 }
00235
00236 void ShadowStage::dump( UInt32,
00237 const BitVector) const
00238 {
00239 SLOG << "Dump ShadowStage NI" << std::endl;
00240 }
00241
00242
00243 void ShadowStage::onCreate(const ShadowStage *source)
00244 {
00245 Inherited::onCreate(source);
00246
00247
00248 if(OSG::GlobalSystemState == OSG::Startup)
00249 return;
00250 }
00251
00252 void ShadowStage::onDestroy(UInt32 uiContainerId)
00253 {
00254 Inherited::onDestroy(uiContainerId);
00255 }
00256
00257 ActionBase::ResultE ShadowStage::renderEnter(Action *action)
00258 {
00259 ActionBase::ResultE returnValue = ActionBase::Continue;
00260
00261 RenderAction *ract = dynamic_cast<RenderAction *>(action);
00262
00263 if(ract->getWindow()->hasExtension(_extSHL ) == false ||
00264 ract->getWindow()->hasExtension(_extDepthTexture ) == false ||
00265 ract->getWindow()->hasExtension(_extShadows ) == false ||
00266 ract->getWindow()->hasExtension(_extFramebufferObject) == false ||
00267 ract->getWindow()->hasExtension(_extDrawBuffers ) == false )
00268 {
00269 return returnValue;
00270 }
00271
00272
00273
00274 ShadowStageData *pData = ract->getData<ShadowStageData *>(_iDataSlotId);
00275
00276
00277 if(pData == NULL)
00278 {
00279 ShadowStageDataUnrecPtr pTmp = ShadowStageData::createLocal();
00280
00281 pData = pTmp;
00282
00283 this->setData(pData, _iDataSlotId, ract);
00284 }
00285
00286
00287
00288 if(pData->getRunning() == true)
00289 return returnValue;
00290
00291
00292 pData->setRunning(true);
00293
00294
00295 ShadowTreeHandler *pTreeHandler = pData->getTreeHandler();
00296
00297 if(pTreeHandler == NULL ||
00298 this->getShadowMode() != pTreeHandler->getMode())
00299 {
00300 pTreeHandler = NULL;
00301
00302
00303
00304 switch(getShadowMode())
00305 {
00306 case NO_SHADOW:
00307 {
00308 FNOTICE(("No Shadows\n"));
00309 }
00310 break;
00311
00312 case STD_SHADOW_MAP:
00313 {
00314 FNOTICE(("using standard Shadow Mapping...\n"));
00315 #ifdef OSG_HAS_STDMAP
00316 pTreeHandler = new StdShadowMapHandler(this, pData);
00317 #endif
00318 }
00319 break;
00320
00321 case PERSPECTIVE_SHADOW_MAP:
00322 {
00323 FNOTICE(("using Lisp Perspective Shadow Mapping...\n"));
00324 #ifdef OSG_HAS_PERSPMAP
00325 pTreeHandler = new PerspectiveShadowMapHandler(this, pData);
00326 #endif
00327 }
00328 break;
00329
00330 case DITHER_SHADOW_MAP:
00331 {
00332 FNOTICE(("using Dither Shadow Mapping...\n"));
00333 #ifdef OSG_HAS_DITHERMAP
00334 pTreeHandler = new DitherShadowMapHandler(this, pData);
00335 #endif
00336 }
00337 break;
00338
00339 case PCF_SHADOW_MAP:
00340 {
00341 FNOTICE(("using PCF Shadow Mapping...\n"));
00342 #ifdef OSG_HAS_PCFMAP
00343 pTreeHandler = new PCFShadowMapHandler(this, pData);
00344 #endif
00345 }
00346 break;
00347
00348 case PCSS_SHADOW_MAP:
00349 {
00350 FNOTICE(("using PCSS Shadow Mapping...\n"));
00351 #ifdef OSG_HAS_PCSSMAP
00352 pTreeHandler = new PCSSShadowMapHandler(this, pData);
00353 #endif
00354 }
00355 break;
00356
00357 case VARIANCE_SHADOW_MAP:
00358 {
00359 FNOTICE(("using Variance Shadow Mapping...\n"));
00360 #ifdef OSG_HAS_VARMAP
00361 pTreeHandler = new VarianceShadowMapHandler(this, pData);
00362 #endif
00363 }
00364 break;
00365
00366 default:
00367 break;
00368 }
00369
00370 pData->setTreeHandler(pTreeHandler);
00371 }
00372
00373 if(pTreeHandler == NULL || getShadowOn() == false)
00374 {
00375 pData->setRunning(false);
00376
00377 return returnValue;
00378 }
00379
00380
00381 #if 0
00382 if(getSceneRoot() == NULL)
00383 {
00384 setSceneRoot(action->getActNode());
00385 }
00386 #endif
00387
00388 const ShadowStageData::LightStore &vLights =
00389 pData->getLights();
00390
00391 const ShadowStageData::LStateStore &vLightStates =
00392 pData->getLightStates();
00393
00394 ShadowStageData::StatusStore &vRealPLight =
00395 pData->getRealPointLight();
00396
00397 ShadowStageData::StatusStore &vExclActive =
00398 pData->getExcludeNodeActive();
00399
00400 ShadowStageData::NodeStore &vTransparents =
00401 pData->getTransparents();
00402
00403 vExclActive.clear();
00404 vRealPLight.clear();
00405
00406
00407 for(UInt32 i = 0;i < getMFExcludeNodes()->size();i++)
00408 {
00409 Node *exnode = getExcludeNodes(i);
00410
00411 if(exnode != NULL)
00412 {
00413 vExclActive.push_back(exnode->getTravMask() != 0);
00414 }
00415 else
00416 {
00417 vExclActive.push_back(false);
00418 }
00419 }
00420
00421 checkLights(ract, pData);
00422
00423 bool allLightsZero = true;
00424
00425 if(getGlobalShadowIntensity() != 0.0)
00426 {
00427 allLightsZero = false;
00428 }
00429 else
00430 {
00431 for(UInt32 i = 0;i < vLights.size();i++)
00432 {
00433 if(vLights [i].second->getShadowIntensity() != 0.0 &&
00434 vLightStates[i] != 0 )
00435 {
00436 allLightsZero = false;
00437 }
00438 }
00439 }
00440
00441 if(vLights.size() == 0 || allLightsZero)
00442 {
00443 pData->setRunning(false);
00444
00445 return returnValue;
00446 }
00447 else
00448 {
00449 ract->disableDefaultPartition();
00450
00451
00452 vTransparents.clear();
00453
00454 if(getAutoExcludeTransparentNodes())
00455 {
00456 traverse(action->getActNode(),
00457 boost::bind(&ShadowStage::findTransparent,
00458 this,
00459 pData,
00460 _1) );
00461 }
00462
00463
00464 for(UInt32 i = 0;i < getMFExcludeNodes()->size();++i)
00465 {
00466 Node *exnode = getExcludeNodes(i);
00467
00468 vExclActive[i] = exnode->getTravMask() != 0;
00469 }
00470
00471
00472
00473 #if 0
00474 _renderSide.clear();
00475 #endif
00476 ract->getActivePartition()->disable();
00477
00478 ract->beginPartitionGroup();
00479 {
00480 pTreeHandler->render(ract,
00481 &(ract->getActivePartition()->getDrawEnv()));
00482 }
00483 ract->endPartitionGroup();
00484
00485 returnValue = ActionBase::Skip;
00486 }
00487
00488 pData->setRunning(false);
00489
00490 return returnValue;
00491 }
00492
00493 ActionBase::ResultE ShadowStage::renderLeave(Action *action)
00494 {
00495 ActionBase::ResultE returnValue = ActionBase::Continue;
00496
00497
00498
00499 return returnValue;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 void ShadowStage::triggerMapUpdate(void)
00520 {
00521 editSField(MapAutoUpdateFieldMask);
00522 }
00523
00524
00525
00526
00527 Action::ResultE ShadowStage::findLight(ShadowStageData * pData,
00528 Node * const node)
00529 {
00530 if(node->getCore()->getType().isDerivedFrom(Light::getClassType()))
00531 {
00532 ShadowStageData::LightStore &vLights = pData->getLights();
00533
00534 vLights.push_back(
00535 std::make_pair(node,
00536 dynamic_cast<Light *>(node->getCore())));
00537 }
00538 else if(node->getCore()->getType().isDerivedFrom(MultiCore::getClassType()))
00539 {
00540 ShadowStageData::LightStore &vLights = pData->getLights();
00541
00542 MultiCore *pCore = dynamic_cast<MultiCore *>(node->getCore());
00543
00544 MultiCore::MFCoresType::const_iterator cIt =
00545 pCore->getMFCores()->begin();
00546
00547 MultiCore::MFCoresType::const_iterator cEnd =
00548 pCore->getMFCores()->end();
00549
00550 for(; cIt != cEnd; ++cIt)
00551 {
00552 if((*cIt)->getType().isDerivedFrom(Light::getClassType()))
00553 {
00554 vLights.push_back(
00555 std::make_pair(node,
00556 dynamic_cast<Light *>(*cIt)));
00557 }
00558 }
00559 }
00560
00561 return Action::Continue;
00562 }
00563
00564 Action::ResultE ShadowStage::findTransparent(ShadowStageData * pData,
00565 Node * const node)
00566 {
00567 if(node->getCore() != NULL)
00568 {
00569 ShadowStageData::NodeStore &vTransparents = pData->getTransparents();
00570
00571 if(node->getCore()->getType() == Geometry::getClassType() ||
00572 node->getCore()->getType() == MaterialGroup::getClassType())
00573 {
00574 Material *mat = NULL;
00575 MultiPassMaterial *multiMat = NULL;
00576 Geometry *geo = dynamic_cast<Geometry *>(
00577 node->getCore());
00578 MaterialGroup *matGroup =
00579 dynamic_cast<MaterialGroup *>(node->getCore());
00580
00581 if(geo != NULL)
00582 mat = geo->getMaterial();
00583 if(matGroup != NULL)
00584 mat = matGroup->getMaterial();
00585 if(mat != NULL)
00586 {
00587
00588
00589
00590
00591
00592 multiMat = dynamic_cast<MultiPassMaterial *>(mat);
00593
00594 if(multiMat != NULL)
00595 {
00596 MultiPassMaterial::MFMaterialsType::const_iterator it =
00597 multiMat->getMFMaterials()->begin();
00598
00599 MultiPassMaterial::MFMaterialsType::const_iterator matsEnd =
00600 multiMat->getMFMaterials()->end();
00601
00602 for(;it != matsEnd;++it)
00603 {
00604 if((*it) == NULL)
00605 continue;
00606
00607 if((*it)->isTransparent() && node->getTravMask() != 0)
00608 {
00609 vTransparents.push_back(node);
00610 break;
00611 }
00612 }
00613 }
00614 else
00615 {
00616 if(mat->isTransparent() && node->getTravMask() != 0)
00617 vTransparents.push_back(node);
00618 }
00619 }
00620
00621 }
00622
00623 if(node->getCore()->getType() == Geometry::getClassType())
00624 {
00625 Geometry *geo = dynamic_cast<Geometry *>(node->getCore());
00626
00627 if(geo->getMaterial() != NULL &&
00628 geo->getMaterial()->isTransparent() &&
00629 node->getTravMask() != 0)
00630 {
00631 vTransparents.push_back(node);
00632 }
00633 }
00634 else if(node->getCore()->getType() == MaterialGroup::getClassType())
00635 {
00636 MaterialGroup *matGroup = dynamic_cast<MaterialGroup *>(
00637 node->getCore());
00638
00639 if(matGroup->getMaterial() != NULL &&
00640 matGroup->getMaterial()->isTransparent() &&
00641 node->getTravMask() != 0)
00642 {
00643 vTransparents.push_back(node);
00644 }
00645 }
00646 }
00647 return Action::Continue;
00648 }
00649
00650
00651
00652 void ShadowStage::checkLights(RenderActionBase *action,
00653 ShadowStageData *pData )
00654 {
00655 ShadowStageData::LightStore &vLights = pData->getLights();
00656 const ShadowStageData::LightStore &vOldLights = pData->getOldLights();
00657 ShadowStageData::LStateStore &vLightStates = pData->getLightStates();
00658
00659 if(getAutoSearchForLights())
00660 {
00661
00662 vLights.clear();
00663
00664 traverse(action->getActNode(),
00665 boost::bind(&ShadowStage::findLight,
00666 this,
00667 pData,
00668 _1));
00669 }
00670 else
00671 {
00672 if(vLights.size() != _mfLightNodes.size())
00673 {
00674 vLights.resize(_mfLightNodes.size());
00675 }
00676
00677 MFLightNodesType ::const_iterator lIt =_mfLightNodes.begin();
00678 MFLightNodesType ::const_iterator lEnd=_mfLightNodes.end ();
00679 ShadowStageData::LightStore:: iterator lsIt= vLights .begin();
00680
00681 for(; lIt != lEnd; ++lIt, ++lsIt)
00682 {
00683 if((*lsIt).first != *lIt)
00684 {
00685 (*lsIt).first = *lIt;
00686 (*lsIt).second = dynamic_cast<Light *>((*lIt)->getCore());
00687 }
00688 }
00689 }
00690
00691 vLightStates.clear();
00692
00693 bool changed = false;
00694
00695 if(vLights.size() > 0 && vLights.size() == vOldLights.size())
00696 {
00697 for(UInt32 i = 0;i < vLights.size();++i)
00698 {
00699
00700 bool light_state = vLights[i].second->getOn();
00701
00702 if(vLights[i].second->getShadowMode() == Light::CAST_SHADOW_ON)
00703 {
00704 light_state = true;
00705 }
00706 else if(vLights[i].second->getShadowMode() ==
00707 Light::CAST_SHADOW_OFF)
00708 {
00709 light_state = false;
00710 }
00711
00712 vLightStates.push_back(light_state ? 1 : 0);
00713
00714 if(vLights[i] != vOldLights[i])
00715 changed = true;
00716 }
00717 }
00718 else
00719 {
00720 changed = true;
00721 }
00722
00723 if(!changed)
00724 {
00725 updateLights(action, pData);
00726 return;
00727 }
00728
00729 initializeLights(action, pData);
00730 }
00731
00732 void ShadowStage::updateLights(RenderActionBase *action,
00733 ShadowStageData *pData )
00734 {
00735 SpotLight *tmpSpot;
00736 DirectionalLight *tmpDir;
00737 PointLight *tmpPoint = NULL;
00738 Matrix tmpMatrix;
00739 bool isSpot, isDirect;
00740 Real32 sceneWidth = 0.0;
00741 Real32 sceneHeight = 0.0;
00742 Real32 PLangle = 0.0;
00743
00744 const ShadowStageData::LightStore &vLights =
00745 pData->getLights();
00746
00747 const ShadowStageData::TransStore &vLCamTrans =
00748 pData->getLightCamTrans();
00749
00750 const ShadowStageData::CamStore &vLCams =
00751 pData->getLightCameras();
00752
00753 const ShadowStageData::NodeStore &vLCamBeacons =
00754 pData->getLightCamBeacons();
00755
00756 ShadowStageData::StatusStore &vRealPLight =
00757 pData->getRealPointLight();
00758
00759 for(UInt32 i = 0;i < vLights.size();++i)
00760 {
00761 pData->getLightRoot(i)->updateVolume();
00762
00763 {
00764 Quaternion q;
00765
00766 tmpMatrix.setIdentity();
00767
00768
00769 if(vLights[i].second->getType() == SpotLight::getClassType())
00770 {
00771
00772 tmpSpot = dynamic_cast<SpotLight *>(vLights[i].second.get());
00773 FDEBUG(("Found Spotlight!\n"));
00774 isSpot = true;
00775 isDirect = false;
00776
00777 Pnt3f lightpos = tmpSpot->getPosition();
00778 Vec3f lightdir = tmpSpot->getDirection();
00779
00780 if(tmpSpot->getBeacon() != NULL)
00781 {
00782 Matrix m = tmpSpot->getBeacon()->getToWorld();
00783 m.mult(lightpos, lightpos);
00784 m.mult(lightdir, lightdir);
00785 }
00786
00787
00788 q.setValue(Vec3f(0, 0, -1), lightdir);
00789 tmpMatrix.setTransform(Vec3f(lightpos), q);
00790
00791 vRealPLight.push_back(false);
00792 }
00793 else if(vLights[i].second->getType() ==
00794 DirectionalLight::getClassType())
00795 {
00796 Vec3f diff;
00797 Pnt3f center;
00798
00799 tmpDir =
00800 dynamic_cast<DirectionalLight *>(vLights[i].second.get());
00801
00802 FDEBUG(("Found Directionallight!\n"));
00803 isSpot = false;
00804 isDirect = true;
00805
00806 diff = (pData->getLightRoot(i)->getVolume().getMax() -
00807 pData->getLightRoot(i)->getVolume().getMin());
00808
00809 sceneWidth = diff.length() * 0.5;
00810
00811 sceneHeight = diff.length() * 0.5;
00812
00813 pData->getLightRoot(i)->getVolume().getCenter(center);
00814
00815 Vec3f lightdir = tmpDir->getDirection();
00816
00817 if(tmpDir->getBeacon() != NULL)
00818 {
00819 Matrix m = tmpDir->getBeacon()->getToWorld();
00820 m.mult(lightdir, lightdir);
00821 }
00822
00823 MatrixLookAt(tmpMatrix, center + lightdir,
00824 center, Vec3f(0, 1, 0));
00825 tmpMatrix.invert();
00826 vRealPLight.push_back(false);
00827 }
00828 else
00829
00830 {
00831 Vec3f dir;
00832 Pnt3f center;
00833
00834 tmpPoint = dynamic_cast<PointLight *>(vLights[i].second.get());
00835 FDEBUG(("Found PointLight!\n"));
00836 isSpot = false;
00837 isDirect = false;
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 Pnt3f lightpos = tmpPoint->getPosition();
00849 if(tmpPoint->getBeacon() != NULL)
00850 {
00851 Matrix m = tmpPoint->getBeacon()->getToWorld();
00852 m.mult(lightpos, lightpos);
00853 }
00854
00855 if((getShadowMode() == STD_SHADOW_MAP ||
00856 getShadowMode() == PERSPECTIVE_SHADOW_MAP ||
00857 getShadowMode() == DITHER_SHADOW_MAP ||
00858 getShadowMode() == PCF_SHADOW_MAP))
00859 {
00860
00861 Pnt3f sceneMin =
00862 pData->getLightRoot(i)->getVolume().getMin();
00863
00864 Pnt3f sceneMax =
00865 pData->getLightRoot(i)->getVolume().getMax();
00866
00867 if((lightpos[0] < sceneMin[0] ||
00868 lightpos[1] < sceneMin[1] ||
00869 lightpos[2] < sceneMin[2]) ||
00870 (lightpos[0] > sceneMax[0] ||
00871 lightpos[1] > sceneMax[1] ||
00872 lightpos[2] > sceneMax[2]))
00873 {
00874
00875 Vec3f dist, diff;
00876 Pnt3f center;
00877
00878 pData->getLightRoot(i)->getVolume().getCenter(center);
00879
00880
00881
00882 Pnt3f bb[8];
00883 bb[0] = Pnt3f(sceneMin[0], sceneMin[1], sceneMin[2]);
00884 bb[1] = Pnt3f(sceneMax[0], sceneMin[1], sceneMin[2]);
00885 bb[2] = Pnt3f(sceneMax[0], sceneMax[1], sceneMin[2]);
00886 bb[3] = Pnt3f(sceneMin[0], sceneMax[1], sceneMin[2]);
00887 bb[4] = Pnt3f(sceneMin[0], sceneMin[1], sceneMax[2]);
00888 bb[5] = Pnt3f(sceneMax[0], sceneMin[1], sceneMax[2]);
00889 bb[6] = Pnt3f(sceneMax[0], sceneMax[1], sceneMax[2]);
00890 bb[7] = Pnt3f(sceneMin[0], sceneMax[1], sceneMax[2]);
00891
00892 PLangle = osgDegree2Rad(0);
00893 Pnt3f maxAnglePnt1, maxAnglePnt2;
00894
00895 for(UInt32 j = 0;j < 8;j++)
00896 {
00897 Vec3f vector1(lightpos - center);
00898 Vec3f vector2(lightpos - bb[j]);
00899 Real32 newAngle = vector1.enclosedAngle(vector2);
00900 if(osgAbs(osgRad2Degree(newAngle)) > 180)
00901 newAngle = vector2.enclosedAngle(vector1);
00902 if(osgRad2Degree(newAngle) > osgRad2Degree(PLangle))
00903 {
00904 PLangle = newAngle;
00905 maxAnglePnt1 = bb[j];
00906 }
00907 }
00908
00909 for(UInt32 j = 0;j < 8;j++)
00910 {
00911 Vec3f vector1(lightpos - maxAnglePnt1);
00912 Vec3f vector2(lightpos - bb[j]);
00913 Real32 newAngle = vector1.enclosedAngle(vector2);
00914 if(osgAbs(osgRad2Degree(newAngle)) > 180)
00915 newAngle = vector2.enclosedAngle(vector1);
00916 if(osgRad2Degree(newAngle) > osgRad2Degree(PLangle))
00917 {
00918 PLangle = newAngle;
00919 maxAnglePnt2 = bb[j];
00920 }
00921 }
00922
00923 if(osgRad2Degree(PLangle) < 120)
00924 {
00925 pData->getLightRoot(i)->getVolume().getCenter(
00926 center);
00927 dir = lightpos - center;
00928 dir.normalize();
00929 dir.negate();
00930 q.setValue(Vec3f(0, 0, -1), dir);
00931 tmpMatrix.setTransform(Vec3f(lightpos), q);
00932
00933 vRealPLight.push_back(false);
00934 }
00935 else
00936
00937 {
00938 dir = Vec3f(0.0, 0.0, -1.0);
00939 dir.negate();
00940 q.setValue(Vec3f(0, 0, -1), dir);
00941 tmpMatrix.setTransform(Vec3f(lightpos), q);
00942 vRealPLight.push_back(true);
00943 }
00944 }
00945 else
00946 {
00947 dir = Vec3f(0.0, 0.0, -1.0);
00948 dir.negate();
00949 q.setValue(Vec3f(0, 0, -1), dir);
00950 tmpMatrix.setTransform(Vec3f(lightpos), q);
00951 vRealPLight.push_back(true);
00952 }
00953 }
00954 else
00955 {
00956
00957 Vec3f dist, diff;
00958 Pnt3f center;
00959 Pnt3f sceneMin =
00960 pData->getLightRoot(i)->getVolume().getMin();
00961
00962 Pnt3f sceneMax =
00963 pData->getLightRoot(i)->getVolume().getMax();
00964
00965 pData->getLightRoot(i)->getVolume().getCenter(center);
00966
00967 Pnt3f bb[8];
00968 bb[0] = Pnt3f(sceneMin[0], sceneMin[1], sceneMin[2]);
00969 bb[1] = Pnt3f(sceneMax[0], sceneMin[1], sceneMin[2]);
00970 bb[2] = Pnt3f(sceneMax[0], sceneMax[1], sceneMin[2]);
00971 bb[3] = Pnt3f(sceneMin[0], sceneMax[1], sceneMin[2]);
00972 bb[4] = Pnt3f(sceneMin[0], sceneMin[1], sceneMax[2]);
00973 bb[5] = Pnt3f(sceneMax[0], sceneMin[1], sceneMax[2]);
00974 bb[6] = Pnt3f(sceneMax[0], sceneMax[1], sceneMax[2]);
00975 bb[7] = Pnt3f(sceneMin[0], sceneMax[1], sceneMax[2]);
00976
00977 PLangle = osgDegree2Rad(0);
00978 Pnt3f maxAnglePnt1, maxAnglePnt2;
00979
00980 for(UInt32 j = 0;j < 8;j++)
00981 {
00982 Vec3f vector1(lightpos - center);
00983 Vec3f vector2(lightpos - bb[j]);
00984 Real32 newAngle = vector1.enclosedAngle(vector2);
00985 if(osgAbs(osgRad2Degree(newAngle)) > 180)
00986 newAngle = vector2.enclosedAngle(vector1);
00987 if(osgRad2Degree(newAngle) > osgRad2Degree(PLangle))
00988 {
00989 PLangle = newAngle;
00990 maxAnglePnt1 = bb[j];
00991 }
00992 }
00993
00994 for(UInt32 j = 0;j < 8;j++)
00995 {
00996 Vec3f vector1(lightpos - maxAnglePnt1);
00997 Vec3f vector2(lightpos - bb[j]);
00998 Real32 newAngle = vector1.enclosedAngle(vector2);
00999 if(osgAbs(osgRad2Degree(newAngle)) > 180)
01000 newAngle = vector2.enclosedAngle(vector1);
01001 if(osgRad2Degree(newAngle) > osgRad2Degree(PLangle))
01002 {
01003 PLangle = newAngle;
01004 maxAnglePnt2 = bb[j];
01005 }
01006 }
01007
01008 if(osgRad2Degree(PLangle) > 175)
01009 {
01010 PLangle = osgDegree2Rad(175);
01011 }
01012
01013 dir = lightpos - center;
01014 dir.normalize();
01015 dir.negate();
01016
01017 q.setValue(Vec3f(0, 0, -1), dir);
01018
01019 tmpMatrix.setTransform(Vec3f(lightpos), q);
01020 vRealPLight.push_back(false);
01021 }
01022 }
01023
01024 vLCamTrans[i]->setMatrix(tmpMatrix);
01025 }
01026
01027
01028 {
01029
01030 if(isSpot)
01031 {
01032 tmpSpot = dynamic_cast<SpotLight *>(vLights[i].second.get());
01033
01034 Pnt3f lightpos = tmpSpot->getPosition();
01035
01036 if(tmpSpot->getBeacon() != NULL)
01037 {
01038 Matrix m = tmpSpot->getBeacon()->getToWorld();
01039 m.mult(lightpos, lightpos);
01040 }
01041
01042 Pnt3f center;
01043 pData->getLightRoot(i)->getVolume().getCenter(center);
01044
01045 Vec3f dir = lightpos - center;
01046 Real64 dirLength = dir.length();
01047
01048 Vec3f diff = (pData->getLightRoot(i)->getVolume().getMax() -
01049 pData->getLightRoot(i)->getVolume().getMin());
01050 Real64 diffLength = diff.length() / 2;
01051
01052 Real64 zNearLimit, zCalcNear = 0;
01053 Real64 zFar = 1.2 * (dirLength + diffLength);
01054 Real64 zNear = action->getCamera()->getNear();
01055
01056 if (diffLength)
01057 {
01058
01059 if (dirLength > diffLength)
01060
01061 zCalcNear = 0.8 * (dirLength - diffLength);
01062
01063
01064 zNear = zCalcNear;
01065 zNearLimit = osgMax( 0.01, zFar / 20000 );
01066 zNear = osgMax( zNear, zNearLimit );
01067 }
01068
01069 vLCams[i]->setNear( zNear );
01070 vLCams[i]->setFar( zFar );
01071
01072
01073 dynamic_cast<PerspectiveCamera *>(vLCams[i].get())->
01074 setFov(tmpSpot->getSpotCutOffDeg() * 2);
01075 }
01076
01077
01078 else if(isDirect)
01079 {
01080 Matrix proMatrix, modMatrix;
01081
01082 proMatrix.setIdentity();
01083 modMatrix.setIdentity();
01084
01085 MatrixOrthogonal(proMatrix, -sceneWidth,
01086 sceneWidth, -sceneHeight,
01087 sceneHeight, -sceneWidth, sceneWidth);
01088
01089
01090 modMatrix = vLCamTrans[i]->getMatrix();
01091
01092 dynamic_cast<MatrixCamera *>(
01093 vLCams[i].get())->setProjectionMatrix(proMatrix);
01094 dynamic_cast<MatrixCamera *>(
01095 vLCams[i].get())->setModelviewMatrix(modMatrix);
01096 }
01097 else
01098
01099 {
01100 if((getShadowMode() == STD_SHADOW_MAP ||
01101 getShadowMode() == PERSPECTIVE_SHADOW_MAP ||
01102 getShadowMode() == DITHER_SHADOW_MAP ||
01103 getShadowMode() == PCF_SHADOW_MAP) && vRealPLight[i] )
01104 {
01105 Vec3f dist, diff;
01106 Pnt3f center;
01107
01108 pData->getLightRoot(i)->getVolume().getCenter(center);
01109
01110 Pnt3f lightpos = tmpPoint->getPosition();
01111
01112 if(tmpPoint->getBeacon() != NULL)
01113 {
01114 Matrix m = tmpPoint->getBeacon()->getToWorld();
01115 m.mult(lightpos, lightpos);
01116 }
01117
01118 dist = (lightpos - center);
01119 diff = (pData->getLightRoot(i)->getVolume().getMax() -
01120 pData->getLightRoot(i)->getVolume().getMin());
01121
01122 Real32 distLength = dist.length();
01123 Real32 diffLength = diff.length();
01124
01125 vLCams[i]->setNear(0.01f);
01126 vLCams[i]->setFar(distLength + diffLength);
01127
01128 dynamic_cast<PerspectiveCamera *>(
01129 vLCams[i].get())->setFov(osgDegree2Rad(91));
01130 }
01131 else
01132 {
01133 Vec3f dist, diff;
01134 Pnt3f center;
01135 pData->getLightRoot(i)->getVolume().getCenter(center);
01136
01137 Pnt3f lightpos = tmpPoint->getPosition();
01138
01139 if(tmpPoint->getBeacon() != NULL)
01140 {
01141 Matrix m = tmpPoint->getBeacon()->getToWorld();
01142 m.mult(lightpos, lightpos);
01143 }
01144
01145 dist = (lightpos - center);
01146 diff = (pData->getLightRoot(i)->getVolume().getMax() -
01147 pData->getLightRoot(i)->getVolume().getMin());
01148
01149 Pnt3f sceneMin =
01150 pData->getLightRoot(i)->getVolume().getMin();
01151 Pnt3f sceneMax =
01152 pData->getLightRoot(i)->getVolume().getMax();
01153
01154 Real64 distLength = dist.length();
01155 Real64 diffLength = diff.length() / 2;
01156
01157 Real64 zNearLimit, zCalcNear = 0;
01158 Real64 zFar = 1.2 * (distLength + diffLength);
01159 Real64 zNear = action->getCamera()->getNear();
01160 if (diffLength)
01161 {
01162
01163 if (distLength > diffLength)
01164
01165 zCalcNear = 0.8 * (distLength - diffLength);
01166
01167
01168 zNear = zCalcNear;
01169 zNearLimit = osgMax( 0.01, zFar / 20000 );
01170 zNear = osgMax( zNear, zNearLimit );
01171 }
01172
01173 vLCams[i]->setNear( zNear );
01174 vLCams[i]->setFar( zFar );
01175
01176 dynamic_cast<PerspectiveCamera *>(
01177 vLCams[i].get())->setFov(PLangle);
01178 }
01179 }
01180
01181 vLCams[i]->setBeacon(vLCamBeacons[i]);
01182 }
01183 }
01184 }
01185
01186 void ShadowStage::initializeLights(RenderActionBase *action,
01187 ShadowStageData *pData )
01188 {
01189 const ShadowStageData::LightStore &vLights =
01190 pData->getLights();
01191
01192 ShadowStageData::LightStore &vOldLights =
01193 pData->getOldLights();
01194
01195 ShadowStageData::LStateStore &vLightStates =
01196 pData->getLightStates();
01197
01198 ShadowStageData::TransStore &vLCamTrans =
01199 pData->getLightCamTrans();
01200
01201 ShadowStageData::NodeStore &vLCamBeacons =
01202 pData->getLightCamBeacons();
01203
01204 ShadowStageData::CamStore &vLCams =
01205 pData->getLightCameras();
01206
01207 pData->clearLightData();
01208
01209 FDEBUG(("Initialising lights.\n"));
01210
01211 vOldLights = vLights;
01212
01213
01214 for(UInt32 i = 0;i < vLights.size();++i)
01215 {
01216 bool light_state = vLights[i].second->getOn();
01217
01218 if(vLights[i].second->getShadowMode() == Light::CAST_SHADOW_ON)
01219 {
01220 light_state = true;
01221 }
01222 else if(vLights[i].second->getShadowMode() == Light::CAST_SHADOW_OFF)
01223 {
01224 light_state = false;
01225 }
01226
01227
01228 vLightStates.push_back(light_state ? 1 : 0);
01229
01230 vLCamTrans.push_back(NULL);
01231
01232 vLCamBeacons.push_back(makeCoredNode<Transform>(&vLCamTrans[i]));
01233
01234
01235 {
01236
01237 if(vLights[i].second->getType() == SpotLight::getClassType())
01238 {
01239
01240 vLCams.push_back(PerspectiveCamera::create());
01241 }
01242 else if(vLights[i].second->getType() ==
01243 DirectionalLight::getClassType())
01244 {
01245 vLCams.push_back(MatrixCamera::create());
01246 }
01247 else
01248
01249 {
01250 vLCams.push_back(PerspectiveCamera::create());
01251 }
01252 }
01253
01254 #ifdef MAPS_IN_STAGE
01255 if(getSceneRoot() == NULL)
01256 {
01257 SFATAL << "RootNode not found!" << endLog;
01258 }
01259 else
01260 {
01261
01262 }
01263
01264
01265 if(_lights[i].second->getType() != PointLight::getClassType())
01266 {
01267 _shadowImages.push_back(Image::create());
01268
01269
01270 _shadowImages[i]->set(Image::OSG_L_PF,
01271 getMapSize(), getMapSize(), 1,
01272 1, 1, 0,
01273 NULL,
01274 Image::OSG_UINT8_IMAGEDATA,
01275 false);
01276
01277 ShadowMapStore tmpStore;
01278
01279 tmpStore.pTexO = TextureObjChunk::create();
01280 tmpStore.pTexE = TextureEnvChunk::create();
01281 tmpStore.pFBO = FrameBufferObject::create();
01282
01283 _vTexChunks.push_back(tmpStore);
01284
01285 TextureBufferUnrecPtr pDepthTex = TextureBuffer::create();
01286
01287 pDepthTex->setTexture(tmpStore.pTexO);
01288
01289 tmpStore.pFBO->setDepthAttachment(pDepthTex);
01290
01291
01292 {
01293 _vTexChunks[i].pTexO->setImage(_shadowImages[i]);
01294 _vTexChunks[i].pTexO->setInternalFormat(GL_DEPTH_COMPONENT_ARB);
01295 _vTexChunks[i].pTexO->setExternalFormat(GL_DEPTH_COMPONENT_ARB);
01296 _vTexChunks[i].pTexO->setMinFilter(GL_LINEAR);
01297 _vTexChunks[i].pTexO->setMagFilter(GL_LINEAR);
01298 _vTexChunks[i].pTexO->setWrapS(GL_CLAMP_TO_EDGE);
01299 _vTexChunks[i].pTexO->setWrapT(GL_CLAMP_TO_EDGE);
01300 _vTexChunks[i].pTexE->setEnvMode(GL_MODULATE);
01301 _vTexChunks[i].pTexO->setTarget(GL_TEXTURE_2D);
01302 }
01303 }
01304 else
01305
01306 {
01307
01308 GLint max_texture_size;
01309 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
01310
01311 _shadowImages.push_back(Image::create());
01312
01313
01314 if((getShadowMode() == STD_SHADOW_MAP ||
01315 getShadowMode() == PERSPECTIVE_SHADOW_MAP ||
01316 getShadowMode() == DITHER_SHADOW_MAP ||
01317 getShadowMode() == PCF_SHADOW_MAP))
01318 {
01319 _shadowImages[i]->set(Image::OSG_L_PF, getMapSize(),
01320 getMapSize(),
01321 1, 1, 1, 0, NULL,
01322 Image::OSG_UINT8_IMAGEDATA, false);
01323 }
01324 else
01325 {
01326 _shadowImages[i]->set(Image::OSG_L_PF, getMapSize(),
01327 getMapSize(),
01328 1, 1, 1, 0, NULL,
01329 Image::OSG_UINT8_IMAGEDATA, false);
01330 }
01331
01332 ShadowMapStore tmpStore;
01333
01334 tmpStore.pTexO = TextureObjChunk::create();
01335 tmpStore.pTexE = TextureEnvChunk::create();
01336 tmpStore.pFBO = FrameBufferObject::create();
01337
01338 _vTexChunks.push_back(tmpStore);
01339
01340 TextureBufferUnrecPtr pDepthTex = TextureBuffer::create();
01341
01342 pDepthTex->setTexture(tmpStore.pTexO);
01343
01344 tmpStore.pFBO->setDepthAttachment(pDepthTex);
01345
01346
01347 {
01348 _vTexChunks[i].pTexO->setImage(_shadowImages[i]);
01349 _vTexChunks[i].pTexO->setInternalFormat(GL_DEPTH_COMPONENT_ARB);
01350 _vTexChunks[i].pTexO->setExternalFormat(GL_DEPTH_COMPONENT_ARB);
01351 _vTexChunks[i].pTexO->setMinFilter(GL_LINEAR);
01352 _vTexChunks[i].pTexO->setMagFilter(GL_LINEAR);
01353 _vTexChunks[i].pTexO->setWrapS(GL_CLAMP_TO_BORDER);
01354 _vTexChunks[i].pTexO->setWrapT(GL_CLAMP_TO_BORDER);
01355 _vTexChunks[i].pTexE->setEnvMode(GL_MODULATE);
01356 _vTexChunks[i].pTexO->setTarget(GL_TEXTURE_2D);
01357 }
01358
01359 }
01360 #endif
01361 }
01362
01363 updateLights(action, pData);
01364 }
01365
01366
01367
01368 void ShadowStage::checkLightsOcclusion(RenderActionBase *action)
01369 {
01370 #if 0
01371 if ( !getDisableOccludedLights() )
01372 {
01373 return;
01374 }
01375
01376 RenderAction *ract = dynamic_cast<RenderAction *>(action);
01377
01378 if (ract == NULL)
01379 return;
01380
01381 for(UInt32 i = 0;i < _lights.size();i++)
01382 {
01383 Node *node = _lights[i].first;
01384
01385
01386 bool occluded = false;
01387
01388 if(glGenQueriesARB != NULL)
01389 {
01390 Matrix view;
01391 if(ract->getCamera() != NULL)
01392 {
01393 ract->getCamera()->getViewing(
01394 view,
01395 ract->getViewport()->getPixelWidth (),
01396 ract->getViewport()->getPixelHeight());
01397 }
01398
01399 BoxVolume vol = node->getVolume();
01400
01401 Matrix m = view;
01402 if(node->getParent() != NULL)
01403 m.mult(node->getParent()->getToWorld());
01404 vol.transform(m);
01405
01406
01407 if(vol.getMax()[2] < 0.0f)
01408 {
01409 glDepthMask(GL_FALSE);
01410 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
01411
01412 if(this->_occlusionQuery == 0)
01413 glGenQueriesARB(1, &this->_occlusionQuery);
01414
01415 const BoxVolume & vol = node->getVolume();
01416
01417 Pnt3f min,max;
01418 vol.getBounds(min, max);
01419
01420 glBeginQueryARB(GL_SAMPLES_PASSED_ARB,
01421 this->_occlusionQuery);
01422 this->drawOcclusionBB(min, max);
01423 glEndQueryARB(GL_SAMPLES_PASSED_ARB);
01424
01425 glDepthMask(GL_TRUE);
01426 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
01427
01428 GLuint pixels = 0;
01429 glGetQueryObjectuivARB(this->_occlusionQuery,
01430 GL_QUERY_RESULT_ARB, &pixels);
01431
01432 occluded = (pixels == 0);
01433 }
01434 }
01435
01436 if(occluded)
01437 {
01438 _lightStates[i] = 0;
01439 }
01440 else
01441 {
01442 bool light_state = _lights[i].second->getOn();
01443 if(_lights[i].second->getShadowMode() == Light::CAST_SHADOW_ON)
01444 light_state = true;
01445 else if(_lights[i].second->getShadowMode() == Light::CAST_SHADOW_OFF)
01446 light_state = false;
01447
01448 _lightStates[i] = (light_state ? 1 : 0);
01449 }
01450 }
01451
01452
01453 #endif
01454 }
01455
01456
01457 void ShadowStage::drawOcclusionBB(const Pnt3f &bbmin, const Pnt3f &bbmax)
01458 {
01459 #if 1
01460
01461 #if 0
01462 glBegin(GL_TRIANGLE_STRIP);
01463 glVertex3f( bbmin[0], bbmin[1], bbmax[2]);
01464 glVertex3f( bbmax[0], bbmin[1], bbmax[2]);
01465 glVertex3f( bbmin[0], bbmax[1], bbmax[2]);
01466 glVertex3f( bbmax[0], bbmax[1], bbmax[2]);
01467 glVertex3f( bbmin[0], bbmax[1], bbmin[2]);
01468 glVertex3f( bbmax[0], bbmax[1], bbmin[2]);
01469 glVertex3f( bbmin[0], bbmin[1], bbmin[2]);
01470 glVertex3f( bbmax[0], bbmin[1], bbmin[2]);
01471 glEnd();
01472
01473 glBegin(GL_TRIANGLE_STRIP);
01474 glVertex3f( bbmax[0], bbmax[1], bbmin[2]);
01475 glVertex3f( bbmax[0], bbmax[1], bbmax[2]);
01476 glVertex3f( bbmax[0], bbmin[1], bbmin[2]);
01477 glVertex3f( bbmax[0], bbmin[1], bbmax[2]);
01478 glVertex3f( bbmin[0], bbmin[1], bbmin[2]);
01479 glVertex3f( bbmin[0], bbmin[1], bbmax[2]);
01480 glVertex3f( bbmin[0], bbmax[1], bbmin[2]);
01481 glVertex3f( bbmin[0], bbmax[1], bbmax[2]);
01482 glEnd();
01483
01484 #else
01485
01486
01487
01488 const GLubyte indices[16] = { 0,1,2,3,4,5,6,7, 5,3,7,1,6,0,4,2 };
01489 Real32 vertices[24];
01490 vertices[0] = bbmin[0]; vertices[1] = bbmin[1]; vertices[2] = bbmax[2];
01491 vertices[3] = bbmax[0]; vertices[4] = bbmin[1]; vertices[5] = bbmax[2];
01492 vertices[6] = bbmin[0]; vertices[7] = bbmax[1]; vertices[8] = bbmax[2];
01493 vertices[9] = bbmax[0]; vertices[10] = bbmax[1]; vertices[11] = bbmax[2];
01494 vertices[12] = bbmin[0]; vertices[13] = bbmax[1]; vertices[14] = bbmin[2];
01495 vertices[15] = bbmax[0]; vertices[16] = bbmax[1]; vertices[17] = bbmin[2];
01496 vertices[18] = bbmin[0]; vertices[19] = bbmin[1]; vertices[20] = bbmin[2];
01497 vertices[21] = bbmax[0]; vertices[22] = bbmin[1]; vertices[23] = bbmin[2];
01498
01499 glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
01500 glEnableClientState(GL_VERTEX_ARRAY);
01501 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[0]);
01502 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[8]);
01503 glDisableClientState(GL_VERTEX_ARRAY);
01504
01505 #endif
01506
01507 #else
01508
01509 if(_occ_bb_dl == 0)
01510 {
01511
01512
01513
01514 Pnt3f min(-0.5f, -0.5f, -0.5f);
01515 Pnt3f max(0.5f, 0.5f, 0.5f);
01516 _occ_bb_dl = glGenLists(1);
01517
01518 const GLubyte indices[16] = { 0,1,2,3,4,5,6,7, 5,3,7,1,6,0,4,2 };
01519 Real32 vertices[24];
01520 vertices[0] = min[0]; vertices[1] = min[1]; vertices[2] = max[2];
01521 vertices[3] = max[0]; vertices[4] = min[1]; vertices[5] = max[2];
01522 vertices[6] = min[0]; vertices[7] = max[1]; vertices[8] = max[2];
01523 vertices[9] = max[0]; vertices[10] = max[1]; vertices[11] = max[2];
01524 vertices[12] = min[0]; vertices[13] = max[1]; vertices[14] = min[2];
01525 vertices[15] = max[0]; vertices[16] = max[1]; vertices[17] = min[2];
01526 vertices[18] = min[0]; vertices[19] = min[1]; vertices[20] = min[2];
01527 vertices[21] = max[0]; vertices[22] = min[1]; vertices[23] = min[2];
01528
01529 glNewList(_occ_bb_dl, GL_COMPILE);
01530 glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
01531 glEnableClientState(GL_VERTEX_ARRAY);
01532 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[0]);
01533 glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_BYTE, &indices[8]);
01534 glDisableClientState(GL_VERTEX_ARRAY);
01535 glEndList();
01536 }
01537
01538 Vec3f s = bbmax - bbmin;
01539 Vec3f t = bbmin + bbmax;
01540 t *= 0.5f;
01541 glPushMatrix();
01542 glTranslatef(t[0], t[1], t[2]);
01543 glScalef(s[0], s[1], s[2]);
01544 glCallList(_occ_bb_dl);
01545 glPopMatrix();
01546
01547 #endif
01548 }