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 <OSGMergeGraphOp.h>
00046 #include <OSGDirectionalLight.h>
00047 #include <OSGSpotLight.h>
00048 #include <OSGLight.h>
00049 #include <OSGPointLight.h>
00050 #include <OSGSwitch.h>
00051 #include <OSGDistanceLOD.h>
00052 #include <OSGBillboard.h>
00053 #include <OSGMaterialGroup.h>
00054 #include <OSGComponentTransform.h>
00055 #include <OSGPrimitiveIterator.h>
00056 #include <OSGGeometry.h>
00057 #include <OSGGeoFunctions.h>
00058
00059 OSG_USING_NAMESPACE
00060
00061
00062
00063
00064
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 MergeGraphOp::MergeGraphOp(const char* name): GraphOp(name)
00084 {
00085 }
00086
00087 MergeGraphOp::~MergeGraphOp(void)
00088 {
00089 }
00090
00091 GraphOp* MergeGraphOp::create()
00092 {
00093 MergeGraphOp* inst = new MergeGraphOp();
00094 return inst;
00095 }
00096
00097 UInt32 countNodes(const NodePtr& node)
00098 {
00099 if (node == NullFC)
00100 return 0;
00101
00102 UInt32 total = 1;
00103 for (UInt32 i = 0; i < node->getNChildren(); ++i)
00104 total += countNodes(node->getChild(i));
00105 return total;
00106 }
00107
00108 bool MergeGraphOp::traverse(NodePtr& node)
00109 {
00110
00111
00112
00113 UInt32 next = countNodes(node);
00114 SINFO << "MergeGraphOp::traverse: Number of nodes before merge: "
00115 << next << endLog;
00116 bool result = true;
00117 UInt32 current;
00118 do {
00119 current = next;
00120 result &= mergeOnce(node);
00121 if (!result)
00122 break;
00123 next = countNodes(node);
00124 } while (next < current);
00125
00126 SINFO << "MergeGraphOp::traverse: Number of nodes after merge: "
00127 << current << endLog;
00128
00129 return result;
00130 }
00131
00132 void MergeGraphOp::setParams(const std::string params)
00133 {
00134 ParamSet ps(params);
00135
00136 std::string out = ps.getUnusedParams();
00137 if(out.length())
00138 {
00139 FWARNING(("MergeGraphOp doesn't have parameters '%s'.\n",
00140 out.c_str()));
00141 }
00142 }
00143
00144 std::string MergeGraphOp::usage(void)
00145 {
00146 return
00147 "Merge: merge all geometries in a subtree\n"
00148 " Tries to merge all Geometries in a subtree into the minimal number.\n"
00149 " of Nodes. Flattens Transformations and transforms indices on the way.\n"
00150 ;
00151 }
00152
00153
00154
00155
00156
00157 bool MergeGraphOp::mergeOnce(NodePtr& node)
00158 {
00159 std::list<NodePtr> tempList;
00160 tempList.clear();
00161 tempList.splice(tempList.end(),_excludeListNodes);
00162 makeExcludeList(node);
00163 bool result = GraphOp::traverse(node);
00164 _excludeListNodes.clear();
00165 _excludeListNodes.splice(_excludeListNodes.end(),tempList);
00166 return result;
00167 }
00168
00169 void MergeGraphOp::makeExcludeList(NodePtr& node)
00170 {
00171 ::traverse(node,
00172 osgTypedMethodFunctor1ObjPtrCPtrRef<Action::ResultE,
00173 MergeGraphOp,
00174 NodePtr>(this,&MergeGraphOp::excludeListEnter),
00175 osgTypedMethodFunctor2ObjPtrCPtrRef<Action::ResultE,
00176 MergeGraphOp,
00177 NodePtr,
00178 Action::ResultE>(this,&MergeGraphOp::excludeListLeave));
00179 }
00180
00181
00182 Action::ResultE MergeGraphOp::excludeListEnter(NodePtr& node)
00183 {
00184 if (node==NullFC) ; else ;
00185 return Action::Continue;
00186 }
00187
00188 Action::ResultE MergeGraphOp::excludeListLeave(NodePtr& node, Action::ResultE res)
00189 {
00190 DirectionalLightPtr dlight = DirectionalLightPtr::dcast(node->getCore());
00191 if (dlight!=NullFC)
00192 addToExcludeList(dlight->getBeacon());
00193
00194 LightPtr light = LightPtr::dcast(node->getCore());
00195 if (light!=NullFC)
00196 addToExcludeList(light->getBeacon());
00197
00198 PointLightPtr plight = PointLightPtr::dcast(node->getCore());
00199 if (plight!=NullFC)
00200 addToExcludeList(plight->getBeacon());
00201
00202 SpotLightPtr slight = SpotLightPtr::dcast(node->getCore());
00203 if (slight!=NullFC)
00204 addToExcludeList(slight->getBeacon());
00205
00206 return res;
00207 }
00208
00209 Action::ResultE MergeGraphOp::traverseEnter(NodePtr& node)
00210 {
00211 SwitchPtr switch_ = SwitchPtr::dcast(node->getCore());
00212 if (switch_!=NullFC) return Action::Skip;
00213
00214 DistanceLODPtr dlod = DistanceLODPtr::dcast(node->getCore());
00215 if (dlod!=NullFC) return Action::Skip;
00216
00217
00218 if (isLeaf(node)) return Action::Skip;
00219
00220 return Action::Continue;
00221 }
00222
00223 Action::ResultE MergeGraphOp::traverseLeave(NodePtr& node, Action::ResultE res)
00224 {
00225 processGroups(node);
00226 processTransformations(node);
00227 processGeometries(node);
00228 return res;
00229 }
00230
00231 bool MergeGraphOp::isLeaf(NodePtr& node)
00232 {
00233 if (node->getMFChildren()->getValues().begin()==
00234 node->getMFChildren()->getValues().end()) return true;
00235 else return false;
00236 }
00237
00240 bool MergeGraphOp::isGroup(NodePtr& node)
00241 {
00242 if( node->getCore()->getType().isDerivedFrom( Group::getClassType() ) &&
00243 !node->getCore()->getType().isDerivedFrom( Transform::getClassType() ) &&
00244 !node->getCore()->getType().isDerivedFrom( ComponentTransform::getClassType() ) &&
00245 !node->getCore()->getType().isDerivedFrom( Switch::getClassType() ) &&
00246 !node->getCore()->getType().isDerivedFrom( MaterialGroup::getClassType() ) &&
00247 !node->getCore()->getType().isDerivedFrom( DistanceLOD::getClassType() ) &&
00248 !node->getCore()->getType().isDerivedFrom( Billboard::getClassType() ))
00249 return true;
00250 else return false;
00251 }
00252
00253 void MergeGraphOp::processGroups(NodePtr& node)
00254 {
00255 std::vector<NodePtr>::iterator it = node->getMFChildren()->getValues().begin();
00256 std::vector<NodePtr>::iterator en = node->getMFChildren()->getValues().end ();
00257 std::vector<NodePtr> toAdd;
00258 std::vector<NodePtr> toSub;
00259
00260 for ( ; it != en; ++it )
00261 {
00262 bool special=isInExcludeList(*it);
00263 bool leaf=isLeaf(*it);
00264
00265 if (isGroup(*it))
00266 {
00267 if (!leaf && !special)
00268 {
00269 std::vector<NodePtr>::iterator it2 = (*it)->getMFChildren()->getValues().begin();
00270 std::vector<NodePtr>::iterator en2 = (*it)->getMFChildren()->getValues().end ();
00271
00272 for ( ; it2 != en2; ++it2 )
00273 {
00274 toAdd.push_back(*it2);
00275 }
00276 }
00277
00278 if (!special)
00279 {
00280 toSub.push_back(*it);
00281 continue;
00282 }
00283
00284 if (leaf && special)
00285 {
00286
00287 }
00288 if (!leaf && special)
00289 {
00290
00291 }
00292 continue;
00293 }
00294 else if ((*it)->getCore()->getType().isDerivedFrom( MaterialGroup::getClassType() ))
00295 {
00296 MaterialGroupPtr mg=MaterialGroupPtr::dcast((*it)->getCore());
00297
00298 std::vector<NodePtr>::iterator it2 = (*it)->getMFChildren()->getValues().begin();
00299 std::vector<NodePtr>::iterator en2 = (*it)->getMFChildren()->getValues().end ();
00300
00301 bool empty=true;
00302
00303 for ( ; it2 != en2; ++it2 )
00304 {
00305 if (!isInExcludeList(*it2))
00306 {
00307
00308 if ((*it2)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00309 {
00310 if(!isLeaf(*it2))
00311 {
00312
00313 empty=false;
00314 }
00315 else
00316 {
00317
00318 GeometryPtr geo = GeometryPtr::dcast((*it2)->getCore());
00319 beginEditCP(geo);
00320 geo->setMaterial(mg->getMaterial());
00321 endEditCP(geo);
00322 toAdd.push_back(*it2);
00323 }
00324 } else empty=false;
00325 } else empty=false;
00326 }
00327
00328 if (empty) toSub.push_back(*it);
00329
00330 }
00331 }
00332
00333 it = toAdd.begin();
00334 en = toAdd.end ();
00335
00336 for ( ; it != en; ++it )
00337 {
00338 beginEditCP(node, Node::ChildrenFieldMask);
00339 node->addChild(*it);
00340 endEditCP (node, Node::ChildrenFieldMask);
00341 }
00342
00343 it = toSub.begin();
00344 en = toSub.end ();
00345
00346 for ( ; it != en; ++it )
00347 {
00348 beginEditCP(node, Node::ChildrenFieldMask);
00349 node->subChild(*it);
00350 endEditCP (node, Node::ChildrenFieldMask);
00351 }
00352 }
00353
00354 void MergeGraphOp::processTransformations(NodePtr& node)
00355 {
00356 std::vector<NodePtr>::iterator it = node->getMFChildren()->getValues().begin();
00357 std::vector<NodePtr>::iterator en = node->getMFChildren()->getValues().end ();
00358 std::vector<NodePtr> toAdd;
00359 std::vector<NodePtr> toSub;
00360
00361 for ( ; it != en; ++it )
00362 {
00363 bool special=isInExcludeList(*it);
00364 bool leaf=isLeaf(*it);
00365 bool empty=true;
00366
00367
00368 if ((*it)->getCore()->getType().isDerivedFrom(Transform::getClassType()))
00369 {
00370 if (!leaf && !special)
00371 {
00372
00373
00374
00375 std::vector<NodePtr>::iterator it2 = (*it)->getMFChildren()->getValues().begin();
00376 std::vector<NodePtr>::iterator en2 = (*it)->getMFChildren()->getValues().end ();
00377
00378 for ( ; it2 != en2; ++it2 )
00379 {
00380 if (!isInExcludeList(*it2))
00381 {
00382
00383 if ((*it2)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00384 {
00385 if(!isLeaf(*it2))
00386 {
00387
00388 empty=false;
00389 }
00390 else
00391 {
00392
00393 GeometryPtr geo_old = GeometryPtr::dcast((*it2)->getCore());
00394 GeometryPtr geo = geo_old->clone();
00395 TransformPtr t = TransformPtr::dcast((*it)->getCore());
00396 GeoPositionsPtr pos = geo->getPositions();
00397 GeoNormalsPtr norm = geo->getNormals();
00398 Matrix m=t->getMatrix();
00399 if (pos!=NullFC)
00400 {
00401 beginEditCP( pos );
00402 for (UInt32 i=0; i<pos->getSize(); i++)
00403 {
00404 Pnt3f p=pos->getValue(i);
00405 m.multFullMatrixPnt(p);
00406 pos->setValue(p,i);
00407 }
00408 endEditCP( pos );
00409 }
00410
00411 if (norm!=NullFC)
00412 {
00413 beginEditCP( norm );
00414 for (UInt32 i=0; i<norm->getSize(); i++)
00415 {
00416 Vec3f n=norm->getValue(i);
00417 m.multMatrixVec(n);
00418 n.normalize();
00419 norm->setValue(n,i);
00420 }
00421 endEditCP( norm );
00422 }
00423 beginEditCP(*it2);
00424 (*it2)->setCore(geo);
00425 endEditCP(*it2);
00426 toAdd.push_back(*it2);
00427 }
00428 } else empty=false;
00429 } else empty=false;
00430 }
00431 }
00432
00433
00434 if ((empty||leaf) && !special)
00435 {
00436 toSub.push_back(*it);
00437 continue;
00438 }
00439
00440 if (leaf && special)
00441 {
00442
00443 }
00444 if (!leaf && special)
00445 {
00446
00447 }
00448 continue;
00449 }
00450 }
00451
00452 it = toAdd.begin();
00453 en = toAdd.end ();
00454
00455 for ( ; it != en; ++it )
00456 {
00457 beginEditCP(node, Node::ChildrenFieldMask);
00458 node->addChild(*it);
00459 endEditCP (node, Node::ChildrenFieldMask);
00460 }
00461
00462 it = toSub.begin();
00463 en = toSub.end ();
00464
00465 for ( ; it != en; ++it )
00466 {
00467 beginEditCP(node, Node::ChildrenFieldMask);
00468 node->subChild(*it);
00469 endEditCP (node, Node::ChildrenFieldMask);
00470 }
00471 }
00472
00473 void MergeGraphOp::processGeometries(NodePtr& node)
00474 {
00475 std::vector<NodePtr>::iterator it = node->getMFChildren()->getValues().begin();
00476 std::vector<NodePtr>::iterator en = node->getMFChildren()->getValues().end ();
00477 std::vector<NodePtr> toSub;
00478 std::vector<NodePtr> toAdd;
00479
00480 for ( ; it != en; ++it )
00481 {
00482 bool special=isInExcludeList(*it);
00483
00484 if ((*it)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00485 {
00486 GeometryPtr geo = GeometryPtr::dcast((*it)->getCore());
00487
00488
00489
00490
00491 bool inSubList=false;
00492
00493 std::vector<NodePtr>::iterator it3=toSub.begin();
00494 std::vector<NodePtr>::iterator en3=toSub.end();
00495
00496 for ( ; it3 != en3; ++it3 )
00497 if (*it3==*it) { inSubList=true; break; }
00498
00499 if (!special && !inSubList)
00500 {
00501
00502 std::vector<NodePtr>::iterator it2=it+1;
00503 GeometryPtr new_geo=NullFC;
00504 for ( ; it2!=en; ++it2)
00505 {
00506 if (!isInExcludeList(*it2) && (*it2)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00507 {
00508 GeometryPtr geo2 = GeometryPtr::dcast((*it2)->getCore());
00509 if (geo->isMergeable(geo2))
00510 {
00511
00512 if(geo->getIndices() == NullFC)
00513 OSG::createSharedIndex(geo);
00514 if(geo2->getIndices() == NullFC)
00515 OSG::createSharedIndex(geo2);
00516 if (new_geo==NullFC)
00517 {
00518 new_geo=Geometry::create();
00519 if (new_geo->merge(geo))
00520 toSub.push_back(*it);
00521 else FWARNING(("MergeGraphOp: processGeometries problem 1\n"));
00522
00523 if (new_geo->merge(geo2))
00524 toSub.push_back(*it2);
00525 else FWARNING(("MergeGraphOp: processGeometries problem 2\n"));
00526 }
00527 else
00528 {
00529 if (new_geo->merge(geo2))
00530 toSub.push_back(*it2);
00531 }
00532 }
00533 }
00534 }
00535 if (new_geo!=NullFC)
00536 {
00537 NodePtr new_node=Node::create();
00538 beginEditCP(new_node);
00539 new_node->setCore(new_geo);
00540 endEditCP (new_node);
00541
00542 toAdd.push_back(new_node);
00543 }
00544 }
00545 else
00546 {
00547
00548 }
00549 }
00550 }
00551
00552 it = toAdd.begin();
00553 en = toAdd.end ();
00554
00555 for ( ; it != en; ++it )
00556 {
00557 beginEditCP(node, Node::ChildrenFieldMask);
00558 node->addChild(*it);
00559 endEditCP (node, Node::ChildrenFieldMask);
00560 }
00561
00562 it = toSub.begin();
00563 en = toSub.end ();
00564
00565 for ( ; it != en; ++it )
00566 {
00567 beginEditCP(node, Node::ChildrenFieldMask);
00568 node->subChild(*it);
00569 endEditCP (node, Node::ChildrenFieldMask);
00570 }
00571 }