OSGShadowStage.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *               Copyright (C) 2000-2002 by the OpenSG Forum                 *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------* \
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038
00039 //---------------------------------------------------------------------------
00040 //  Includes
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 *                            Description                                  *
00098 \***************************************************************************/
00099
00100 /***************************************************************************\
00101 *                           Class variables                               *
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 *                           Class methods                                 *
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 *                           Instance methods                              *
00155 \***************************************************************************/
00156
00157 /*-------------------------------------------------------------------------*\
00158    -  private                                                                 -
00159    \*-------------------------------------------------------------------------*/
00160
00161 /*----------------------- constructors & destructors ----------------------*/
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 /*----------------------------- class specific ----------------------------*/
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     // if we're in startup this is the prototype ...
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 //    fprintf(stderr, "ShadowStage::renderEnter\n");
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 //        clearLights(_oldLights.size());
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     //get excludeNode states
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         //find transparent nodes
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         //check if excludeNodes are disabled
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         //check if all sides of a pointlight are needed
00472         //TODO: Not implemented yet ...
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 //    fprintf(stderr, "ShadowStage::renderLeave\n");
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                 /* isTransparent in MultiPassMaterial returns false,
00588                    if one Material is not transparent. Here we need
00589                    to know if one Material is transparent so we can't
00590                    use isTransparent for MultiPassMaterials. */
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         //Finding lights by going through whole Scenegraph
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         //Giving new Camera Rotation and Position of the light it belongs to
00763         {
00764             Quaternion  q;
00765
00766             tmpMatrix.setIdentity();
00767
00768             //Is the Lightsource a Spotlight?
00769             if(vLights[i].second->getType() == SpotLight::getClassType())
00770             {
00771                 //Casting to Spotlight
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                 // Not final values. May get tweaked in the future
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                 // Preparation for PointLight -- In this version just a hack
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                 /* Direction of LightCam is a hack. 
00840                    It always looks at the center of the scene.
00841                    If the light is placed INSIDE of your Scene
00842                    (surrounded by Geometry, like a bulb in a Room)
00843                    the result of the Shadows may be not what you wanted.
00844                    So, please use the PointLight only outside of your 
00845                    Scene/outside the Bounding-Box of the lit geometry
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                     //Lightpos inside Scene BB?
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                         //check if angle is ok to use one Side
00875                         Vec3f   dist, diff;
00876                         Pnt3f   center;
00877
00878                         pData->getLightRoot(i)->getVolume().getCenter(center);
00879
00880                         //Scene Bounding Box Points
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) //Use one Side only
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                             //use 6 side Pointlight
00937                         {
00938                             dir = Vec3f(0.0, 0.0, -1.0);//lightpos - center;
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);//lightpos - center;
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) //Use one Side only
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         //Feeding new Camera with paramters of original camera
01028         {
01029             // Is the Lightsource a Spotlight?
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                     // Camera outside of the scene
01059                     if (dirLength > diffLength)
01060                         // Camera outside of the scene
01061                         zCalcNear = 0.8 * (dirLength - diffLength);
01062                     // else camera inside of the scene
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                 //Using Spot-angle of Spotlight as FOV for LightCamera
01073                 dynamic_cast<PerspectiveCamera *>(vLCams[i].get())->
01074                     setFov(tmpSpot->getSpotCutOffDeg() * 2);
01075             }
01076             // Is the Lightsource a Directional-Light? 
01077             // Setting up MatrixCamera
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                 // Grabbing ModelView-Matrix from Light-Transformation
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                 // If none of above the Lightsource must be a PointLight
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                         // Camera outside of the scene
01163                         if (distLength > diffLength)
01164                             // Camera outside of the scene
01165                             zCalcNear = 0.8 * (distLength - diffLength);
01166                         // else camera inside of the scene
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     //Setting up Light-Cameras, ShadowMaps and TextureChunks
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         // Remembering initial state of Lights
01228         vLightStates.push_back(light_state ? 1 : 0);
01229         //Fill Transformation-List, so it can be used later on
01230         vLCamTrans.push_back(NULL);
01231         //Creation of Lightcam-Beacon
01232         vLCamBeacons.push_back(makeCoredNode<Transform>(&vLCamTrans[i]));
01233
01234         //Giving new Camera Rotation and Position of the light it belongs to
01235         {
01236             //Is the Lightsource a Spotlight?
01237             if(vLights[i].second->getType() == SpotLight::getClassType())
01238             {
01239                 //Creation of new Perspective-LightCam
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                 // Preparation for PointLight -- In this version just a hack
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 //            getSceneRoot()->addChild(_lightCamBeacons[i]);
01262         }
01263
01264         //----------Shadowtexture-Images and Texture-Chunks-----------
01265         if(_lights[i].second->getType() != PointLight::getClassType())
01266         {
01267             _shadowImages.push_back(Image::create());
01268
01269             // creates a image without allocating main memory.
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             // Preparation of Texture be a Depth-Texture
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             //Light is a point light
01306         {
01307             //TODO: Texturgr�se anpassen, je nach Bedarf
01308             GLint   max_texture_size;
01309             glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
01310
01311             _shadowImages.push_back(Image::create());
01312
01313             // creates a image without allocating main memory.
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             // Preparation of Texture be a Depth-Texture
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         // now make a occlusion test for all light sources.
01386         bool occluded = false;
01387
01388         if(glGenQueriesARB != NULL) // occlusion queries supported?
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             // ignore objects behind the camera.
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     //updateLights();
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]); // 0
01464     glVertex3f( bbmax[0], bbmin[1], bbmax[2]); // 1
01465     glVertex3f( bbmin[0], bbmax[1], bbmax[2]); // 2
01466     glVertex3f( bbmax[0], bbmax[1], bbmax[2]); // 3
01467     glVertex3f( bbmin[0], bbmax[1], bbmin[2]); // 4
01468     glVertex3f( bbmax[0], bbmax[1], bbmin[2]); // 5
01469     glVertex3f( bbmin[0], bbmin[1], bbmin[2]); // 6
01470     glVertex3f( bbmax[0], bbmin[1], bbmin[2]); // 7
01471     glEnd();
01472
01473     glBegin(GL_TRIANGLE_STRIP);
01474     glVertex3f( bbmax[0], bbmax[1], bbmin[2]); // 5
01475     glVertex3f( bbmax[0], bbmax[1], bbmax[2]); // 3
01476     glVertex3f( bbmax[0], bbmin[1], bbmin[2]); // 7
01477     glVertex3f( bbmax[0], bbmin[1], bbmax[2]); // 1
01478     glVertex3f( bbmin[0], bbmin[1], bbmin[2]); // 6
01479     glVertex3f( bbmin[0], bbmin[1], bbmax[2]); // 0
01480     glVertex3f( bbmin[0], bbmax[1], bbmin[2]); // 4
01481     glVertex3f( bbmin[0], bbmax[1], bbmax[2]); // 2
01482     glEnd();
01483
01484 #else
01485 
01486     // not sure if this is faster but it reduces the amount of
01487     // gl commands.
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         // we create a display list for rendering the occlusion
01512         // bounding box.
01513         // is this faster ??? need to check it amz.
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 }