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

OSGMaterialMergeGraphOp.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 
00040 /***************************************************************************\
00041 *                             Includes                                    *
00042 \***************************************************************************/
00043 
00044 #include <OSGMaterialMergeGraphOp.h>
00045 
00046 OSG_USING_NAMESPACE
00047 
00048 /***************************************************************************\
00049  *                            Description                                  *
00050 \***************************************************************************/
00051 
00058 MaterialMergeGraphOp::MaterialMergeGraphOp(const char* name)
00059     : GraphOp(name)
00060 {
00061 }
00062 
00063 GraphOp* MaterialMergeGraphOp::create()
00064 {
00065     return new MaterialMergeGraphOp();
00066 }
00067 
00068 
00069 // Similar to boost's next iterator function.  (I think it's from
00070 // boost, at least.)
00071 template<typename T>
00072 T next(T t) { // Iterator passed by value.
00073     ++t;
00074     return t;
00075 }
00076 
00077 
00078 bool isEqual(const osg::FieldContainerPtr& a, const osg::FieldContainerPtr& b)
00079 {
00080     using std::string;
00081 
00082     // Compare the pointers.
00083     if(a == b)
00084         return true;
00085 
00086     if(a == NullFC || b == NullFC)
00087         return false;
00088 
00089     if(a->getType() != b->getType())
00090         return false;
00091     
00092     //printf("comparing: %s\n", a->getType().getName().str());
00093     
00094     const FieldContainerType &type = a->getType();
00095     UInt32 fcount = type.getNumFieldDescs();
00096     
00097     for(UInt32 i=1;i <= fcount;++i)
00098     {
00099         const FieldDescription* fdesc = type.getFieldDescription(i);
00100     
00101         if(fdesc->isInternal())
00102             continue;
00103     
00104         // ignore attachments
00105         if(strcmp(fdesc->getCName(), "attachments") == 0)
00106             continue;
00107     
00108         Field *a_field = a->getField(i);
00109         Field *b_field = b->getField(i);
00110     
00111         const FieldType &a_ftype = a_field->getType();
00112         const FieldType &b_ftype = b_field->getType();
00113     
00114         //printf("comparing field %s\n", a_ftype.getCName());
00115     
00116         if(a_ftype != b_ftype)
00117             return false;
00118     
00119         if(strstr(a_ftype.getCName(), "Ptr") == NULL)
00120         {
00121             // This would be nice but there is no virtual compare method :-(
00122             // if(*a_field != *b_field)
00123             //     return false;
00124     
00125             // This is very slow with multi fields!!!!
00126             string av, bv;
00127             a_field->getValueByStr(av);
00128             b_field->getValueByStr(bv);
00129             if(av != bv)
00130                 return false;
00131         }
00132         else
00133         {
00134             if(a_field->getCardinality() == FieldType::SINGLE_FIELD)
00135             {
00136                 if(!isEqual(((SFFieldContainerPtr *) a_field)->getValue(),
00137                             ((SFFieldContainerPtr *) b_field)->getValue()))
00138                     return false;
00139             }
00140             else if(a_field->getCardinality() == FieldType::MULTI_FIELD)
00141             {
00142                 if(((MFFieldContainerPtr*)a_field)->size() !=
00143                    ((MFFieldContainerPtr*)b_field)->size())
00144                     return false;
00145     
00146                 for(UInt32 j=0;j < ((MFFieldContainerPtr*)a_field)->size();++j)
00147                 {
00148                     if(!isEqual((*(((MFFieldContainerPtr *)a_field)))[j],
00149                                 (*(((MFFieldContainerPtr *)b_field)))[j]))
00150                         return false;
00151                 }
00152             }
00153         }
00154     }
00155     return true;
00156 }
00157 
00158 
00159 bool equal(MaterialPtr a, MaterialPtr b) {
00160     // It's too bad Material::operator== doesn't work.
00161     //return *a == *b;
00162     return isEqual(a, b);
00163 }
00164 
00165 
00166 bool MaterialMergeGraphOp::traverse(NodePtr& node)
00167 {
00168     // Find the materials.
00169     if (!GraphOp::traverse(node)) {
00170         return false;
00171     }
00172 
00173     SINFO << "Number of materials before merge: " << _materialObjects.size() << std::endl;
00174 
00175     // Now do the merge.
00176     MaterialObjectMap::iterator itr = _materialObjects.begin();
00177     for (; itr != _materialObjects.end(); ++itr)
00178     {
00179         MaterialPtr current = itr->first;
00180         MaterialObjectList& currentList = itr->second;
00181 
00182         MaterialObjectMap::iterator walker = next(itr);
00183         while (walker != _materialObjects.end()) {
00184             // Store the next iterator in case we have to delete
00185             // 'walker' from the map.
00186             MaterialObjectMap::iterator nextStep = next(walker);
00187 
00188             if (equal(current, walker->first)) {
00189                 // Set the new objects to have the current material,
00190                 // and move the objects to the current list.
00191                 MaterialObjectList::iterator i = walker->second.begin();
00192                 for (; i != walker->second.end(); ++i) {
00193                     i->setMaterial(current);
00194                     currentList.push_back(*i);
00195                 }
00196                 _materialObjects.erase(walker);
00197             }
00198 
00199             walker = nextStep;
00200         }
00201     }
00202 
00203     SINFO << "Number of materials after merge: " << _materialObjects.size() << std::endl;
00204     return true;
00205 }
00206 
00207 
00208 void MaterialMergeGraphOp::setParams(const std::string params)
00209 {
00210     ParamSet ps(params);   
00211     
00212     std::string out = ps.getUnusedParams();
00213     if(out.length())
00214     {
00215         FWARNING(("MaterialMergeGraphOp doesn't have parameters '%s'.\n",
00216                 out.c_str()));
00217     }
00218 }
00219 
00220 std::string MaterialMergeGraphOp::usage(void)
00221 {
00222     return 
00223     "MaterialMerge: merge Materials in given subtree\n"
00224     "  Tries to find and merge equiavlent Materials to reduce the number\n"
00225     "  of Materials used.\n"
00226     ;
00227 }
00228 
00229 Action::ResultE MaterialMergeGraphOp::traverseEnter(NodePtr& node)
00230 {
00231     GeometryPtr geo = GeometryPtr::dcast(node->getCore());
00232     if (geo != NullFC)
00233     {
00234         addObject(MaterialObject(geo));
00235         return Action::Continue;
00236     }
00237     
00238     MaterialGroupPtr mg = MaterialGroupPtr::dcast(node->getCore());
00239     if (mg != NullFC)
00240     {
00241         addObject(MaterialObject(mg));
00242         return Action::Continue;
00243     }
00244 
00245     // Otherwise, keep looking.
00246     return Action::Continue;
00247 }
00248 
00249 Action::ResultE MaterialMergeGraphOp::traverseLeave(NodePtr& node, Action::ResultE res)
00250 {
00251     return res;
00252 }
00253 
00254 void MaterialMergeGraphOp::addObject(MaterialObject m)
00255 {
00256     MaterialPtr mat = m.getMaterial();
00257     if (mat == osg::NullFC)
00258         return;
00259 
00260     _materialObjects[mat].push_back(m);
00261 }

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