00001
00002
00003
00004
00005
00006
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
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <boost/bind.hpp>
00046
00047 #include "OSGMergeGraphOp.h"
00048 #include "OSGDirectionalLight.h"
00049 #include "OSGSpotLight.h"
00050 #include "OSGLight.h"
00051 #include "OSGPointLight.h"
00052 #include "OSGSwitch.h"
00053 #include "OSGDistanceLOD.h"
00054 #include "OSGBillboard.h"
00055 #include "OSGMaterialGroup.h"
00056 #include "OSGComponentTransform.h"
00057 #include "OSGPrimitiveIterator.h"
00058 #include "OSGGeometry.h"
00059 #include "OSGGeoFunctions.h"
00060 #include "OSGGraphOpFactory.h"
00061
00062
00063 #define OSG2_MERGE_MISSING
00064
00065 OSG_USING_NAMESPACE
00066
00067
00068
00069
00070
00078
00079 static bool registerOp(void)
00080 {
00081 GraphOpRefPtr newOp = MergeGraphOp::create();
00082
00083 GraphOpFactory::the()->registerOp(newOp);
00084 return true;
00085 }
00086 static OSG::StaticInitFuncWrapper registerOpWrapper(registerOp);
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 MergeGraphOp::MergeGraphOp(const char* name): GraphOp(name),
00100 _secondary_color_is_vector(false),
00101 _texcoord0_is_vector(false),
00102 _texcoord1_is_vector(false),
00103 _texcoord2_is_vector(false),
00104 _texcoord3_is_vector(false)
00105 {
00106 }
00107
00108 MergeGraphOp::~MergeGraphOp(void)
00109 {
00110 }
00111
00112 MergeGraphOpTransitPtr
00113 MergeGraphOp::create(void)
00114 {
00115 return MergeGraphOpTransitPtr(new MergeGraphOp);
00116 }
00117
00118 GraphOpTransitPtr MergeGraphOp::clone(void)
00119 {
00120 return GraphOpTransitPtr(new MergeGraphOp);
00121 }
00122
00123 UInt32 countNodes(Node * const node)
00124 {
00125 if (node == NULL)
00126 return 0;
00127
00128 UInt32 total = 1;
00129 for (UInt32 i = 0; i < node->getNChildren(); ++i)
00130 total += countNodes(node->getChild(i));
00131 return total;
00132 }
00133
00134 bool MergeGraphOp::traverse(Node * node)
00135 {
00136
00137
00138
00139 UInt32 next = countNodes(node);
00140 SINFO << "MergeGraphOp::traverse: Number of nodes before merge: "
00141 << next << endLog;
00142 bool result = true;
00143 UInt32 current;
00144 do {
00145 current = next;
00146 result &= mergeOnce(node);
00147 if (!result)
00148 break;
00149 next = countNodes(node);
00150 } while (next < current);
00151
00152 SINFO << "MergeGraphOp::traverse: Number of nodes after merge: "
00153 << current << endLog;
00154
00155 return result;
00156 }
00157
00158 void MergeGraphOp::setParams(const std::string params)
00159 {
00160 ParamSet ps(params);
00161
00162 ps("color_is_vector", _color_is_vector);
00163 ps("secondary_color_is_vector", _secondary_color_is_vector);
00164 ps("texcoord_is_vector", _texcoord0_is_vector);
00165 ps("texcoord0_is_vector", _texcoord0_is_vector);
00166 ps("texcoord1_is_vector", _texcoord1_is_vector);
00167 ps("texcoord2_is_vector", _texcoord2_is_vector);
00168 ps("texcoord3_is_vector", _texcoord3_is_vector);
00169
00170 std::string out = ps.getUnusedParams();
00171 if(out.length())
00172 {
00173 FWARNING(("MergeGraphOp doesn't have parameters '%s'.\n",
00174 out.c_str()));
00175 }
00176 }
00177
00178 std::string MergeGraphOp::usage(void)
00179 {
00180 return
00181 "Merge: merge all geometries in a subtree\n"
00182 " Tries to merge all Geometries in a subtree into the minimal number.\n"
00183 " of Nodes. Flattens Transformations and transforms indices on the way.\n"
00184 "Params: name (type, default)\n"
00185 " (The following params are useful for transforming tangent space vectors.)\n"
00186 " color_is_vector (bool, false): transform color as if it were a normal\n"
00187 " secondary_color_is_vector (bool, false): transform secondary color as if it were a normal\n"
00188 " texcoord_is_vector (bool, false): transform texcoord0 as if it were a normal\n"
00189 " texcoord0_is_vector (bool, false): transform texcoord0 as if it were a normal\n"
00190 " texcoord1_is_vector (bool, false): transform texcoord1 as if it were a normal\n"
00191 " texcoord2_is_vector (bool, false): transform texcoord2 as if it were a normal\n"
00192 " texcoord3_is_vector (bool, false): transform texcoord3 as if it were a normal\n"
00193 ;
00194 }
00195
00196
00197
00198
00199
00200 bool MergeGraphOp::mergeOnce(Node * node)
00201 {
00202 std::list<Node const *> tempList;
00203 tempList.clear();
00204 tempList.splice(tempList.end(),_excludeListNodes);
00205 makeExcludeList(node);
00206 bool result = GraphOp::traverse(node);
00207 _excludeListNodes.clear();
00208 _excludeListNodes.splice(_excludeListNodes.end(),tempList);
00209 return result;
00210 }
00211
00212 void MergeGraphOp::makeExcludeList(Node * node)
00213 {
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 ::traverse(node,
00225 boost::bind(&MergeGraphOp::excludeListEnter, this, _1 ),
00226 boost::bind(&MergeGraphOp::excludeListLeave, this, _1, _2) );
00227 }
00228
00229
00230 Action::ResultE MergeGraphOp::excludeListEnter(Node * const node)
00231 {
00232
00233 return Action::Continue;
00234 }
00235
00236 Action::ResultE MergeGraphOp::excludeListLeave(Node * const node, Action::ResultE res)
00237 {
00238 DirectionalLight *dlight = dynamic_cast<DirectionalLight *>(node->getCore());
00239 if (dlight!=NULL)
00240 addToExcludeList(dlight->getBeacon());
00241
00242 Light *light = dynamic_cast<Light *>(node->getCore());
00243 if (light!=NULL)
00244 addToExcludeList(light->getBeacon());
00245
00246 PointLight *plight = dynamic_cast<PointLight *>(node->getCore());
00247 if (plight!=NULL)
00248 addToExcludeList(plight->getBeacon());
00249
00250 SpotLight *slight = dynamic_cast<SpotLight *>(node->getCore());
00251 if (slight!=NULL)
00252 addToExcludeList(slight->getBeacon());
00253
00254 return res;
00255 }
00256
00257 Action::ResultE MergeGraphOp::traverseEnter(Node * const node)
00258 {
00259 Switch *switch_ = dynamic_cast<Switch *>(node->getCore());
00260 if (switch_!=NULL) return Action::Skip;
00261
00262 DistanceLOD *dlod = dynamic_cast<DistanceLOD *>(node->getCore());
00263 if (dlod!=NULL) return Action::Skip;
00264
00265
00266 if (isLeaf(node)) return Action::Skip;
00267
00268 return Action::Continue;
00269 }
00270
00271 Action::ResultE MergeGraphOp::traverseLeave(Node * const node, Action::ResultE res)
00272 {
00273 processGroups(node);
00274 processTransformations(node);
00275 processGeometries(node);
00276 return res;
00277 }
00278
00279 bool MergeGraphOp::isLeaf(Node * const node)
00280 {
00281 if (node->getMFChildren()->begin() ==
00282 node->getMFChildren()->end ()) return true;
00283 else return false;
00284 }
00285
00288 bool MergeGraphOp::isGroup(Node * const node)
00289 {
00290 if( node->getCore()->getType().isDerivedFrom( Group::getClassType() ) &&
00291 !node->getCore()->getType().isDerivedFrom( Transform::getClassType() ) &&
00292 !node->getCore()->getType().isDerivedFrom( ComponentTransform::getClassType() ) &&
00293 !node->getCore()->getType().isDerivedFrom( Switch::getClassType() ) &&
00294 !node->getCore()->getType().isDerivedFrom( MaterialGroup::getClassType() ) &&
00295 !node->getCore()->getType().isDerivedFrom( DistanceLOD::getClassType() ) &&
00296 !node->getCore()->getType().isDerivedFrom( Billboard::getClassType() ))
00297 return true;
00298 else return false;
00299 }
00300
00301 void MergeGraphOp::processGroups(Node * const node)
00302 {
00303 MFUnrecChildNodePtr::const_iterator mfit = node->getMFChildren()->begin();
00304 MFUnrecChildNodePtr::const_iterator mfen = node->getMFChildren()->end ();
00305 std::vector<Node *> toAdd;
00306 std::vector<Node *> toSub;
00307
00308 for ( ; mfit != mfen; ++mfit )
00309 {
00310 bool special=isInExcludeList(*mfit);
00311 bool leaf=isLeaf(*mfit);
00312
00313 if (isGroup(*mfit))
00314 {
00315 if (!leaf && !special)
00316 {
00317 MFUnrecChildNodePtr::const_iterator it2 =
00318 (*mfit)->getMFChildren()->begin();
00319 MFUnrecChildNodePtr::const_iterator en2 =
00320 (*mfit)->getMFChildren()->end ();
00321
00322 for ( ; it2 != en2; ++it2 )
00323 {
00324 toAdd.push_back(*it2);
00325 }
00326 }
00327
00328 if (!special)
00329 {
00330 toSub.push_back(*mfit);
00331 continue;
00332 }
00333
00334 if (leaf && special)
00335 {
00336
00337 }
00338 if (!leaf && special)
00339 {
00340
00341 }
00342 continue;
00343 }
00344 else if ((*mfit)->getCore()->getType().isDerivedFrom(
00345 MaterialGroup::getClassType() ))
00346 {
00347 MaterialGroup *mg =
00348 dynamic_cast<MaterialGroup *>((*mfit)->getCore());
00349
00350 MFUnrecChildNodePtr::const_iterator it2 =
00351 (*mfit)->getMFChildren()->begin();
00352 MFUnrecChildNodePtr::const_iterator en2 =
00353 (*mfit)->getMFChildren()->end ();
00354
00355 bool empty=true;
00356
00357 for ( ; it2 != en2; ++it2 )
00358 {
00359 if (!isInExcludeList(*it2))
00360 {
00361
00362 if ((*it2)->getCore()->getType().isDerivedFrom(
00363 Geometry::getClassType()))
00364 {
00365 if(!isLeaf(*it2))
00366 {
00367
00368 empty=false;
00369 }
00370 else
00371 {
00372
00373 Geometry *geo =
00374 dynamic_cast<Geometry *>((*it2)->getCore());
00375
00376 geo->setMaterial(mg->getMaterial());
00377
00378 toAdd.push_back(*it2);
00379 }
00380 }
00381 else
00382 {
00383 empty=false;
00384 }
00385 }
00386 else
00387 {
00388 empty=false;
00389 }
00390 }
00391
00392 if (empty)
00393 toSub.push_back(*mfit);
00394 }
00395 }
00396
00397 std::vector<Node *>::const_iterator vit = toAdd.begin();
00398 std::vector<Node *>::const_iterator ven = toAdd.end ();
00399
00400 for ( ; vit != ven; ++vit )
00401 {
00402 node->addChild(*vit);
00403 }
00404
00405 vit = toSub.begin();
00406 ven = toSub.end ();
00407
00408 for ( ; vit != ven; ++vit )
00409 {
00410 node->subChild(*vit);
00411 }
00412 }
00413
00414 void MergeGraphOp::processTransformations(Node * const node)
00415 {
00416 MFUnrecChildNodePtr::const_iterator mfit = node->getMFChildren()->begin();
00417 MFUnrecChildNodePtr::const_iterator mfen = node->getMFChildren()->end ();
00418 std::vector<Node *> toAdd;
00419 std::vector<Node *> toSub;
00420
00421 for ( ; mfit != mfen; ++mfit )
00422 {
00423 bool special=isInExcludeList(*mfit);
00424 bool leaf=isLeaf(*mfit);
00425 bool empty=true;
00426
00427
00428 if ((*mfit)->getCore()->getType().isDerivedFrom(
00429 Transform::getClassType()))
00430 {
00431 if (!leaf && !special)
00432 {
00433
00434
00435
00436 MFUnrecChildNodePtr::const_iterator it2 =
00437 (*mfit)->getMFChildren()->begin();
00438 MFUnrecChildNodePtr::const_iterator en2 =
00439 (*mfit)->getMFChildren()->end ();
00440
00441 for ( ; it2 != en2; ++it2 )
00442 {
00443 if (!isInExcludeList(*it2))
00444 {
00445
00446 if ((*it2)->getCore()->getType().isDerivedFrom(
00447 Geometry::getClassType()))
00448 {
00449 if(!isLeaf(*it2))
00450 {
00451
00452 empty=false;
00453 }
00454 else
00455 {
00456
00457 Geometry *geo_old =
00458 dynamic_cast<Geometry *>(
00459 (*it2)->getCore());
00460
00461 GeometryUnrecPtr geo =
00462 dynamic_pointer_cast<Geometry>(
00463 OSG::deepClone(geo_old, "Material"));
00464
00465 Transform *t =
00466 dynamic_cast<Transform *>(
00467 (*mfit)->getCore());
00468
00469 GeoPnt3fProperty *pos = dynamic_cast<GeoPnt3fProperty *>(geo->getPositions());
00470 GeoVec3fProperty *norm = dynamic_cast<GeoVec3fProperty *>(geo->getNormals());
00471 GeoColor3fProperty *color = dynamic_cast<GeoColor3fProperty *>(geo->getColors());
00472 GeoColor3fProperty *scolor = dynamic_cast<GeoColor3fProperty *>(geo->getSecondaryColors());
00473 GeoVec3fProperty *texcoord0 = dynamic_cast<GeoVec3fProperty *>(geo->getTexCoords());
00474 GeoVec3fProperty *texcoord1 = dynamic_cast<GeoVec3fProperty *>(geo->getTexCoords1());
00475 GeoVec3fProperty *texcoord2 = dynamic_cast<GeoVec3fProperty *>(geo->getTexCoords2());
00476 GeoVec3fProperty * texcoord3 = dynamic_cast<GeoVec3fProperty *>(geo->getTexCoords3());
00477
00478 Matrix m=t->getMatrix();
00479
00480 if (pos!=NULL)
00481 {
00482 for (UInt32 i=0; i<pos->getSize(); i++)
00483 {
00484 Pnt3f p=pos->getValue(i);
00485 m.multFull(p, p);
00486 pos->setValue(p,i);
00487 }
00488 }
00489
00490 if (norm!=NULL)
00491 {
00492 for (UInt32 i=0; i<norm->getSize(); i++)
00493 {
00494 Vec3f n=norm->getValue(i);
00495 m.mult(n, n);
00496 n.normalize();
00497 norm->setValue(n,i);
00498 }
00499 }
00500
00501 if (color!=NULL && _color_is_vector)
00502 {
00503 for (UInt32 i=0; i<color->getSize(); i++)
00504 {
00505 Color3f c = color->getValue(i);
00506 Vec3f v;
00507 v.setValue(c.getValuesRGB());
00508 m.mult(v, v);
00509 v.normalize();
00510 c.setValuesRGB(v[0], v[1], v[2]);
00511 color->setValue(c,i);
00512 }
00513 }
00514
00515 if (scolor!=NULL && _secondary_color_is_vector)
00516 {
00517 for (UInt32 i=0; i<scolor->getSize(); i++)
00518 {
00519 Color3f c = scolor->getValue(i);
00520 Vec3f v;
00521 v.setValue(c.getValuesRGB());
00522 m.mult(v, v);
00523 v.normalize();
00524 c.setValuesRGB(v[0], v[1], v[2]);
00525 scolor->setValue(c,i);
00526 }
00527 }
00528
00529 if (texcoord0!=NULL && _texcoord0_is_vector)
00530 {
00531 for (UInt32 i=0; i<texcoord0->getSize(); i++)
00532 {
00533 Vec3f v=texcoord0->getValue(i);
00534 m.mult(v, v);
00535 v.normalize();
00536 texcoord0->setValue(v,i);
00537 }
00538 }
00539
00540 if (texcoord1!=NULL && _texcoord1_is_vector)
00541 {
00542 for (UInt32 i=0; i<texcoord1->getSize(); i++)
00543 {
00544 Vec3f v=texcoord1->getValue(i);
00545 m.mult(v, v);
00546 v.normalize();
00547 texcoord1->setValue(v,i);
00548 }
00549 }
00550
00551 if (texcoord2!=NULL && _texcoord2_is_vector)
00552 {
00553 for (UInt32 i=0; i<texcoord2->getSize(); i++)
00554 {
00555 Vec3f v=texcoord2->getValue(i);
00556 m.mult(v, v);
00557 v.normalize();
00558 texcoord2->setValue(v,i);
00559 }
00560 }
00561
00562 if (texcoord3!=NULL && _texcoord3_is_vector)
00563 {
00564 for (UInt32 i=0; i<texcoord3->getSize(); i++)
00565 {
00566 Vec3f v=texcoord3->getValue(i);
00567 m.mult(v, v);
00568 v.normalize();
00569 texcoord3->setValue(v,i);
00570 }
00571 }
00572 (*it2)->setCore(geo);
00573 toAdd.push_back(*it2);
00574 }
00575 } else empty=false;
00576 } else empty=false;
00577 }
00578 }
00579
00580
00581 if ((empty||leaf) && !special)
00582 {
00583 toSub.push_back(*mfit);
00584 continue;
00585 }
00586
00587 if (leaf && special)
00588 {
00589
00590 }
00591 if (!leaf && special)
00592 {
00593
00594 }
00595 continue;
00596 }
00597 }
00598
00599 std::vector<Node *>::const_iterator vit = toAdd.begin();
00600 std::vector<Node *>::const_iterator ven = toAdd.end ();
00601
00602 for ( ; vit != ven; ++vit )
00603 {
00604 node->addChild(*vit);
00605 }
00606
00607 vit = toSub.begin();
00608 ven = toSub.end ();
00609
00610 for ( ; vit != ven; ++vit )
00611 {
00612 node->subChild(*vit);
00613 }
00614 }
00615
00616 void MergeGraphOp::processGeometries(Node * const node)
00617 {
00618 MFUnrecChildNodePtr::const_iterator mfit = node->getMFChildren()->begin();
00619 MFUnrecChildNodePtr::const_iterator mfen = node->getMFChildren()->end ();
00620
00621 std::vector<Node *> toSub;
00622 std::vector<NodeUnrecPtr > toAdd;
00623
00624 for ( ; mfit != mfen; ++mfit )
00625 {
00626 bool special=isInExcludeList(*mfit);
00627
00628 if ((*mfit)->getCore()->getType().isDerivedFrom(
00629 Geometry::getClassType()))
00630 {
00631 #ifndef OSG2_MERGE_MISSING
00632 Geometry *geo = dynamic_cast<Geometry *>((*mfit)->getCore());
00633 #endif
00634
00635
00636
00637
00638 bool inSubList=false;
00639
00640 std::vector<Node *>::const_iterator it3=toSub.begin();
00641 std::vector<Node *>::const_iterator en3=toSub.end();
00642
00643 for ( ; it3 != en3; ++it3 )
00644 if (*it3==*mfit) { inSubList=true; break; }
00645
00646 if (!special && !inSubList)
00647 {
00648
00649 MFUnrecChildNodePtr::const_iterator it2=mfit+1;
00650 Geometry *new_geo=NULL;
00651 for ( ; it2!=mfen; ++it2)
00652 {
00653 if (!isInExcludeList(*it2) && (*it2)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00654 {
00655 #ifndef OSG2_MERGE_MISSING
00656 Geometry *geo2 = dynamic_cast<Geometry *>((*it2)->getCore());
00657 if (geo->isMergeable(geo2))
00658 {
00659
00660 if(geo->getIndices() == NULL)
00661 OSG::createSharedIndex(geo);
00662 if(geo2->getIndices() == NULL)
00663 OSG::createSharedIndex(geo2);
00664 if (new_geo==NULL)
00665 {
00666 new_geo=Geometry::create();
00667 if (new_geo->merge(geo))
00668 toSub.push_back(*it);
00669 else FWARNING(("MergeGraphOp: processGeometries problem 1\n"));
00670
00671 if (new_geo->merge(geo2))
00672 toSub.push_back(*it2);
00673 else FWARNING(("MergeGraphOp: processGeometries problem 2\n"));
00674 }
00675 else
00676 {
00677 if (new_geo->merge(geo2))
00678 toSub.push_back(*it2);
00679 }
00680 }
00681 #endif
00682 }
00683 }
00684 if (new_geo!=NULL)
00685 {
00686 NodeUnrecPtr new_node=Node::create();
00687 new_node->setCore(new_geo);
00688
00689 toAdd.push_back(new_node);
00690 }
00691 }
00692 else
00693 {
00694
00695 }
00696 }
00697 }
00698
00699 std::vector<NodeUnrecPtr>::const_iterator ait = toAdd.begin();
00700 std::vector<NodeUnrecPtr>::const_iterator aen = toAdd.end ();
00701
00702 for ( ; ait != aen; ++ait )
00703 {
00704 node->addChild(*ait);
00705 }
00706
00707 std::vector<Node *>::const_iterator sit = toSub.begin();
00708 std::vector<Node *>::const_iterator sen = toSub.end ();
00709
00710 for ( ; sit != sen; ++sit )
00711 {
00712 node->subChild(*sit);
00713 }
00714 }