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

OSGParticleBSP.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 //  Includes
00041 //---------------------------------------------------------------------------
00042 
00043 #define OSG_COMPILEPARTICLEBSPINST
00044 
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 
00048 #include <OSGConfig.h>
00049 
00050 #include <OSGBaseFunctions.h>
00051 
00052 // exclude the whole class from user docs
00053 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
00054 
00055 #include "OSGNodePtr.h"
00056 #include "OSGParticleBSP.h"
00057 
00058 #include "OSGParticles.h"
00059 
00060 OSG_USING_NAMESPACE
00061 
00072 /*----------------------- constructors & destructors ----------------------*/
00073 
00074 ParticleBSPNode::ParticleBSPNode(void) :
00075     _axis()
00076 {
00077 }
00078     
00079 ParticleBSPNode::ParticleBSPNode(const ParticleBSPNode &source) :
00080     _axis(source._axis)
00081 {
00082     if(isLeaf())
00083     {
00084         _value = source._value;
00085     }
00086     else
00087     {
00088         _splitvalue = source._splitvalue;        
00089     }
00090 }
00091 
00092 ParticleBSPNode::ParticleBSPNode(UInt32 value) :
00093     _axis(Leaf),
00094     _value(value)
00095 {
00096 }
00097 
00098 ParticleBSPNode::ParticleBSPNode(UInt8 axis, Real32 splitvalue) :
00099     _axis(axis),
00100     _splitvalue(splitvalue)
00101 {
00102 }
00103 
00104 ParticleBSPNode::~ParticleBSPNode(void)
00105 {
00106 }
00107 
00108 /*---------------------------------- output -------------------------------*/
00109 
00110 void ParticleBSPNode::dump(      UInt32    OSG_CHECK_ARG(uiIndent), 
00111                            const BitVector OSG_CHECK_ARG(bvFlags )) const
00112 {
00113     static const char *axisname = "XYZL";
00114     
00115     Real32 v = isLeaf()?_value:_splitvalue;
00116     
00117     PLOG << "(" << axisname[_axis] << " " << v << ")";
00118 }
00119 
00120 
00121 /*-------------------------------------------------------------------------*/
00122 /*---------------------------- BSP Tree -----------------------------------*/
00123 /*-------------------------------------------------------------------------*/
00124 
00125 /*----------------------- constructors & destructors ----------------------*/
00126 
00127 ParticleBSPTree::ParticleBSPTree(void)
00128 {
00129 }
00130 
00131 ParticleBSPTree::~ParticleBSPTree(void)
00132 {
00133 } 
00134 
00135 /*---------------------------------- output -------------------------------*/
00136 
00137 void ParticleBSPTree::dump(      UInt32    OSG_CHECK_ARG(uiIndent), 
00138                            const BitVector OSG_CHECK_ARG(bvFlags )) const
00139 {
00140     PLOG << "ParticleBSPTree(";
00141 
00142     if(!_tree.empty())
00143     {
00144         for(std::vector<ParticleBSPNode>::const_iterator i = _tree.begin() + 1;
00145             i != _tree.end(); ++i )
00146         {
00147             i->dump();
00148         }
00149     }   
00150     
00151     PLOG << ")" << std::endl;
00152 }
00153     
00154 void ParticleBSPTree::putToString(std::string &outVal) const
00155 {
00156     outVal.assign(TypeTraits<UInt32>::putToString(_tree.size()));
00157     outVal.append(";");
00158     
00159     if(! _tree.empty())
00160     {
00161         for(std::vector<ParticleBSPNode>::const_iterator i = _tree.begin() + 1;
00162             i != _tree.end(); ++i )
00163         {
00164             outVal.append(TypeTraits<UInt8>::putToString(i->getAxis()));
00165             outVal.append(":");
00166             if(i->isLeaf())
00167             {
00168                 outVal.append(TypeTraits<Int32>::putToString(i->getValue()));
00169             }
00170             else
00171             {
00172                 outVal.append(TypeTraits<Real32>::putToString(
00173                     i->getSplitValue()));
00174             }
00175             outVal.append(";");
00176         }   
00177     }
00178 }
00179     
00180 bool ParticleBSPTree::getFromString(const Char8 *&inVal)
00181 {
00182     UInt32 size = TypeTraits<UInt32>::getFromString(inVal);
00183  
00184     const Char8 *c = strchr(inVal, ';');
00185     
00186     if(!c)
00187         return false;
00188     c++;
00189     
00190     _tree.resize(size);
00191     
00192     for(UInt32 i = 1; i < size; ++i)
00193     {
00194         UInt8 axis = TypeTraits<UInt8>::getFromString(c);
00195         c = strchr(c, ':');
00196         if(!c)
00197             return false;
00198         c++;
00199         
00200         if(axis == ParticleBSPNode::Leaf)
00201         {
00202             Int32 value = TypeTraits<Int32>::getFromString(c);
00203             _tree[i].setValue(value);
00204         }
00205         else
00206         {
00207             Real32 value = TypeTraits<Real32>::getFromString(c);
00208             _tree[i].setSplit(axis, value);           
00209         }
00210         c = strchr(c, ';');
00211         if(!c)
00212             return false;
00213         c++;
00214     }
00215     
00216     return true;
00217 }
00218 
00219 UInt32 ParticleBSPTree::getBinSize(void) const
00220 {
00221     return sizeof(UInt32) // num elements
00222         + (sizeof(UInt8)+sizeof(UInt32)) * _tree.size();
00223 }
00224     
00225 void ParticleBSPTree::copyToBin(BinaryDataHandler &pMem) const
00226 {
00227     UInt8  axis;
00228     Int32  value;
00229     Real32 splitvalue;
00230     UInt32 i;
00231     UInt32 size = _tree.size();
00232     pMem.putValue(size);
00233 
00234     for(i=0;i<size;++i)
00235     {
00236         axis=_tree[i].getAxis();
00237         pMem.putValue(axis);
00238         if(axis==ParticleBSPNode::Leaf)
00239         {
00240             value=_tree[i].getValue();
00241             pMem.putValue(value);
00242         }
00243         else
00244         {
00245             splitvalue=_tree[i].getSplitValue();
00246             pMem.putValue(splitvalue);
00247         }
00248     }
00249 }
00250     
00251 void ParticleBSPTree::copyFromBin(BinaryDataHandler &pMem)
00252 {
00253     UInt8  axis;
00254     Int32  value;
00255     Real32 splitvalue;
00256     UInt32 i;
00257     UInt32 size;
00258     pMem.getValue(size);
00259     _tree.resize(size);
00260 
00261     for(i=0;i<size;++i)
00262     {
00263         pMem.getValue(axis);
00264         if(axis==ParticleBSPNode::Leaf)
00265         {
00266             pMem.getValue(value);
00267             _tree[i].setValue(value);
00268         }
00269         else
00270         {
00271             pMem.getValue(splitvalue);
00272             _tree[i].setSplit(axis, Real32(value));
00273         }
00274     }
00275 }
00276 
00277 /*-------------------------------- traversal ------------------------------*/
00278 
00279 Int32 *ParticleBSPTree::traverse(const Pnt3f &refPoint, UInt32 &length, 
00280                                  Int32 *order) const
00281 {
00282     if(_tree.empty())
00283         return NULL;
00284         
00285     if(order == NULL)
00286     {
00287         order = new Int32 [length];
00288     }
00289     
00290     length = doTraverse(refPoint,1,0,order);
00291     
00292     return order;
00293 }
00294 
00295 UInt32 ParticleBSPTree::doTraverse(const Pnt3f &refPoint, UInt32 index, 
00296                                    UInt32 length, Int32 *order) const
00297 {
00298     const ParticleBSPNode *n = &_tree[index];
00299     
00300     if(n->isLeaf())
00301     {
00302         order[length] = n->getValue();
00303         return ++length;
00304     }
00305     else
00306     {
00307         if(refPoint[n->getAxis()] > n->getSplitValue())
00308         {
00309             length = doTraverse(refPoint, index * 2    , length, order);
00310             length = doTraverse(refPoint, index * 2 + 1, length, order);
00311         }
00312         else
00313         {
00314             length = doTraverse(refPoint, index * 2 + 1, length, order);
00315             length = doTraverse(refPoint, index * 2    , length, order);
00316         }
00317     }
00318     return length;
00319 }
00320 
00321 Int32 *ParticleBSPTree::traverse(const Vec3f &refVec, UInt32 &length, 
00322                                  Int32 *order) const
00323 {
00324     if(order == NULL)
00325     {
00326         order = new Int32 [length];
00327     }
00328     
00329     length = doTraverse(refVec,1,0,order);
00330     
00331     return order;
00332 }
00333 
00334 UInt32 ParticleBSPTree::doTraverse(const Vec3f &refVec, UInt32 index, 
00335                                    UInt32 length, Int32 *order) const
00336 {
00337     const ParticleBSPNode *n = &_tree[index];
00338     
00339     if(n->isLeaf())
00340     {
00341         order[length] = n->getValue();
00342         return ++length;
00343     }
00344     else
00345     {
00346         if(refVec[n->getAxis()] > 0.f)
00347         {
00348             length = doTraverse(refVec, index * 2    , length, order);
00349             length = doTraverse(refVec, index * 2 + 1, length, order);
00350         }
00351         else
00352         {
00353             length = doTraverse(refVec, index * 2 + 1, length, order);
00354             length = doTraverse(refVec, index * 2    , length, order);
00355         }
00356     }
00357     return length;
00358 }
00359 
00360 /*--------------------------------- creation ------------------------------*/
00361 
00362 void ParticleBSPTree::build(Particles *core)
00363 {
00364     _tree.clear();
00365     
00366     if(core == NULL)
00367     {
00368         FWARNING(("ParticleBSP::build: no core!!\n"));
00369         return;
00370     }
00371     
00372     const GeoPositionsPtr pos = core->getPositions();
00373     
00374     if(pos == NullFC)
00375         return;
00376 
00377     const MFInt32 *indices = core->getMFIndices();
00378         
00379     // 1. create list for particles
00380  
00381     std::vector<Int32> order;
00382     order.reserve(pos->getSize());
00383     
00384     for(UInt32 i = 0; i < pos->getSize(); ++i )
00385     {     
00386         if(indices->size() == pos->getSize())
00387         {        
00388             order.push_back((*indices)[i]);
00389         }
00390         else
00391         {
00392             order.push_back(i);            
00393         }
00394     }
00395     
00396     // reserve mem for tree
00397     
00398     _tree.resize(osgnextpower2(order.size()) * 2);
00399     
00400     // 2. recursively build the tree
00401     
00402     UInt32 nnodes = doBuild(order.begin(), order.end(), 1, pos);
00403     
00404     // 3. remove the unneeded elements from the end
00405     
00406     if(nnodes < _tree.size())
00407         _tree.erase( _tree.begin() + nnodes, _tree.end());
00408 
00409     // done
00410 }
00411 
00415 struct ParticleCompare : public std::binary_function<Int32, Int32, bool> 
00416 {
00417     ParticleCompare(GeoPositionsPtr pos, UInt8 axis) : _pos(pos), _axis(axis)
00418     {}
00419     
00420     bool operator()(Int32 x, Int32 y) 
00421     { 
00422         Pnt3f px,py;
00423         _pos->getValue(px, x);
00424         _pos->getValue(py, y);
00425         
00426         return px[_axis] < py[_axis]; 
00427     }
00428     
00429     GeoPositionsPtr _pos;
00430     UInt8 _axis;
00431 };
00432     
00433 UInt32 ParticleBSPTree::doBuild(std::vector<Int32>::iterator begin, 
00434                                 std::vector<Int32>::iterator end,
00435                                      UInt32                  nodeindex,
00436                                      GeoPositionsPtr         pos)
00437 {
00438     // reached a leaf?
00439     
00440     if(begin + 1 == end)
00441     {
00442         _tree[nodeindex].setValue(*begin);
00443         return nodeindex + 1;
00444     }
00445     
00446     // find the bounding volume of the group
00447     
00448     BoxVolume b;
00449     Pnt3f p;
00450     
00451     b.setEmpty();
00452     
00453     for(std::vector<Int32>::iterator i = begin; i != end; ++i)
00454     {
00455         pos->getValue(p,*i);     
00456         b.extendBy(p);
00457     }
00458     
00459     // find the axis with the longest extension
00460     
00461     Vec3f d = b.getMax() - b.getMin();
00462     
00463     UInt8 axis = ParticleBSPNode::X;
00464     Real32 maxval = d[0];
00465     
00466     if(d[1] > maxval)
00467     {
00468         axis = ParticleBSPNode::Y;
00469         maxval = d[1];
00470     }
00471     if(d[2] > maxval)
00472     {
00473         axis = ParticleBSPNode::Z;
00474         maxval = d[2];
00475     }
00476 
00477     // sort in that axis
00478     ParticleCompare comp(pos, axis);
00479     
00480     std::sort(begin,end,comp);
00481     
00482     // find median value
00483     std::vector<Int32>::iterator mid = begin + (end - begin) / 2;
00484     
00485     Pnt3f p2;
00486     pos->getValue(p ,*mid);
00487     pos->getValue(p2,(*mid)-1);
00488     _tree[nodeindex].setSplit(axis, (p[axis] + p2[axis]) / 2.f);
00489     
00490     return osgMax( doBuild(begin, mid, nodeindex * 2    , pos),
00491                    doBuild(  mid, end, nodeindex * 2 + 1, pos) );   
00492 }   
00493 
00494 
00495 void ParticleBSPTree::destroy()
00496 {
00497     _tree.clear();
00498 }
00499 
00500 
00501 #include <OSGMFieldTypeDef.inl>
00502 #include <OSGSFieldTypeDef.inl>
00503 
00504 OSG_BEGIN_NAMESPACE
00505 
00506 /*-------------------------- field instantiations -------------------------*/
00507 
00508 DataType FieldDataTraits<ParticleBSPTree>::_type("ParticleBSPTree", 
00509         "None");
00510 
00511 OSG_DLLEXPORT_SFIELD_DEF1(ParticleBSPTree, OSG_SYSTEMLIB_DLLTMPLMAPPING);
00512 
00513 OSG_END_NAMESPACE
00514 
00515 #endif            // exclude from user doc
00516 
00517 /*-------------------------------------------------------------------------*/
00518 /*                              cvs id's                                   */
00519 
00520 #ifdef __sgi
00521 #pragma set woff 1174
00522 #endif
00523 
00524 #ifdef OSG_LINUX_ICC
00525 #pragma warning( disable : 177 )
00526 #endif
00527 
00528 namespace
00529 {
00530     static char cvsid_cpp[] = "@(#)$Id: $";
00531     static char cvsid_hpp[] = OSGPARTICLEBSP_HEADER_CVSID;
00532     static char cvsid_inl[] = OSGPARTICLEBSP_INLINE_CVSID;
00533 }

Generated on Thu Aug 25 04:08:02 2005 for OpenSG by  doxygen 1.4.3