00001
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 #include "ShadowManager.h"
00033 #include "SoShadowCaster.h"
00034 #include "SoShadowVolume.h"
00035
00036
00037 #ifdef _WIN32
00038 #include <windows.h>
00039 #endif
00040
00041
00042 #include <GL/gl.h>
00043
00044
00045
00046
00047
00048 float CShadowManager::envIntensity = 0.0f;
00049
00068 CShadowManager::CShadowManager(SoSeparator *sr, SoEnvironment * env)
00069 : sceneRoot(sr),
00070 environment(env)
00071 {
00072
00073 if ( this->sceneRoot == NULL )
00074 {
00075 this->printError("Your scene root node is NULL.");
00076 }
00077 else
00078 {
00079 fprintf(stdout,"\nShadows generated by Shadow Engine v %s\n",SE_VERSION);
00080 sceneRoot->ref();
00081
00082 }
00083
00084 first = TRUE;
00085
00086 objectIndex = 0;
00087 lightIndex = 0;
00088
00089
00090 settings = new struct TShadowSettings;
00091 settings->method = zpass;
00092 settings->dropShadows = TRUE;
00093 settings->fDepth = 150.f;
00094 this->method2algorithm();
00095 ONDEBUG( this->printSettings() );
00096
00097
00098 shadowCastersRoot = new SoSeparator;
00099 shadowCastersRoot->setName("ShadowCastersRoot");
00100 shadowCastersRoot->ref();
00101
00102
00103 shadowSceneRoot = new SoSeparator;
00104 shadowSceneRoot->setName("ShadowSceneRoot");
00105 shadowSceneRoot->ref();
00106
00107
00108 shadowLightsRoot = new SoSeparator;
00109 shadowLightsRoot->setName("shadowLightsRoot");
00110 shadowLightsRoot->ref();
00111
00112 switchNode = new SoSwitch;
00113 sceneNoShadows = new SoSeparator;
00114 sceneWithShadows = new SoSeparator;
00115 sceneWithShadowVolumes = new SoSeparator;
00116
00117
00118 switchNode->addChild(sceneWithShadows);
00119 switchNode->addChild(sceneNoShadows);
00120 switchNode->addChild(sceneWithShadowVolumes);
00121
00122
00123 if ( environment == NULL )
00124 {
00125 ONDEBUG( printf("look for env node\n") );
00126
00127 environment = this->findEnvironmentNode();
00128 if ( environment == NULL )
00129 {
00130 ONDEBUG( printf("my own env\n") );
00131 environment = new SoEnvironment;
00132
00133 environment->ambientColor.setValue(SbColor(1.f, 1.f, 1.f));
00134
00135 environment->ambientIntensity.setValue(0.2f);
00136 this->shadowSceneRoot->addChild(environment);
00137 }
00138 }
00139 environment->ref();
00140
00141 shadowSceneRoot->addChild(switchNode);
00142 this->setSceneType(CShadowManager::SHADOWS);
00143 }
00144
00145
00149 CShadowManager::~CShadowManager()
00150 {
00151 ONDEBUG( printf("--CShadowManager::destructor()\n") );
00152
00153 if ( this->sceneRoot != NULL )
00154 sceneRoot->unref();
00155
00156 environment->unref();
00157
00158 shadowCastersRoot->removeAllChildren();
00159 shadowCastersRoot->unref();
00160 shadowCastersRoot = NULL;
00161
00162 shadowLightsRoot->removeAllChildren();
00163 shadowLightsRoot->unref();
00164 shadowLightsRoot = NULL;
00165
00166 shadowSceneRoot->removeAllChildren();
00167 shadowSceneRoot->unref();
00168 shadowSceneRoot = NULL;
00169
00170 switchNode = NULL;
00171 }
00172
00173
00177 void CShadowManager::createShadows()
00178 {
00179 ONDEBUG( printf("--CShadowManager::createShadows()\n") );
00180
00181 int cnt = this->shadowLightsRoot->getNumChildren();
00182 ONDEBUG( printf("--CShadowManager:: SVN cnt: %d\n",cnt) );
00183 for (int i = 0; i < cnt; i++)
00184 {
00185 SoShadowLight * slight = static_cast<SoShadowLight *>(this->shadowLightsRoot->getChild(i));
00186 slight->createShadowVolumes();
00187 }
00188
00189 if ( this->sceneRoot != NULL )
00190 this->sceneRoot->touch();
00191 }
00192
00193
00199 void CShadowManager::setSceneType(enum CShadowManager::SCENE_TYPE type)
00200 {
00201
00202 this->switchNode->whichChild.setValue(type);
00203 }
00204
00205
00211 void CShadowManager::setManager(TShadowSettings * s)
00212 {
00213 settings = s;
00214 this->method2algorithm();
00215 this->createShadows();
00216 }
00217
00218
00224 const struct TShadowSettings * CShadowManager::readSettings()
00225 {
00226 return this->settings;
00227 }
00228
00229
00235 void CShadowManager::setMethod(enum TShadowMethod newMethod)
00236 {
00237 enum TShadowAlgorithm old = this->algorithm;
00238 this->settings->method = newMethod;
00239 this->method2algorithm();
00240 if ( old != this->algorithm )
00241 {
00242 ONDEBUG ( printf("setMethod: new algorithm => createShadows\n"); );
00243 this->createShadows();
00244 }
00245 else
00246 {
00247 ONDEBUG ( printf("setMethod: algorithm is not updated\n"); );
00248 }
00249 ONDEBUG ( printSettings() );
00250 }
00251
00252
00258 void CShadowManager::setSVDepth(float newfDepth)
00259 {
00260 this->settings->fDepth = newfDepth;
00261 this->createShadows();
00262 ONDEBUG ( printSettings() );
00263 }
00264
00265
00269 void CShadowManager::printSettings()
00270 {
00271 char * a = "";
00272 char * m = "";
00273 char * ds = "";
00274 switch (settings->method)
00275 {
00276 case zpass: m = "z-pass"; break;
00277 case zfail: m = "z-fail"; break;
00278 case autoset: m = "autoset"; break;
00279 default: m = "unknown"; break;
00280 }
00281 algorithm == zpassAlg ? a = "z-pass alg." : a = "z-fail alg.";
00282 settings->dropShadows ? ds = "shadows" : ds = "shadow volumes";
00283
00284 printf("\nSM Settings:\n");
00285 printf(" method: %s\n", m);
00286 printf(" algorithm: %s\n", a);
00287 printf(" show: %s\n", ds);
00288 printf(" far depth: %.2f\n\n", settings->fDepth);
00289 }
00290
00291
00297 TShadowAlgorithm * CShadowManager::getAlgorithm()
00298 {
00299 return &algorithm;
00300 }
00301
00302
00306 void CShadowManager::method2algorithm()
00307 {
00308 ONDEBUG(printf("CShadowManager::method2algorithm\n"));
00309 switch ( settings->method )
00310 {
00311 case zpass: algorithm = zpassAlg; break;
00312
00313 case zfail: algorithm = zfailAlg; break;
00314
00315 case autoset:
00316
00317 algorithm = zfailAlg;
00318 break;
00319
00320 default: algorithm = zfailAlg; break;
00321 }
00322 }
00323
00324
00333 void CShadowManager::disableSensors()
00334 {
00335
00336 int cnt = this->shadowCastersRoot->getNumChildren();
00337 ONDEBUG( printf(" disableSensors: SVN has %d children:\n",cnt));
00338 if ( cnt > 0 ) {
00339 for (int i = 0; i < cnt; i++ ) {
00340 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00341 caster->getMoveSensor()->detach();
00342 caster->getShapeSensor()->detach();
00343 }
00344 }
00345 }
00346
00347
00351 void CShadowManager::enableSensors()
00352 {
00353
00354 int cnt = this->shadowCastersRoot->getNumChildren();
00355 ONDEBUG( printf(" enableSensors: SVN has %d children:\n",cnt));
00356 if ( cnt > 0 ) {
00357 for (int i = 0; i < cnt; i++ ) {
00358 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00359 caster->getMoveSensor()->attach(caster->path);
00360 caster->getShapeSensor()->attach(caster->objectRoot);
00361 }
00362 }
00363 }
00364
00367
00368
00374 SoEnvironment * CShadowManager::getEnvironmentNode()
00375 {
00376 return this->environment;
00377 }
00378
00379
00387 void CShadowManager::setAmbientIntensity(float val)
00388 {
00389 this->environment->ambientIntensity.setValue(val);
00390 }
00391
00401 SoEnvironment * CShadowManager::findEnvironmentNode()
00402 {
00403 if ( this->sceneRoot != NULL )
00404 {
00405 SoSearchAction * sa = new SoSearchAction;
00406 sa->setType(SoEnvironment::getClassTypeId());
00407 sa->setSearchingAll(FALSE);
00408 sa->apply(this->sceneRoot);
00409
00410 SoPath * nodePath = sa->getPath();
00411 if ( nodePath == NULL ) {
00412 ONDEBUG( printf("SoEnvironment not FOUND\n") );
00413 return NULL;
00414 }
00415 else
00416 {
00417 if (nodePath->getTail()->isOfType(SoEnvironment::getClassTypeId()))
00418 {
00419 ONDEBUG( printf("SoEnvironment is FOUND !!!\n") );
00420 SoEnvironment * env = (SoEnvironment*) nodePath->getTail();
00421 return env;
00422 }
00423 }
00424 }
00425 return NULL;
00426 }
00427
00430
00437 void CShadowManager::lightMoveCallback(void * userdata, SoSensor *s)
00438 {
00439 ONDEBUG( printf("CShadowManager::lightMoveCallback for one light\n") );
00440
00441 SoShadowLight * slight = static_cast<SoShadowLight *> (userdata);
00442 slight->createShadowVolumes();
00443 }
00444
00445
00451 void CShadowManager::addLight(SoLight * light)
00452 {
00453 ONDEBUG( printf("addLight:\n") );
00454 int i = 0;
00455 int cnt = 0;
00456
00457
00458 SoSearchAction * sa = new SoSearchAction;
00459 sa->setNode(light);
00460 sa->setSearchingAll(FALSE);
00461 sa->apply(this->sceneRoot);
00462
00463 SoPath * nodePath = sa->getPath();
00464
00465 if ( nodePath == NULL ) {
00466 printError("addLight (warning): Light was not found in the scene graph.\nTherefore it was not added in the Shadow Manager\n");
00467 }
00468 else
00469 {
00470 bool found = FALSE;
00471
00472
00473
00474 cnt = this->shadowLightsRoot->getNumChildren();
00475 if ( cnt > 0 )
00476 {
00477 for (int i = 0; i < cnt; i++ )
00478 {
00479 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
00480 if ( slight->getLight() == light )
00481 {
00482 found = TRUE;
00483 }
00484 }
00485 }
00486
00487 if ( !found )
00488 {
00489
00490
00491 SbString lindex(lightIndex);
00492 SbString lname = "ShadowLight_";
00493 lname += lindex;
00494 ONDEBUG( printf(" sh light name: %s\n",lname.getString()) );
00495
00496 light->ref();
00497 SoShadowLight * slight = new SoShadowLight(this, light);
00498 slight->setName(lname);
00499 slight->setLightName(lightIndex);
00500
00501
00502 SoNodeSensor * lightSensor = new SoNodeSensor(this->lightMoveCallback, slight);
00503 lightSensor->attach((SoNode *) light);
00504 slight->setSensor(lightSensor);
00505
00506 this->shadowLightsRoot->addChild(slight);
00507
00508
00509 int cntc = this->shadowCastersRoot->getNumChildren();
00510 ONDEBUG( printf(" add light: num. casters: %d\n",cntc));
00511 if ( cntc > 0 ) {
00512 for (int i = 0; i < cntc; i++ ) {
00513 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00514
00515
00516
00517 SbString cindex(caster->getCasterName());
00518 SbString vname = "SV_L";
00519 vname += lindex;
00520 vname += "_C";
00521 vname += cindex;
00522 ONDEBUG( printf(" sh light name: %s\n",vname.getString()) );
00523
00524
00525 SoShadowVolume * volume = new SoShadowVolume(slight, caster->getCasterName());
00526 volume->setName(vname);
00527 slight->addVolume(volume);
00528
00529 ONDEBUG( fprintf(stdout," child %d: %s\n",i,caster->getName().getString()) );
00530 }
00531 }
00532
00533 lightIndex++;
00534
00535 this->createShadows();
00536 } else {
00537 this->printError("Light is already present.");
00538 }
00539 }
00540 ONDEBUG(
00541 printf(" num. lights %d \n", this->shadowLightsRoot->getNumChildren() );
00542 );
00543 this->checkLights();
00544 ONDEBUG( printf("addLight end\n\n") );
00545 }
00546
00547
00558 void CShadowManager::removeLight(SoLight * light)
00559 {
00560 ONDEBUG( printf("removeLight:\n") );
00561
00562 int i = 0;
00563
00564 if ( light == NULL )
00565 {
00566 this->printError("Light is NULL.");
00567 }
00568 else
00569 {
00570 int cnt = this->shadowLightsRoot->getNumChildren();
00571 if ( cnt > 0 )
00572 {
00573 for ( i = 0; i < cnt; i++ )
00574 {
00575 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
00576 if ( slight->getLight() == light )
00577 {
00578 this->shadowLightsRoot->removeChild(i);
00579
00580 this->createShadows();
00581 light->unref();
00582 break;
00583 }
00584 }
00585 if ( i == cnt )
00586 this->printError("Light is not in SM.");
00587 }
00588 }
00589
00590 ONDEBUG(
00591 checkLights();
00592 printf(" lights %d \n", this->shadowLightsRoot->getNumChildren() );
00593 printf("removeLight end\n\n");
00594 );
00595 }
00596
00597
00601 void CShadowManager::checkLights()
00602 {
00603 bool found = FALSE;
00604
00605 int cnt = this->shadowLightsRoot->getNumChildren();
00606 if ( cnt > 0 )
00607 {
00608 for (int i = 0; i < cnt; i++ )
00609 {
00610 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
00611
00612 slight->getLight()->on.enableNotify(FALSE);
00613 SbBool s = slight->getLight()->on.getValue();
00614 char * status = "";
00615 s ? status = "on" : status = "off";
00616
00617 char * typ = "";
00618 if (slight->getLight()->getTypeId() == SoDirectionalLight::getClassTypeId() )
00619 typ = "SoDirectionalLight";
00620 else if (slight->getLight()->getTypeId() == SoDirectionalLightManip::getClassTypeId() )
00621 typ = "SoDirectionalLightManip";
00622 else if (slight->getLight()->getTypeId() == SoPointLight::getClassTypeId() )
00623 typ = "SoPointLight";
00624 else if (slight->getLight()->getTypeId() == SoPointLightManip::getClassTypeId() )
00625 typ = "SoPointLightManip";
00626 else if (slight->getLight()->getTypeId() == SoSpotLight::getClassTypeId() )
00627 typ = "SoSpotLight";
00628 else if (slight->getLight()->getTypeId() == SoSpotLightManip::getClassTypeId() )
00629 typ = "SoSpotLightManip";
00630 else
00631 typ = "Unknown light type";
00632
00633 ONDEBUG( fprintf(stdout," light %d: %s %s\n",i,status,typ) );
00634 }
00635 }
00636
00637 }
00638
00641
00652 void CShadowManager::objectMoveCallback(void * userdata, SoSensor *s)
00653 {
00654 ONDEBUG( printf("@@@caster path CB\n") );
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 SoShadowCaster * caster = static_cast<SoShadowCaster *>(userdata);
00671
00672 ONDEBUG( printf("@@@caster path CB called by %s\n", caster->getName().getString()) );
00673
00674
00675 SoDataSensor *mySensor = (SoDataSensor *)s;
00676
00677 SoNode *changedNode = mySensor->getTriggerNode();
00678 SoField *changedField = mySensor->getTriggerField();
00679
00680 if ( changedNode != NULL ) {
00681 ONDEBUG( printf(" The node named '%s' changed\n", changedNode->getName().getString()) );
00682 if ( changedNode->getTypeId().isDerivedFrom(SoTransformation::getClassTypeId()) )
00683 {
00684
00685 if ( !changedNode->isOfType(SoScale::getClassTypeId()) ) {
00686 ONDEBUG( printf(" create shadow volume for the caster (not a scale tr.)\n") );
00687 caster->setMoved(TRUE);
00688 caster->createShadowVolumes();
00689 } else {
00690 ONDEBUG( printf(" create shadow volume: scale transform\n") );
00691 caster->createFaceModel();
00692 caster->createShadowVolumes();
00693 }
00694 }
00695 else
00696 {
00697
00698
00699
00700
00701 if ( changedField == NULL )
00702 {
00703
00704
00705
00706
00707
00708 }
00709 else
00710 {
00711 ONDEBUG( printf(" changedNode is NOT NULL and changedField is NOT NULL as well, no SoTransformation \n") );
00712
00713 caster->createShadowVolumes();
00714 }
00715
00716 }
00717 }
00718 else
00719 {
00720 ONDEBUG( printf(" changedNode is NULL \n") );
00721 }
00722
00723 ONDEBUG( printf("@@@caster path CB done\n") );
00724 }
00725
00726
00733 void CShadowManager::objectShapeCallback(void * userdata, SoSensor *s)
00734 {
00735 ONDEBUG( printf("###caster shape CB\n") );
00736
00737 SoShadowCaster * caster = static_cast<SoShadowCaster *>(userdata);
00738
00739
00740 SoDataSensor * mySensor = (SoDataSensor *) s;
00741
00742 SoNode *changedNode = mySensor->getTriggerNode();
00743 SoField *changedField = mySensor->getTriggerField();
00744
00745 if ( changedNode != NULL ) {
00746 ONDEBUG( printf(" The node named '%s' changed\n", changedNode->getName().getString()) );
00747
00748 if (changedField == NULL)
00749 {
00750
00751 ONDEBUG( printf(" changedField == NULL\n") );
00752 if ( changedNode->isOfType(SoSeparator::getClassTypeId()) ) {
00753 ONDEBUG( printf(" added %d \n",caster->getCasterName()) );
00754
00755 caster->createFaceModel();
00756
00757 caster->createShadowVolumes();
00758 }
00759 }
00760 }
00761 else
00762 {
00763 ONDEBUG( printf(" changedNode is NULL in shape CB\n") );
00764 }
00765 ONDEBUG( printf("###caster shape CB\n") );
00766 }
00767
00775 int CShadowManager::findObject(SoSeparator * object)
00776 {
00777
00778 int found = -1;
00779 int cnt = this->shadowCastersRoot->getNumChildren();
00780 if ( cnt > 0 )
00781 {
00782 for (int i = 0; i < cnt; i++ )
00783 {
00784 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00785 if ( caster->getObjectNode() == object )
00786 {
00787 ONDEBUG( printf("findObject: Object is already in SM: %d\n", caster->getCasterName()) );
00788 return caster->getCasterName();
00789 }
00790 }
00791 }
00792 ONDEBUG( printf("findObject: Object is not in SM\n") );
00793 return found;
00794 }
00795
00796
00810 void CShadowManager::addObject(SoSeparator * object)
00811 {
00812 ONDEBUG( printf("add Object\n") );
00813 int i = 0;
00814
00815
00816 SoSearchAction * sa = new SoSearchAction;
00817 sa->setNode(object);
00818 sa->setSearchingAll(FALSE);
00819 sa->apply(this->sceneRoot);
00820
00821
00822 SoPath * nodePath = sa->getPath();
00823 if ( nodePath == NULL ) {
00824 printError("addObject (warning): Object was not found in the scene graph.\nTherefore it was not added in the Shadow Manager.\n");
00825 }
00826 else
00827 {
00828 if ( findObject(object) < 0 )
00829 {
00830
00831 SoShadowCaster * caster = new SoShadowCaster(this, object);
00832 caster->setCasterName(objectIndex);
00833 this->shadowCastersRoot->addChild(caster);
00834 objectIndex++;
00835
00836
00837 object->ref();
00838
00839
00840 SoPathSensor * objectSensor = new SoPathSensor(this->objectMoveCallback, caster);
00841 objectSensor->setPriority(0);
00842 objectSensor->attach(nodePath);
00843 caster->setMoveSensor(objectSensor);
00844
00845 caster->path = nodePath;
00846
00847
00848 SoNodeSensor * objectSensorC = new SoNodeSensor(this->objectShapeCallback, caster);
00849 objectSensorC->attach((SoNode *) object);
00850 objectSensorC->setPriority(0);
00851 caster->setShapeSensor(objectSensorC);
00852
00853
00854
00855 int cnt = this->shadowLightsRoot->getNumChildren();
00856 if ( cnt > 0 )
00857 {
00858 for (int i = 0; i < cnt; i++ )
00859 {
00860 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
00861
00862
00863
00864 SbString cindex(caster->getCasterName());
00865 SbString lindex(slight->getLightName());
00866 SbString vname = "SV_L";
00867 vname += lindex;
00868 vname += "_C";
00869 vname += cindex;
00870 ONDEBUG( printf(" sh volume name: %s\n",vname.getString()) );
00871
00872
00873 SoShadowVolume * volume = new SoShadowVolume(slight, caster->getCasterName());
00874 volume->setName(vname);
00875
00876 slight->addVolume(volume);
00877 }
00878 }
00879
00880 ONDEBUG( printf(" child %d: %s\n",i,caster->getName().getString()) );
00881 ONDEBUG( printf(" add obj: volume added\n") );
00882 ONDEBUG( printf(" The new caster has %d children.\n", caster->getNumChildren()) );
00883
00884
00885
00886
00887 object->touch();
00888 ONDEBUG( this->printMsg(" Object was added.") );
00889
00890 } else {
00891 this->printError("Object is already present.");
00892 }
00893 }
00894 ONDEBUG( checkObjects() );
00895 ONDEBUG( printf("add object done\n\n") );
00896 }
00897
00898
00907 void CShadowManager::removeObject(SoSeparator * object)
00908 {
00909
00910 ONDEBUG( printf("remove object\n") );
00911
00912 int found = -1;
00913 int cnt = this->shadowCastersRoot->getNumChildren();
00914 if ( cnt > 0 )
00915 {
00916 for (int i = 0; i < cnt; i++ )
00917 {
00918 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00919 if ( caster->getObjectNode() == object )
00920 {
00921 ONDEBUG( printf(" removing caster: %d\n", caster->getCasterName()) );
00922 found = caster->getCasterName();
00923
00924
00925 int cntl = this->shadowLightsRoot->getNumChildren();
00926 for (int j = 0; j < cntl; j++ )
00927 {
00928 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(j);
00929 slight->deleteVolume(caster->getCasterName());
00930 }
00931
00932 this->shadowCastersRoot->removeChild(i);
00933
00934 object->unref();
00935
00936 break;
00937
00938
00939 }
00940 }
00941 }
00942 if ( found < 0 ) {
00943 this->printError("removeObject: object not found.");
00944 }
00945 ONDEBUG( checkObjects() );
00946 ONDEBUG( printf("remove object done\n\n") );
00947
00948 }
00949
00950
00959 void CShadowManager::createObjectsShadows(SoSeparator * object)
00960 {
00961 ONDEBUG( printf("recreateObjectsShadows\n") );
00962
00963 int found = -1;
00964 int cnt = this->shadowCastersRoot->getNumChildren();
00965 if ( cnt > 0 )
00966 {
00967 for (int i = 0; i < cnt; i++ )
00968 {
00969 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00970 if ( caster->getObjectNode() == object )
00971 {
00972 found = 1;
00973 caster->createFaceModel();
00974 caster->createShadowVolumes();
00975 }
00976 }
00977 }
00978 if ( found < 0 ) {
00979 this->printError("recreateObjectsShadows: object not found.");
00980 }
00981 ONDEBUG( printf("recreateObjectsShadows done\n\n") );
00982 }
00983
00984
00988 void CShadowManager::checkObjects()
00989 {
00990 int cnt = this->shadowCastersRoot->getNumChildren();
00991 ONDEBUG( fprintf(stdout,"\nSVN has %d children:\n",cnt) );
00992 if ( cnt > 0 ) {
00993 for (int i = 0; i < cnt; i++ ) {
00994 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00995 ONDEBUG( fprintf(stdout," child %d: %s\n",i,caster->getName().getString()) );
00996 }
00997 }
00998 ONDEBUG( fprintf(stdout,"\n") );
00999 }
01000
01001
01007 void CShadowManager::createCasterVolumes(int index)
01008 {
01009 int cnt = this->shadowLightsRoot->getNumChildren();
01010 if ( cnt > 0 )
01011 {
01012 for (int i = 0; i < cnt; i++ )
01013 {
01014 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
01015
01016 int vcnt = slight->getNumVolumes();
01017 if ( vcnt > 0 )
01018 {
01019 for (int j = 0; j < vcnt; j++ )
01020 {
01021
01022 SoShadowVolume * volume = (SoShadowVolume *) slight->getVolume(j);
01023 if ( volume->getCasterName() == index )
01024 {
01025 volume->create();
01026 }
01027 }
01028 }
01029 }
01030 }
01031 }
01032
01033
01036
01042 void CShadowManager::createShadowScene()
01043 {
01044 ONDEBUG( printf("creating shadow scene graph...\n") );
01045
01046
01047
01048 SoCallback * nslightsOffCallback = new SoCallback;
01049 nslightsOffCallback->setCallback(nslightsOffCB, this->shadowLightsRoot);
01050
01051 SoCallback * nslightsOnCallback = new SoCallback;
01052 nslightsOnCallback->setCallback(nslightsOnCB, this->shadowLightsRoot);
01053
01054 SoCallback * nsambientOffCallback = new SoCallback;
01055 nsambientOffCallback->setCallback(nsambientOffCB, this->environment);
01056
01057 SoCallback * nsambientOnCallback = new SoCallback;
01058 nsambientOnCallback->setCallback(nsambientOnCB, this->environment);
01059
01060
01061 SoCallback * initCallback = new SoCallback;
01062 initCallback->setCallback(initCB, this->shadowLightsRoot);
01063
01064 SoCallback * endCallback = new SoCallback;
01065 endCallback->setCallback(endCB, this->shadowLightsRoot);
01066
01067 ONDEBUG( this->printSettings() );
01068
01069 if ( this->sceneRoot != NULL )
01070 {
01071
01072
01073
01074
01075 this->sceneNoShadows->addChild(nslightsOffCallback);
01076 this->sceneNoShadows->addChild(this->sceneRoot);
01077 this->sceneNoShadows->addChild(nslightsOnCallback);
01078 this->sceneNoShadows->addChild(nsambientOffCallback);
01079 this->sceneNoShadows->addChild(this->sceneRoot);
01080 this->sceneNoShadows->addChild(nsambientOnCallback);
01081
01082
01083
01084
01085 SoSeparator * aboveShadowVloumesRoot = new SoSeparator;
01086 this->sceneWithShadows->addChild(aboveShadowVloumesRoot);
01087
01088 aboveShadowVloumesRoot->addChild(initCallback);
01089 aboveShadowVloumesRoot->addChild(this->sceneRoot);
01090
01091 aboveShadowVloumesRoot->addChild(shadowLightsRoot);
01092 aboveShadowVloumesRoot->addChild(endCallback);
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 }
01108 }
01109
01110
01116 SoSeparator * CShadowManager::getShadowSceneRoot()
01117 {
01118 if ( first ) {
01119 this->createShadowScene();
01120 first = FALSE;
01121 }
01122 return this->shadowSceneRoot;
01123 }
01124
01125
01131 SoSeparator * CShadowManager::getSceneRoot()
01132 {
01133 return this->sceneRoot;
01134 }
01135
01136
01139
01145 void CShadowManager::printMsg(const char *msg)
01146 {
01147 fprintf(stdout,"SM: %s\n",msg);
01148 }
01149
01150
01156 void CShadowManager::printError(const char *msg)
01157 {
01158 fprintf(stderr,"SM Error: %s\n",msg);
01159 }
01160
01161
01167 void CShadowManager::export(const char * filename)
01168 {
01169 SoOutput output;
01170 if ( output.openFile(filename) ) {
01171 SoWriteAction * writer = new SoWriteAction(&output);
01172 writer->apply(this->shadowLightsRoot);
01173 delete writer;
01174 }
01175 else
01176 {
01177 char * buf = NULL;
01178 sprintf(buf,"Can not open file '%s' for export.",filename);
01179 this->printError(buf);
01180 }
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01226
01228
01229
01230
01239 void CShadowManager::nslightsOffCB(void *userdata, SoAction *action)
01240 {
01241 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01242
01243 ONDEBUG(printf("nslightsOffCB\n"));
01244
01245
01246 glClearDepth(1.0f);
01247
01248 glEnable(GL_DEPTH_TEST);
01249 glDepthFunc(GL_LEQUAL);
01250
01251 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
01252
01253
01254
01255 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
01256 glPushAttrib(GL_ENABLE_BIT);
01257
01258 glEnable(GL_LIGHTING);
01259
01260
01261 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01262 int cnt = lightRoot->getNumChildren();
01263 for ( int i = 0; i < cnt; i++ )
01264 {
01265 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01266 slight->getLight()->on.enableNotify(FALSE);
01267 slight->status = slight->getLight()->on.getValue();
01268 slight->getLight()->on = FALSE;
01269 slight->getLight()->on.enableNotify(TRUE);
01270 }
01271
01272 }
01273 }
01274
01275
01284 void CShadowManager::nslightsOnCB(void *userdata, SoAction *action)
01285 {
01286 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01287
01288 ONDEBUG(printf("nslightsOnCB\n"));
01289
01290
01291 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01292 int cnt = lightRoot->getNumChildren();
01293 for ( int i = 0; i < cnt; i++ )
01294 {
01295 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01296 slight->getLight()->on.enableNotify(FALSE);
01297 slight->getLight()->on = slight->status;
01298 slight->getLight()->on.enableNotify(TRUE);
01299 }
01300 }
01301 }
01302
01303
01312 void CShadowManager::nsambientOffCB(void *userdata, SoAction *action)
01313 {
01314 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01315 ONDEBUG(printf("nsambientOffCB\n"));
01316
01317 glBlendFunc(GL_ONE, GL_ONE);
01318 glEnable(GL_BLEND);
01319
01320 SoEnvironment * env = (SoEnvironment * ) userdata;
01321
01322
01323
01324 if ( env != NULL )
01325 {
01326 env->ambientIntensity.enableNotify(FALSE);
01327 envIntensity = env->ambientIntensity.getValue();
01328 env->ambientIntensity.setValue(0.0f);
01329 env->ambientIntensity.enableNotify(TRUE);
01330 }
01331 }
01332 }
01333
01334
01344 void CShadowManager::nsambientOnCB(void *userdata, SoAction *action)
01345 {
01346 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01347 ONDEBUG(printf("nsambientOnCB\n"));
01348
01349 SoEnvironment * env = (SoEnvironment * ) userdata;
01350
01351
01352 if ( env != NULL )
01353 {
01354 env->ambientIntensity.enableNotify(FALSE);
01355 env->ambientIntensity.setValue(envIntensity);
01356 env->ambientIntensity.enableNotify(TRUE);
01357 }
01358
01359 glDisable(GL_BLEND);
01360 glDepthFunc(GL_LEQUAL);
01361 glPopAttrib();
01362 }
01363 }
01364
01365
01367
01369
01370
01380 void CShadowManager::initCB(void *userdata, SoAction *action)
01381 {
01382 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01383 ONDEBUG(printf("initCB\n"));
01384
01385
01386 glClearDepth(1.0f);
01387
01388 glEnable(GL_DEPTH_TEST);
01389 glDepthFunc(GL_LEQUAL);
01390
01391 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
01392 glEnable(GL_CULL_FACE);
01393
01394
01395 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
01396 glPushAttrib(GL_ENABLE_BIT);
01397
01398 glEnable(GL_LIGHTING);
01399
01400
01401 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01402 int cnt = lightRoot->getNumChildren();
01403 for ( int i = 0; i < cnt; i++ )
01404 {
01405 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01406 slight->getLight()->on.enableNotify(FALSE);
01407 slight->status = slight->getLight()->on.getValue();
01408 slight->getLight()->on = FALSE;
01409 slight->getLight()->on.enableNotify(TRUE);
01410 }
01411 }
01412 }
01413
01414
01424 void CShadowManager::endCB(void *userdata, SoAction *action)
01425 {
01426 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01427 ONDEBUG(printf("endCB\n"));
01428
01429
01430 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01431 int cnt = lightRoot->getNumChildren();
01432 for ( int i = 0; i < cnt; i++ )
01433 {
01434 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01435 slight->getLight()->on.enableNotify(FALSE);
01436 slight->getLight()->on = slight->status;
01437 slight->getLight()->on.enableNotify(TRUE);
01438 }
01439
01440 glDepthFunc(GL_LEQUAL);
01441 glPopAttrib();
01442 }
01443 }