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
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 }
00721 }
00722 else
00723 {
00724 ONDEBUG( printf(" changedNode is NULL \n") );
00725 }
00726
00727 ONDEBUG( printf("@@@caster path CB done\n") );
00728 }
00729
00730
00737 void CShadowManager::objectShapeCallback(void * userdata, SoSensor *s)
00738 {
00739 ONDEBUG( printf("###caster shape CB\n") );
00740
00741 SoShadowCaster * caster = static_cast<SoShadowCaster *>(userdata);
00742
00743
00744 SoDataSensor * mySensor = (SoDataSensor *) s;
00745
00746 SoNode *changedNode = mySensor->getTriggerNode();
00747 SoField *changedField = mySensor->getTriggerField();
00748
00749 if ( changedNode != NULL ) {
00750 ONDEBUG( printf(" The node named '%s' changed\n", changedNode->getName().getString()) );
00751
00752 if (changedField == NULL)
00753 {
00754
00755 ONDEBUG( printf(" changedField == NULL\n") );
00756 if ( changedNode->isOfType(SoSeparator::getClassTypeId()) ) {
00757 ONDEBUG( printf(" added %d \n",caster->getCasterName()) );
00758
00759 caster->createFaceModel();
00760
00761 caster->createShadowVolumes();
00762 }
00763 }
00764 }
00765 else
00766 {
00767 ONDEBUG( printf(" changedNode is NULL in shape CB\n") );
00768 }
00769 ONDEBUG( printf("###caster shape CB\n") );
00770 }
00771
00779 int CShadowManager::findObject(SoSeparator * object)
00780 {
00781
00782 int found = -1;
00783 int cnt = this->shadowCastersRoot->getNumChildren();
00784 if ( cnt > 0 )
00785 {
00786 for (int i = 0; i < cnt; i++ )
00787 {
00788 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00789 if ( caster->getObjectNode() == object )
00790 {
00791 ONDEBUG( printf("findObject: Object is already in SM: %d\n", caster->getCasterName()) );
00792 return caster->getCasterName();
00793 }
00794 }
00795 }
00796 ONDEBUG( printf("findObject: Object is not in SM\n") );
00797 return found;
00798 }
00799
00800
00814 void CShadowManager::addObject(SoSeparator * object)
00815 {
00816 ONDEBUG( printf("add Object\n") );
00817 int i = 0;
00818
00819
00820 SoSearchAction * sa = new SoSearchAction;
00821 sa->setNode(object);
00822 sa->setSearchingAll(FALSE);
00823 sa->apply(this->sceneRoot);
00824
00825
00826 SoPath * nodePath = sa->getPath();
00827 if ( nodePath == NULL ) {
00828 printError("addObject (warning): Object was not found in the scene graph.\nTherefore it was not added in the Shadow Manager.\n");
00829 }
00830 else
00831 {
00832 if ( findObject(object) < 0 )
00833 {
00834
00835 SoShadowCaster * caster = new SoShadowCaster(this, object);
00836 caster->setCasterName(objectIndex);
00837 this->shadowCastersRoot->addChild(caster);
00838 objectIndex++;
00839
00840
00841 object->ref();
00842
00843
00844 SoPathSensor * objectSensor = new SoPathSensor(this->objectMoveCallback, caster);
00845 objectSensor->setPriority(0);
00846 objectSensor->attach(nodePath);
00847 caster->setMoveSensor(objectSensor);
00848
00849 caster->path = nodePath;
00850
00851
00852 SoNodeSensor * objectSensorC = new SoNodeSensor(this->objectShapeCallback, caster);
00853 objectSensorC->attach((SoNode *) object);
00854 objectSensorC->setPriority(0);
00855 caster->setShapeSensor(objectSensorC);
00856
00857
00858
00859 int cnt = this->shadowLightsRoot->getNumChildren();
00860 if ( cnt > 0 )
00861 {
00862 for (int i = 0; i < cnt; i++ )
00863 {
00864 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
00865
00866
00867
00868 SbString cindex(caster->getCasterName());
00869 SbString lindex(slight->getLightName());
00870 SbString vname = "SV_L";
00871 vname += lindex;
00872 vname += "_C";
00873 vname += cindex;
00874 ONDEBUG( printf(" sh volume name: %s\n",vname.getString()) );
00875
00876
00877 SoShadowVolume * volume = new SoShadowVolume(slight, caster->getCasterName());
00878 volume->setName(vname);
00879
00880 slight->addVolume(volume);
00881 }
00882 }
00883
00884 ONDEBUG( printf(" child %d: %s\n",i,caster->getName().getString()) );
00885 ONDEBUG( printf(" add obj: volume added\n") );
00886 ONDEBUG( printf(" The new caster has %d children.\n", caster->getNumChildren()) );
00887
00888
00889
00890
00891 object->touch();
00892 ONDEBUG( this->printMsg(" Object was added.") );
00893
00894 } else {
00895 this->printError("Object is already present.");
00896 }
00897 }
00898 ONDEBUG( checkObjects() );
00899 ONDEBUG( printf("add object done\n\n") );
00900 }
00901
00902
00911 void CShadowManager::removeObject(SoSeparator * object)
00912 {
00913
00914 ONDEBUG( printf("remove object\n") );
00915
00916 int found = -1;
00917 int cnt = this->shadowCastersRoot->getNumChildren();
00918 if ( cnt > 0 )
00919 {
00920 for (int i = 0; i < cnt; i++ )
00921 {
00922 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00923 if ( caster->getObjectNode() == object )
00924 {
00925 ONDEBUG( printf(" removing caster: %d\n", caster->getCasterName()) );
00926 found = caster->getCasterName();
00927
00928
00929 int cntl = this->shadowLightsRoot->getNumChildren();
00930 for (int j = 0; j < cntl; j++ )
00931 {
00932 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(j);
00933 slight->deleteVolume(caster->getCasterName());
00934 }
00935
00936 this->shadowCastersRoot->removeChild(i);
00937
00938 object->unref();
00939
00940 break;
00941
00942
00943 }
00944 }
00945 }
00946 if ( found < 0 ) {
00947 this->printError("removeObject: object not found.");
00948 }
00949 ONDEBUG( checkObjects() );
00950 ONDEBUG( printf("remove object done\n\n") );
00951
00952 }
00953
00954
00963 void CShadowManager::createObjectsShadows(SoSeparator * object)
00964 {
00965 ONDEBUG( printf("recreateObjectsShadows\n") );
00966
00967 int found = -1;
00968 int cnt = this->shadowCastersRoot->getNumChildren();
00969 if ( cnt > 0 )
00970 {
00971 for (int i = 0; i < cnt; i++ )
00972 {
00973 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00974 if ( caster->getObjectNode() == object )
00975 {
00976 found = 1;
00977 caster->createFaceModel();
00978 caster->createShadowVolumes();
00979 }
00980 }
00981 }
00982 if ( found < 0 ) {
00983 this->printError("recreateObjectsShadows: object not found.");
00984 }
00985 ONDEBUG( printf("recreateObjectsShadows done\n\n") );
00986 }
00987
00988
00992 void CShadowManager::checkObjects()
00993 {
00994 int cnt = this->shadowCastersRoot->getNumChildren();
00995 ONDEBUG( fprintf(stdout,"\nSVN has %d children:\n",cnt) );
00996 if ( cnt > 0 ) {
00997 for (int i = 0; i < cnt; i++ ) {
00998 SoShadowCaster * caster = (SoShadowCaster *) this->shadowCastersRoot->getChild(i);
00999 ONDEBUG( fprintf(stdout," child %d: %s\n",i,caster->getName().getString()) );
01000 }
01001 }
01002 ONDEBUG( fprintf(stdout,"\n") );
01003 }
01004
01005
01011 void CShadowManager::createCasterVolumes(int index)
01012 {
01013 int cnt = this->shadowLightsRoot->getNumChildren();
01014 if ( cnt > 0 )
01015 {
01016 for (int i = 0; i < cnt; i++ )
01017 {
01018 SoShadowLight * slight = (SoShadowLight *) this->shadowLightsRoot->getChild(i);
01019
01020 int vcnt = slight->getNumVolumes();
01021 if ( vcnt > 0 )
01022 {
01023 for (int j = 0; j < vcnt; j++ )
01024 {
01025
01026 SoShadowVolume * volume = (SoShadowVolume *) slight->getVolume(j);
01027 if ( volume->getCasterName() == index )
01028 {
01029 volume->create();
01030 }
01031 }
01032 }
01033 }
01034 }
01035 }
01036
01037
01040
01046 void CShadowManager::createShadowScene()
01047 {
01048 ONDEBUG( printf("creating shadow scene graph...\n") );
01049
01050
01051
01052 SoCallback * nslightsOffCallback = new SoCallback;
01053 nslightsOffCallback->setCallback(nslightsOffCB, this->shadowLightsRoot);
01054
01055 SoCallback * nslightsOnCallback = new SoCallback;
01056 nslightsOnCallback->setCallback(nslightsOnCB, this->shadowLightsRoot);
01057
01058 SoCallback * nsambientOffCallback = new SoCallback;
01059 nsambientOffCallback->setCallback(nsambientOffCB, this->environment);
01060
01061 SoCallback * nsambientOnCallback = new SoCallback;
01062 nsambientOnCallback->setCallback(nsambientOnCB, this->environment);
01063
01064
01065 SoCallback * initCallback = new SoCallback;
01066 initCallback->setCallback(initCB, this->shadowLightsRoot);
01067
01068 SoCallback * endCallback = new SoCallback;
01069 endCallback->setCallback(endCB, this->shadowLightsRoot);
01070
01071 ONDEBUG( this->printSettings() );
01072
01073 if ( this->sceneRoot != NULL )
01074 {
01075
01076
01077
01078
01079 this->sceneNoShadows->addChild(nslightsOffCallback);
01080 this->sceneNoShadows->addChild(this->sceneRoot);
01081 this->sceneNoShadows->addChild(nslightsOnCallback);
01082 this->sceneNoShadows->addChild(nsambientOffCallback);
01083 this->sceneNoShadows->addChild(this->sceneRoot);
01084 this->sceneNoShadows->addChild(nsambientOnCallback);
01085
01086
01087
01088
01089 SoSeparator * aboveShadowVloumesRoot = new SoSeparator;
01090 this->sceneWithShadows->addChild(aboveShadowVloumesRoot);
01091
01092 aboveShadowVloumesRoot->addChild(initCallback);
01093 aboveShadowVloumesRoot->addChild(this->sceneRoot);
01094
01095 aboveShadowVloumesRoot->addChild(shadowLightsRoot);
01096 aboveShadowVloumesRoot->addChild(endCallback);
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111 }
01112 }
01113
01114
01120 SoSeparator * CShadowManager::getShadowSceneRoot()
01121 {
01122 if ( first ) {
01123 this->createShadowScene();
01124 first = FALSE;
01125 }
01126 return this->shadowSceneRoot;
01127 }
01128
01129
01135 SoSeparator * CShadowManager::getSceneRoot()
01136 {
01137 return this->sceneRoot;
01138 }
01139
01140
01143
01149 void CShadowManager::printMsg(const char *msg)
01150 {
01151 fprintf(stdout,"SM: %s\n",msg);
01152 }
01153
01154
01160 void CShadowManager::printError(const char *msg)
01161 {
01162 fprintf(stderr,"SM Error: %s\n",msg);
01163 }
01164
01165
01171 void CShadowManager::export(const char * filename)
01172 {
01173 SoOutput output;
01174 if ( output.openFile(filename) ) {
01175 SoWriteAction * writer = new SoWriteAction(&output);
01176 writer->apply(this->shadowLightsRoot);
01177 delete writer;
01178 }
01179 else
01180 {
01181 char * buf = NULL;
01182 sprintf(buf,"Can not open file '%s' for export.",filename);
01183 this->printError(buf);
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
01225
01226
01227
01228
01230
01232
01233
01234
01243 void CShadowManager::nslightsOffCB(void *userdata, SoAction *action)
01244 {
01245 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01246
01247 ONDEBUG(printf("nslightsOffCB\n"));
01248
01249
01250 glClearDepth(1.0f);
01251
01252 glEnable(GL_DEPTH_TEST);
01253 glDepthFunc(GL_LEQUAL);
01254
01255 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
01256
01257
01258
01259 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
01260 glPushAttrib(GL_ENABLE_BIT);
01261
01262 glEnable(GL_LIGHTING);
01263
01264
01265 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01266 int cnt = lightRoot->getNumChildren();
01267 for ( int i = 0; i < cnt; i++ )
01268 {
01269 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01270 slight->getLight()->on.enableNotify(FALSE);
01271 slight->status = slight->getLight()->on.getValue();
01272 slight->getLight()->on = FALSE;
01273 slight->getLight()->on.enableNotify(TRUE);
01274 }
01275
01276 }
01277 }
01278
01279
01288 void CShadowManager::nslightsOnCB(void *userdata, SoAction *action)
01289 {
01290 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01291
01292 ONDEBUG(printf("nslightsOnCB\n"));
01293
01294
01295 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01296 int cnt = lightRoot->getNumChildren();
01297 for ( int i = 0; i < cnt; i++ )
01298 {
01299 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01300 slight->getLight()->on.enableNotify(FALSE);
01301 slight->getLight()->on = slight->status;
01302 slight->getLight()->on.enableNotify(TRUE);
01303 }
01304 }
01305 }
01306
01307
01316 void CShadowManager::nsambientOffCB(void *userdata, SoAction *action)
01317 {
01318 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01319 ONDEBUG(printf("nsambientOffCB\n"));
01320
01321 glBlendFunc(GL_ONE, GL_ONE);
01322 glEnable(GL_BLEND);
01323
01324 SoEnvironment * env = (SoEnvironment * ) userdata;
01325
01326
01327
01328 if ( env != NULL )
01329 {
01330 env->ambientIntensity.enableNotify(FALSE);
01331 envIntensity = env->ambientIntensity.getValue();
01332 env->ambientIntensity.setValue(0.0f);
01333 env->ambientIntensity.enableNotify(TRUE);
01334 }
01335 }
01336 }
01337
01338
01348 void CShadowManager::nsambientOnCB(void *userdata, SoAction *action)
01349 {
01350 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01351 ONDEBUG(printf("nsambientOnCB\n"));
01352
01353 SoEnvironment * env = (SoEnvironment * ) userdata;
01354
01355
01356 if ( env != NULL )
01357 {
01358 env->ambientIntensity.enableNotify(FALSE);
01359 env->ambientIntensity.setValue(envIntensity);
01360 env->ambientIntensity.enableNotify(TRUE);
01361 }
01362
01363 glDisable(GL_BLEND);
01364 glDepthFunc(GL_LEQUAL);
01365 glPopAttrib();
01366 }
01367 }
01368
01369
01371
01373
01374
01384 void CShadowManager::initCB(void *userdata, SoAction *action)
01385 {
01386 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01387 ONDEBUG(printf("initCB\n"));
01388
01389
01390 glClearDepth(1.0f);
01391
01392 glEnable(GL_DEPTH_TEST);
01393 glDepthFunc(GL_LEQUAL);
01394
01395 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
01396 glEnable(GL_CULL_FACE);
01397
01398
01399 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
01400 glPushAttrib(GL_ENABLE_BIT);
01401
01402 glEnable(GL_LIGHTING);
01403
01404
01405 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01406 int cnt = lightRoot->getNumChildren();
01407 for ( int i = 0; i < cnt; i++ )
01408 {
01409 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01410 slight->getLight()->on.enableNotify(FALSE);
01411 slight->status = slight->getLight()->on.getValue();
01412 slight->getLight()->on = FALSE;
01413 slight->getLight()->on.enableNotify(TRUE);
01414 }
01415 }
01416 }
01417
01418
01428 void CShadowManager::endCB(void *userdata, SoAction *action)
01429 {
01430 if (action->isOfType(SoGLRenderAction::getClassTypeId())) {
01431 ONDEBUG(printf("endCB\n"));
01432
01433
01434 SoSeparator * lightRoot = (SoSeparator * ) userdata;
01435 int cnt = lightRoot->getNumChildren();
01436 for ( int i = 0; i < cnt; i++ )
01437 {
01438 SoShadowLight * slight = static_cast<SoShadowLight *>(lightRoot->getChild(i));
01439 slight->getLight()->on.enableNotify(FALSE);
01440 slight->getLight()->on = slight->status;
01441 slight->getLight()->on.enableNotify(TRUE);
01442 }
01443
01444 glDepthFunc(GL_LEQUAL);
01445 glPopAttrib();
01446 }
01447 }