Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGMergeGraphOp.cpp

Go to the documentation of this file.
00001 
00002 /*---------------------------------------------------------------------------*\
00003  *                                OpenSG                                     *
00004  *                                                                           *
00005  *                                                                           *
00006  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00007  *                                                                           *
00008  *                            www.opensg.org                                 *
00009  *                                                                           *
00010  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00011  *                                                                           *
00012 \*---------------------------------------------------------------------------*/
00013 /*---------------------------------------------------------------------------*\
00014  *                                License                                    *
00015  *                                                                           *
00016  * This library is free software; you can redistribute it and/or modify it   *
00017  * under the terms of the GNU Library General Public License as published    *
00018  * by the Free Software Foundation, version 2.                               *
00019  *                                                                           *
00020  * This library is distributed in the hope that it will be useful, but       *
00021  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00023  * Library General Public License for more details.                          *
00024  *                                                                           *
00025  * You should have received a copy of the GNU Library General Public         *
00026  * License along with this library; if not, write to the Free Software       *
00027  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00028  *                                                                           *
00029 \*---------------------------------------------------------------------------*/
00030 /*---------------------------------------------------------------------------*\
00031  *                                Changes                                    *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037  *                                                                           *
00038 \*---------------------------------------------------------------------------*/
00039 
00040 
00041 /***************************************************************************\
00042 *                             Includes                                    *
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  *                            Description                                  *
00063 \***************************************************************************/
00064 
00072 /***************************************************************************\
00073  *                           Instance methods                              *
00074 \***************************************************************************/
00075 
00076 /*-------------------------------------------------------------------------*\
00077  -  public                                                                 -
00078 \*-------------------------------------------------------------------------*/
00079 
00080 
00081 /*------------- constructors & destructors --------------------------------*/
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     // This is a hack and should be treated as such.
00111     // The fact that it helps means there is something wrong with
00112     // the merger. FIXME!!!
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  -  private                                                                -
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     //leaf, don't enter, cause no job here
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                 //what to do?
00287             }
00288             if (!leaf && special)
00289             {
00290                 //what to do?
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                     //check if geometry
00308                     if ((*it2)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00309                     {
00310                         if(!isLeaf(*it2))
00311                         {
00312                             //hmm...bad tree...
00313                             empty=false;
00314                         }
00315                         else
00316                         {                                
00317                             //it is a leaf geometry, so apply the transformation
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         //if a transformation:
00368         if ((*it)->getCore()->getType().isDerivedFrom(Transform::getClassType()))
00369         {        
00370             if (!leaf && !special)
00371             {
00372                 //try to apply it to children geometries
00373                 //move all "moveable" children one level up
00374                 //if empty after that, delete it
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                         //check if geometry
00383                         if ((*it2)->getCore()->getType().isDerivedFrom(Geometry::getClassType()))
00384                         {
00385                             if(!isLeaf(*it2))
00386                             {
00387                                 //hmm...bad tree...
00388                                 empty=false;
00389                             }
00390                             else
00391                             {                                
00392                                 //it is a leaf geometry, so apply the transformation
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             //now check whether we have to remove it
00434             if ((empty||leaf) && !special)
00435             {
00436                 toSub.push_back(*it);
00437                 continue;
00438             }
00439             
00440             if (leaf && special)
00441             {
00442                 //what to do?
00443             }
00444             if (!leaf && special)
00445             {
00446                 //what to do?
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             //if a geometry, try to merge it in another geometry
00488             //if successfull, delete it.
00489             //check also if it is added for exclusion
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                 //ok, try
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                             // HACK merge crashes when indices == NullFC!
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                 //hmm...have to skip it
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 }

Generated on Thu Aug 25 04:07:47 2005 for OpenSG by  doxygen 1.4.3