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