OSGTransformPushGraphOp.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *                   Copyright (C) 2008 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 #include "OSGTransformPushGraphOp.h"
00040 #include "OSGGraphOpFactory.h"
00041 #include "OSGAction.h"
00042
00043 #include <set>
00044
00045 #include <boost/bind.hpp>
00046
00063 OSG_BEGIN_NAMESPACE
00064
00065 namespace
00066 {
00067     static bool registerOp(void)
00068     {
00069         GraphOpRefPtr newOp = TransformPushGraphOp::create();
00070
00071         GraphOpFactory::the()->registerOp(newOp);
00072         return true;
00073     }
00074
00075     static OSG::StaticInitFuncWrapper registerOpWrapper(registerOp);
00076 } // namespace
00077
00078 const char *TransformPushGraphOp::getClassname(void)
00079 {
00080     return "TransformPushGraphOp";
00081 }
00082
00083 TransformPushGraphOp::TransformPushGraphOp(const char* name)
00084     : Inherited(name)
00085 {
00086     // nothing to do
00087 }
00088
00089 TransformPushGraphOpTransitPtr
00090 TransformPushGraphOp::create(void)
00091 {
00092     return TransformPushGraphOpTransitPtr(new TransformPushGraphOp);
00093 }
00094
00095 GraphOpTransitPtr TransformPushGraphOp::clone(void)
00096 {
00097     return GraphOpTransitPtr(new TransformPushGraphOp);
00098 }
00099
00100 void TransformPushGraphOp::setParams(const std::string params)
00101 {
00102     ParamSet ps(params);
00103
00104     std::string out = ps.getUnusedParams();
00105     if(out.length())
00106     {
00107         FWARNING(("TransformPushGraphOp doesn't have parameters '%s'.\n",
00108                 out.c_str()));
00109     }
00110 }
00111
00112 std::string TransformPushGraphOp::usage(void)
00113 {
00114     return "TransformPush: Move Transform towards leafs of the scene.\n";
00115 }
00116
00117
00118 TransformPushGraphOp::~TransformPushGraphOp(void)
00119 {
00120     // nothing to do
00121 }
00122
00123
00124 Action::ResultE TransformPushGraphOp::traverseEnter(Node * const node)
00125 {
00126     if(isInExcludeList(node))
00127         return Action::Skip;
00128
00129     return Action::Continue;
00130 }
00131
00132 Action::ResultE TransformPushGraphOp::traverseLeave(
00133     Node * const node, Action::ResultE res)
00134 {
00135     if(isInExcludeList(node))
00136         return Action::Skip;
00137
00138     if(isInPreserveList(node))
00139         return Action::Continue;
00140
00141     Transform *trans = dynamic_cast<Transform *>(node->getCore());
00142
00143     if(trans == NULL)
00144         return Action::Continue;
00145
00146     // if not a leaf, search children recursively to find push targets
00147     if(!node->getMFChildren()->empty())
00148     {
00149         _pushPossible = true;
00150         _pushTargets.clear();
00151
00152         OSG::traverse(
00153                       *(node->getMFChildren()),
00154                         boost::bind(&TransformPushGraphOp::traverseTargetsEnter, this, _1));
00155
00156         if(_pushPossible == true)
00157         {
00158             // push transform into targets
00159             pushTransform(trans);
00160
00161             // replace transform with group
00162             GroupUnrecPtr replaceCore = Group::create();
00163             node->setCore(replaceCore);
00164         }
00165     }
00166
00167     return Action::Continue;
00168 }
00169
00172 Action::ResultE TransformPushGraphOp::traverseTargetsEnter(Node * const node)
00173 {
00174     NodeCore *core = node->getCore();
00175
00176     if(core == NULL)
00177     {
00178         // warn about broken subtree, but do not prevent push, just skip it
00179         FWARNING(("TransformPushGraphOp::traverseTargetsEnter: "
00180                   "Found node without core!\n"));
00181         return Action::Skip;
00182     }
00183
00184     if(isInExcludeList(node) || isInPreserveList(node))
00185     {
00186         // prevent the push as the transform can not be moved into this branch.
00187         _pushPossible = false;
00188
00189         return Action::Quit;
00190     }
00191
00192     if(core->getType().isDerivedFrom(Transform::getClassType()))
00193     {
00194         _pushTargets.push_back(node);
00195
00196         return Action::Skip;
00197     }
00198
00199     if(core->getType().isDerivedFrom(Geometry ::getClassType()))
00200     {
00201         Geometry *geo = dynamic_cast<Geometry *>(core);
00202
00203         if(geo != NULL && validTargetGeo(geo))
00204         {
00205             // found a push target in this branch, store it and stop searching
00206             _pushTargets.push_back(node);
00207
00208             return Action::Skip;
00209         }
00210         else
00211         {
00212             // prevent the push as the transform can not be moved into this branch.
00213             _pushPossible = false;
00214
00215             return Action::Quit;
00216         }
00217     }
00218
00219     if(core->getType().isDerivedFrom(Group::getClassType()))
00220     {
00221         // keep searching children for push targets
00222         return Action::Continue;
00223     }
00224
00225     // unknown core type, be conservative and prevent the push
00226     _pushPossible = false;
00227
00228     return Action::Quit;
00229 }
00230
00233 bool TransformPushGraphOp::validTargetGeo(const Geometry *geo)
00234 {
00235     bool returnValue = true;
00236
00237     const Geometry::MFPropertiesType           *mfProp  =
00238         geo->getMFProperties ();
00239     Geometry::MFPropertiesType::const_iterator  propIt  = mfProp->begin();
00240     Geometry::MFPropertiesType::const_iterator  propEnd = mfProp->end  ();
00241
00242     for(; propIt != propEnd; ++propIt)
00243     {
00244         if(*propIt != NULL && (*propIt)->getMFParents()->size() > 1)
00245         {
00246             returnValue = false;
00247             break;
00248         }
00249     }
00250
00251     return returnValue;
00252 }
00253
00254 void TransformPushGraphOp::pushTransform(const Transform *srcTrans)
00255 {
00256     PushTargetStore::iterator ptIt  = _pushTargets.begin();
00257     PushTargetStore::iterator ptEnd = _pushTargets.end  ();
00258
00259     for(; ptIt != ptEnd; ++ptIt)
00260     {
00261         Transform *dstTrans = dynamic_cast<Transform *>((*ptIt)->getCore());
00262         if(dstTrans != NULL)
00263         {
00264             pushToTransform(srcTrans, dstTrans);
00265             continue;
00266         }
00267
00268         Geometry *dstGeo = dynamic_cast<Geometry *>((*ptIt)->getCore());
00269         if(dstGeo != NULL)
00270         {
00271             pushToGeometry(srcTrans, dstGeo);
00272             continue;
00273         }
00274
00275         // should not happen
00276         FWARNING(("TransformPushGraphOp::pushTransform: Unhandled push target"
00277                   " type [%s]\n", (*ptIt)->getType().getCName()));
00278     }
00279 }
00280
00283 void TransformPushGraphOp::pushToTransform(
00284     const Transform *srcTrans, Transform *dstTrans)
00285 {
00286     dstTrans->editMatrix().multLeft(srcTrans->getMatrix());
00287 }
00288
00291 void TransformPushGraphOp::pushToGeometry(
00292     const Transform *srcTrans, Geometry *dstGeo)
00293 {
00294     typedef Vec4f  VecType;
00295     typedef Pnt3f  PntType;
00296
00297     Matrix mat    = srcTrans->getMatrix();
00298     Matrix invMat;
00299     invMat.invertFrom(mat);
00300
00301     const Geometry::SFLengthsType     *sfLen  = dstGeo->getSFLengths     ();
00302           Geometry::MFPropertiesType  *mfProp = dstGeo->editMFProperties ();
00303           Geometry::MFPropIndicesType *mfInd  = dstGeo->editMFPropIndices();
00304
00305     Geometry::MFPropertiesType::const_iterator  propIt  = mfProp->begin();
00306     Geometry::MFPropertiesType::const_iterator  propEnd = mfProp->end  ();
00307
00308     Geometry::MFPropIndicesType::const_iterator indIt   = mfInd ->begin();
00309     Geometry::MFPropIndicesType::const_iterator indEnd  = mfInd ->end  ();
00310
00311     UInt32 propUsed = 0;
00312     for(UInt32 i = 0; i < sfLen->getValue()->size(); ++i)
00313         propUsed += sfLen->getValue()->getValue<UInt32>(i);
00314
00315     for(; propIt != propEnd && indIt != indEnd; ++propIt, ++indIt)
00316     {
00317               GeoVectorProperty   *prop = *propIt;
00318         const GeoIntegralProperty *ind  = *indIt;
00319
00320         if(prop == NULL)
00321             continue;
00322
00323         if(ind == NULL)
00324         {
00325             // unindexed
00326             if((prop->getUsage() & GeoProperty::UsageObjectSpace) != 0x0000)
00327             {
00328                 // transform with mat
00329                 for(UInt32 i = 0; i < propUsed; ++i)
00330                 {
00331                     PntType pnt = prop->getValue<PntType>(i);
00332                     mat.multFull(pnt, pnt);
00333                     prop->setValue(pnt, i);
00334                 }
00335             }
00336             else if((prop->getUsage() & GeoProperty::UsageTangentSpace) != 0x0000)
00337             {
00338                 // transform with invMat
00339                 for(UInt32 i = 0; i < propUsed; ++i)
00340                 {
00341                     VecType vec = prop->getValue<VecType>(i);
00342                     invMat.mult(vec, vec);
00343                     prop->setValue(vec, i);
00344                 }
00345             }
00346         }
00347         else
00348         {
00349             std::set<UInt32> transInd;
00350
00351             if((prop->getUsage() & GeoProperty::UsageObjectSpace) != 0x0000)
00352             {
00353                 // transform with mat
00354                 for(UInt32 i = 0; i < propUsed; ++i)
00355                 {
00356                     UInt32 j = ind->getValue(i);
00357
00358                     if(transInd.find(j) == transInd.end())
00359                     {
00360                         PntType pnt = prop->getValue<PntType>(j);
00361                         mat.multFull(pnt, pnt);
00362                         prop->setValue(pnt, j);
00363
00364                         transInd.insert(j);
00365                     }
00366                 }
00367             }
00368             else if((prop->getUsage() & GeoProperty::UsageTangentSpace) != 0x0000)
00369             {
00370                 // transform with invMat
00371                 for(UInt32 i = 0; i < propUsed; ++i)
00372                 {
00373                     UInt32 j = ind->getValue(i);
00374
00375                     if(transInd.find(j) == transInd.end())
00376                     {
00377                         VecType vec = prop->getValue<VecType>(j);
00378                         invMat.mult(vec, vec);
00379                         prop->setValue(vec, j);
00380
00381                         transInd.insert(j);
00382                     }
00383                 }
00384             }
00385         }
00386     }
00387 }
00388
00389
00390 OSG_END_NAMESPACE