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 "SoShadowVolume.h"
00033
00034
00035
00036
00037
00044 SoShadowVolume::SoShadowVolume(SoShadowLight *l, int cn)
00045 : shadowlight(l),
00046 casterName(cn)
00047 {
00048
00049 transform = new SoTransform();
00050 nScTr = 0;
00051 nSVTr = 0;
00052 aLight = shadowlight->getLight();
00053
00054 objectModel = NULL;
00055 trMatrix = NULL;
00056 caster = NULL;
00057
00058 if ( casterName >= 0 )
00059 {
00060
00061 SbString index(casterName);
00062 SbString name = "Caster_";
00063 name += index;
00064
00065
00066 caster = (SoShadowCaster *)SoNode::getByName(name);
00067 ONDEBUG( printf("SV::constructor caster name (%d): %d\n", casterName, caster->getCasterName()) );
00068 }
00069
00070 initNode = NULL;
00071 volumeNode = NULL;
00072
00073 this->init();
00074 }
00075
00076
00080 SoShadowVolume::~SoShadowVolume()
00081 {
00082 this->removeAllChildren();
00083 }
00084
00085
00089 void SoShadowVolume::init()
00090 {
00091 this->initNode = new SoGroup;
00092 this->addChild(initNode);
00093 this->volumeNode = new SoGroup;
00094 this->addChild(volumeNode);
00095
00096
00097
00098 transform->translation.setValue(0.0f, 0.0f, 0.0f);
00099 transform->rotation.setValue(0.0f, 0.0f, 0.0f, 1.0f);
00100 transform->scaleFactor.setValue(1.0f, 1.0f, 1.0f);
00101 transform->scaleOrientation.setValue(0.0f, 0.0f, 0.0f, 1.0f);
00102 transform->center.setValue(0.0f, 0.0f, 0.0f);
00103 this->initNode->addChild(transform);
00104
00105
00106 SoMaterial *material = new SoMaterial;
00107 material->ambientColor.setValue(svColor);
00108 material->diffuseColor.setValue(svColor);
00109
00110 this->initNode->addChild(material);
00111
00112
00113 SoShapeHints * hints = new SoShapeHints;
00114 hints->shapeType = SoShapeHintsElement::SOLID;
00115 hints->vertexOrdering = SoShapeHintsElement::COUNTERCLOCKWISE;
00116 this->initNode->addChild(hints);
00117
00118
00119 SoNormalBinding *nbind = new SoNormalBinding;
00120 nbind->value.setValue(SoNormalBinding::PER_FACE_INDEXED);
00121 this->initNode->addChild(nbind);
00122 }
00123
00124
00130 int SoShadowVolume::getCasterName()
00131 {
00132 return this->casterName;
00133 }
00134
00135
00139 void SoShadowVolume::create()
00140 {
00141 ONDEBUG( printf("+++SoShadowVolume::create()\n") );
00142
00143 if ( aLight != NULL )
00144 {
00145
00146 SbBool lightON = TRUE;
00147 aLight->on.enableNotify(FALSE);
00148 lightON = this->aLight->on.getValue();
00149 aLight->on.enableNotify(TRUE);
00150
00151 ONDEBUG(
00152 if ( lightON )
00153 printf("+++SoShadowVolume::light is ON\n");
00154 else
00155 printf("+++SoShadowVolume::light is OFF\n");
00156 );
00157
00158
00159
00160
00161 ONDEBUG( printf("caster name: %d\n",casterName) );
00162 SbVec3f translation(0.0f, 0.0f, 0.0f);
00163 bool dirOpt = FALSE;
00164
00165 if ( caster != NULL )
00166 {
00167 trMatrix = caster->getMatrix();
00168 objectModel = caster->getObjectModel();
00169
00170 if ( caster->moved() )
00171 {
00172 ONDEBUG( printf("CASTER MOVEMENT: \n") );
00173 if ( aLight->getTypeId() == SoDirectionalLight::getClassTypeId()
00174 || aLight->getTypeId() == SoDirectionalLightManip::getClassTypeId()
00175 )
00176 {
00177 ONDEBUG( printf("dir. light optimalisation \n") );
00178 SbVec3f pointOld(1.0f, 1.0f, 1.0f);
00179 SbVec3f pointNew(1.0f, 1.0f, 1.0f);
00180 caster->trMatrixOld.multVecMatrix(pointOld, pointOld);
00181 caster->trMatrix.multVecMatrix(pointNew, pointNew);
00182 translation = pointNew - pointOld;
00183 dirOpt = TRUE;
00184 }
00185 caster->setMoved(FALSE);
00186 }
00187 }
00188
00189
00190 if ( !dirOpt )
00191 {
00192
00193 ONDEBUG(
00194 int x = this->volumeNode->getNumChildren();
00195 printf("volume had %d children\n",x);
00196 );
00197
00198
00199 this->volumeNode->removeAllChildren();
00200
00201 nScTr = 0;
00202 nSVTr = 0;
00203
00204 transform->translation.setValue(0.0f, 0.0f, 0.0f);
00205 }
00206
00207 else
00208 {
00209
00210 transform->translation.setValue(transform->translation.getValue() + translation);
00211 }
00212
00213 if ( lightON && !dirOpt )
00214
00215 {
00216
00217
00218
00219 this->shadowlight->getManager()->method2algorithm();
00220
00221 int itn = 0;
00222 int j = 2;
00223 int itmat = 0;
00224 float vysl = 0.0f;
00225
00226 SbVec3f normal;
00227
00228 int b = this->objectModel->modelIfs->normalIndex.getNum();
00229
00230
00231
00232 while ( j < objectModel->modelIfs->coordIndex.getNum() ) {
00233
00234 while ( objectModel->modelIfs->coordIndex[j] != -1 ) {
00235
00236 if ( b < itn ) {
00237 ONDEBUG( fprintf(stderr,"Normal index out of range.\n\n") );
00238 exit(1);
00239 }
00240
00241
00242 int nindex = objectModel->modelIfs->normalIndex[itn];
00243 normal = objectModel->modelNormal->vector[nindex];
00244
00245
00246 SbVec3f x(objectModel->modelCoord3->point[objectModel->modelIfs->coordIndex[j-2]]);
00247 SbVec3f normEnd(x+1*normal);
00248
00249
00250 trMatrix->multVecMatrix(x, x);
00251
00252 trMatrix->multVecMatrix(normEnd, normEnd);
00253 normal = normEnd - x;
00254
00255 if ( normal.length() > .0f ) {
00256 normal.normalize();
00257 } else {
00258 ONDEBUG(printf("Error: Length of the normal is 0.\n"));
00259 }
00260
00261
00262
00263 SbVec3f lightLocation;
00264 SbVec3f lightDirection;
00265 enum TLightTypes lightType;
00266 char * typ = "";
00267
00268 if (aLight->getTypeId() == SoDirectionalLight::getClassTypeId() )
00269 {
00270 lightType = TSoDirectionalLight;
00271 typ = "TSoDirectionalLight";
00272 SoDirectionalLight * light = (SoDirectionalLight *)aLight;
00273 lightDirection = light->direction.getValue();
00274 }
00275 else if (aLight->getTypeId() == SoDirectionalLightManip::getClassTypeId() )
00276 {
00277 lightType = TSoDirectionalLightManip;
00278 typ = "TSoDirectionalLightManip";
00279 SoDirectionalLightManip * light = (SoDirectionalLightManip *)aLight;
00280 lightDirection = light->direction.getValue();
00281 }
00282 else if (aLight->getTypeId() == SoPointLight::getClassTypeId() )
00283 {
00284 lightType = TSoPointLight;
00285 typ = "TSoPointLight";
00286 SoPointLight * light = (SoPointLight *)aLight;
00287 lightLocation = light->location.getValue();
00288 }
00289 else if (aLight->getTypeId() == SoPointLightManip::getClassTypeId() )
00290 {
00291 lightType = TSoPointLightManip;
00292 typ = "TSoPointLightManip";
00293 SoPointLightManip * light = (SoPointLightManip *)(aLight);
00294 lightLocation = light->location.getValue();
00295 }
00296 else if (aLight->getTypeId() == SoSpotLight::getClassTypeId() )
00297 {
00298 lightType = TSoSpotLight;
00299 typ = "TSoSpotLight";
00300 SoSpotLight * light = (SoSpotLight *)(aLight);
00301 lightLocation = light->location.getValue();
00302 }
00303 else if (aLight->getTypeId() == SoSpotLightManip::getClassTypeId() )
00304 {
00305 lightType = TSoSpotLightManip;
00306 typ = "TSoSpotLightManip";
00307 SoSpotLightManip * light = (SoSpotLightManip *)aLight;
00308 lightLocation = light->location.getValue();
00309 }
00310 else
00311 {
00312 lightType = TUnknownLightType;
00313 typ = "TUnknownLightType";
00314 }
00315
00316
00317
00318
00319 SbVec3f lv;
00320 if (lightType == TSoDirectionalLight)
00321 {
00322 lv = lightDirection;
00323 }
00324 else if (lightType == TSoDirectionalLightManip)
00325 {
00326 lv = lightDirection;
00327 }
00328 else if (lightType == TSoPointLight)
00329 {
00330 lv = (lightLocation-x);
00331 }
00332 else if (lightType == TSoPointLightManip)
00333 {
00334 lv = (lightLocation-x);
00335 }
00336 else if (lightType == TSoSpotLight)
00337 {
00338 lv = (lightLocation-x);
00339 }
00340 else if (lightType == TSoSpotLightManip)
00341 {
00342 lv = (lightLocation-x);
00343 }
00344
00345
00346
00347 vysl = normal.dot(lv);
00348 if ( vysl <= 0.0f )
00349 {
00350
00351 int n = objectModel->modelIfs->materialIndex.getNum();
00352 objectModel->modelIfs->materialIndex.set1Value(n,0);
00353 objectModel->modelIfs->materialIndex.setNum(n+1);
00354 }
00355 else
00356 {
00357
00358 this->nScTr++;
00359 int n = objectModel->modelIfs->materialIndex.getNum();
00360 objectModel->modelIfs->materialIndex.set1Value(n,1);
00361 objectModel->modelIfs->materialIndex.setNum(n+1);
00362
00363
00364
00365 SoCoordinate3 *envCoords = new SoCoordinate3;
00366 SoIndexedTriangleStripSet * envStrip = new SoIndexedTriangleStripSet;
00367
00368
00369
00370 envCoords->point.setNum(2*3+2);
00371 this->nSVTr += 6;
00372
00373 SbVec3f *c = envCoords->point.startEditing();
00374
00375 int k = 0;
00376
00377
00378 for ( k=3; k >= 0; k-- )
00379 {
00380
00381 int t = j-k%3;
00382 SbVec3f xx(objectModel->modelCoord3->point[objectModel->modelIfs->coordIndex[t]]);
00383 trMatrix->multVecMatrix(xx, xx);
00384
00385 SbVec3f l2pVec;
00386 if (lightType != TSoDirectionalLight && lightType != TSoDirectionalLightManip)
00387 {
00388 l2pVec = xx - lightLocation;
00389 }
00390 else
00391 {
00392 l2pVec = lightDirection;
00393 }
00394
00395
00396 SbVec3f xxFar(farPointNew(l2pVec, xx, this->shadowlight->getManager()->readSettings()->fDepth));
00397 *(c++) = xx;
00398 *(c++) = xxFar;
00399 }
00400 envCoords->point.finishEditing();
00401
00402
00403 this->volumeNode->addChild(envCoords);
00404
00405
00406 int32_t indeces[24] = {0,1,2,-1,2,1,3,-1, 2,3,4,-1,4,3,5,-1, 4,5,6,-1,6,5,7,-1};
00407
00408
00409 int32_t indecesDir[24] = {1,0,2,-1, 1,2,3,-1, 2,4,3,-1, 3,4,5,-1, 4,6,5,-1, 6,7,5,-1};
00410 if (lightType == TSoDirectionalLight || lightType == TSoDirectionalLightManip)
00411 envStrip->coordIndex.setValues(0,24,indecesDir);
00412 else
00413 envStrip->coordIndex.setValues(0,24,indeces);
00414 this->volumeNode->addChild(envStrip);
00415
00416
00417
00418
00419
00420 if ( *this->shadowlight->getManager()->getAlgorithm() == zfailAlg )
00421
00422 {
00423
00424 SoIndexedTriangleStripSet * ncapStrip = new SoIndexedTriangleStripSet;
00425 int32_t ncapIndeces[4] = {0,2,4,-1};
00426
00427 int32_t ncapIndecesDir[4] = {0,4,2,-1};
00428 if (lightType == TSoDirectionalLight || lightType == TSoDirectionalLightManip)
00429 ncapStrip->coordIndex.setValues(0,4,ncapIndecesDir);
00430 else
00431 ncapStrip->coordIndex.setValues(0,4,ncapIndeces);
00432 this->volumeNode->addChild(ncapStrip);
00433
00434 SoIndexedTriangleStripSet * fcapStrip = new SoIndexedTriangleStripSet;
00435 int32_t fcapIndeces[4] = {1,5,3,-1};
00436
00437 int32_t fcapIndecesDir[4] = {1,3,5,-1};
00438 if (lightType == TSoDirectionalLight || lightType == TSoDirectionalLightManip)
00439 fcapStrip->coordIndex.setValues(0,4,fcapIndecesDir);
00440 else
00441 fcapStrip->coordIndex.setValues(0,4,fcapIndeces);
00442 this->volumeNode->addChild(fcapStrip);
00443
00444
00445 this->nSVTr += 2;
00446 }
00447
00448
00449 }
00450
00451 itn++;
00452 j++;
00453
00454 }
00455
00456 j += 3;
00457
00458 }
00459 ONDEBUG( printf("Shadow volumes of the object created. They consists of %d shadow casting tr.\n", this->nScTr) );
00460 }
00461
00462 }
00463 else
00464 {
00465 printf("light is NULL\n");
00466 }
00467 }
00468
00469
00475 void SoShadowVolume::writeShadowVolume(const char *filename)
00476 {
00477 SoOutput output;
00478
00479 if (this->getChildren()->getLength() != 0) {
00480 output.openFile(filename);
00481 SoWriteAction * writer = new SoWriteAction(&output);
00482 writer->apply(this);
00483 delete writer;
00484 ONDEBUG( fprintf(stdout,"Shadows' scene graph was written in '%s'.\n\n", filename) );
00485 } else {
00486 ONDEBUG( fprintf(stderr,"Error: Could not write shadows' scene graph.\nShadow volumes have not been generated yet.\n\n") );
00487 }
00488 }
00489
00490
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00526 SbVec3f SoShadowVolume::farPointNew(SbVec3f lightVec, SbVec3f point, float farDepth)
00527 {
00528 SbVec3f farPoint(point);
00529 lightVec.normalize();
00530 farPoint = point + farDepth * lightVec;
00531
00532 return farPoint;
00533 }
00534
00535
00547 SbVec3f SoShadowVolume::faceNormal(const SbVec3f p1, const SbVec3f p2, const SbVec3f p3)
00548 {
00549 SbVec3f vector1, vector2;
00550
00551 vector1 = p2 - p1;
00552 vector2 = p3 - p2;
00553
00554 if ( vector1.length() <= .0f ) {
00555 ONDEBUG(printf("Error: Length of a vector1 is 0. Correcting...\n"));
00556 }
00557 if ( vector2.length() <= .0f ) {
00558 ONDEBUG(printf("Error: Length of a vector2 is 0. Correcting...\n"));
00559 }
00560
00561 SbVec3f normal = vector1.cross(vector2);
00562 if ( normal.length() > .0f ) {
00563 normal.normalize();
00564 } else {
00565 ONDEBUG(printf("Error: FaceNormal: Length of the normal is 0.\n"));
00566 }
00567
00568 return normal;
00569 }