1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.h"
48 #include "OSGBaseFunctions.h"
51 #include "OSGParticleBSP.h"
53 #include "OSGParticles.h"
57 /*! \class OSG::ParticleBSPTree
59 A very simple BSP tree, optimized for particle sorting.
62 /*! \class OSG::ParticleBSPNode
64 A node of the ParticleBSPTree.
67 /*----------------------- constructors & destructors ----------------------*/
69 ParticleBSPNode::ParticleBSPNode(void) :
74 ParticleBSPNode::ParticleBSPNode(const ParticleBSPNode
&source
) :
79 _value
= source
._value
;
83 _splitvalue
= source
._splitvalue
;
87 ParticleBSPNode::ParticleBSPNode(UInt32 value
) :
93 ParticleBSPNode::ParticleBSPNode(UInt8 axis
, Real32 splitvalue
) :
95 _splitvalue(splitvalue
)
99 ParticleBSPNode::~ParticleBSPNode(void)
103 /*---------------------------------- output -------------------------------*/
105 void ParticleBSPNode::dump( UInt32
OSG_CHECK_ARG(uiIndent
),
106 const BitVector
OSG_CHECK_ARG(bvFlags
)) const
108 static const char *axisname
= "XYZL";
110 Real32 v
= isLeaf()?_value
:_splitvalue
;
112 PLOG
<< "(" << axisname
[_axis
] << " " << v
<< ")";
116 /*-------------------------------------------------------------------------*/
117 /*---------------------------- BSP Tree -----------------------------------*/
118 /*-------------------------------------------------------------------------*/
120 /*----------------------- constructors & destructors ----------------------*/
122 ParticleBSPTree::ParticleBSPTree(void) :
127 ParticleBSPTree::~ParticleBSPTree(void)
131 /*---------------------------------- output -------------------------------*/
133 void ParticleBSPTree::dump( UInt32
OSG_CHECK_ARG(uiIndent
),
134 const BitVector
OSG_CHECK_ARG(bvFlags
)) const
136 PLOG
<< "ParticleBSPTree(";
140 for(std::vector
<ParticleBSPNode
>::const_iterator i
= _tree
.begin() + 1;
141 i
!= _tree
.end(); ++i
)
147 PLOG
<< ")" << std::endl
;
151 void ParticleBSPTree::putToString(std::string
&outVal
) const
153 outVal
.assign(TypeTraits
<UInt32
>::putToString(_tree
.size()));
158 for(std::vector
<ParticleBSPNode
>::const_iterator i
= _tree
.begin() + 1;
159 i
!= _tree
.end(); ++i
)
161 outVal
.append(TypeTraits
<UInt8
>::putToString(i
->getAxis()));
165 outVal
.append(TypeTraits
<Int32
>::putToString(i
->getValue()));
169 outVal
.append(TypeTraits
<Real32
>::putToString(
170 i
->getSplitValue()));
177 bool ParticleBSPTree::getFromString(const Char8
*&inVal
)
179 UInt32 size
= TypeTraits
<UInt32
>::getFromString(inVal
);
181 const Char8
*c
= strchr(inVal
, ';');
189 for(UInt32 i
= 1; i
< size
; ++i
)
191 UInt8 axis
= TypeTraits
<UInt8
>::getFromString(c
);
197 if(axis
== ParticleBSPNode::Leaf
)
199 Int32 value
= TypeTraits
<Int32
>::getFromString(c
);
200 _tree
[i
].setValue(value
);
204 Real32 value
= TypeTraits
<Real32
>::getFromString(c
);
205 _tree
[i
].setSplit(axis
, value
);
217 SizeT
ParticleBSPTree::getBinSize(void) const
219 return sizeof(UInt32
) // num elements
220 + (sizeof(UInt8
)+sizeof(UInt32
)) * _tree
.size();
223 void ParticleBSPTree::copyToBin(BinaryDataHandler
&pMem
) const
229 UInt32 size
= UInt32(_tree
.size());
234 axis
=_tree
[i
].getAxis();
236 if(axis
==ParticleBSPNode::Leaf
)
238 value
=_tree
[i
].getValue();
239 pMem
.putValue(value
);
243 splitvalue
=_tree
[i
].getSplitValue();
244 pMem
.putValue(splitvalue
);
249 void ParticleBSPTree::copyFromBin(BinaryDataHandler
&pMem
)
262 if(axis
==ParticleBSPNode::Leaf
)
264 pMem
.getValue(value
);
265 _tree
[i
].setValue(value
);
269 pMem
.getValue(splitvalue
);
270 _tree
[i
].setSplit(axis
, Real32(value
));
275 bool ParticleBSPTree::operator ==(const ParticleBSPTree
&source
) const
280 /*-------------------------------- traversal ------------------------------*/
282 Int32
*ParticleBSPTree::traverse(const Pnt3f
&refPoint
, UInt32
&length
,
290 order
= new Int32
[length
];
293 length
= doTraverse(refPoint
,1,0,order
);
298 UInt32
ParticleBSPTree::doTraverse(const Pnt3f
&refPoint
, UInt32 index
,
299 UInt32 length
, Int32
*order
) const
301 const ParticleBSPNode
*n
= &_tree
[index
];
305 order
[length
] = n
->getValue();
310 if(refPoint
[n
->getAxis()] > n
->getSplitValue())
312 length
= doTraverse(refPoint
, index
* 2 , length
, order
);
313 length
= doTraverse(refPoint
, index
* 2 + 1, length
, order
);
317 length
= doTraverse(refPoint
, index
* 2 + 1, length
, order
);
318 length
= doTraverse(refPoint
, index
* 2 , length
, order
);
324 Int32
*ParticleBSPTree::traverse(const Vec3f
&refVec
, UInt32
&length
,
329 order
= new Int32
[length
];
332 length
= doTraverse(refVec
,1,0,order
);
337 UInt32
ParticleBSPTree::doTraverse(const Vec3f
&refVec
, UInt32 index
,
338 UInt32 length
, Int32
*order
) const
340 const ParticleBSPNode
*n
= &_tree
[index
];
344 order
[length
] = n
->getValue();
349 if(refVec
[n
->getAxis()] > 0.f
)
351 length
= doTraverse(refVec
, index
* 2 , length
, order
);
352 length
= doTraverse(refVec
, index
* 2 + 1, length
, order
);
356 length
= doTraverse(refVec
, index
* 2 + 1, length
, order
);
357 length
= doTraverse(refVec
, index
* 2 , length
, order
);
363 /*--------------------------------- creation ------------------------------*/
365 void ParticleBSPTree::build(Particles
*core
)
371 FWARNING(("ParticleBSP::build: no core!!\n"));
375 GeoVectorProperty
* const pos
= core
->getPositions();
380 const MFInt32
*indices
= core
->getMFIndices();
382 // 1. create list for particles
384 std::vector
<Int32
> order
;
385 order
.reserve(pos
->size());
387 for(UInt32 i
= 0; i
< pos
->size32(); ++i
)
389 if(indices
->size() == pos
->size())
391 order
.push_back((*indices
)[i
]);
399 // reserve mem for tree
401 _tree
.resize(osgNextPower2(order
.size()) * 2);
403 // 2. recursively build the tree
405 UInt32 nnodes
= doBuild(order
.begin(), order
.end(), 1, pos
);
407 // 3. remove the unneeded elements from the end
409 if(nnodes
< _tree
.size())
410 _tree
.erase( _tree
.begin() + nnodes
, _tree
.end());
415 /*! \ingroup GrpDrawablesParticlesHelpers
419 struct ParticleCompare
: public std::binary_function
<Int32
, Int32
, bool>
421 ParticleCompare(GeoVectorProperty
*pos
, UInt8 axis
) :
426 bool operator()(Int32 x
, Int32 y
)
429 _pos
->getValue(px
, x
);
430 _pos
->getValue(py
, y
);
432 return px
[_axis
] < py
[_axis
];
435 GeoVectorProperty
*_pos
;
439 UInt32
ParticleBSPTree::doBuild(std::vector
<Int32
>::iterator begin
,
440 std::vector
<Int32
>::iterator end
,
442 GeoVectorProperty
*pos
)
448 _tree
[nodeindex
].setValue(*begin
);
449 return nodeindex
+ 1;
452 // find the bounding volume of the group
459 for(std::vector
<Int32
>::iterator i
= begin
; i
!= end
; ++i
)
465 // find the axis with the longest extension
467 Vec3f d
= b
.getMax() - b
.getMin();
469 UInt8 axis
= ParticleBSPNode::X
;
470 Real32 maxval
= d
[0];
474 axis
= ParticleBSPNode::Y
;
479 axis
= ParticleBSPNode::Z
;
484 ParticleCompare
comp(pos
, axis
);
486 std::sort(begin
,end
,comp
);
489 std::vector
<Int32
>::iterator mid
= begin
+ (end
- begin
) / 2;
492 pos
->getValue(p
,*mid
);
493 pos
->getValue(p2
,(*mid
)-1);
494 _tree
[nodeindex
].setSplit(axis
, (p
[axis
] + p2
[axis
]) / 2.f
);
496 return osgMax( doBuild(begin
, mid
, nodeindex
* 2 , pos
),
497 doBuild( mid
, end
, nodeindex
* 2 + 1, pos
) );
501 void ParticleBSPTree::destroy()
507 #include "OSGSField.ins"
508 #include "OSGMField.ins"
512 /*-------------------------- field instantiations -------------------------*/
514 DataType FieldTraits
<ParticleBSPTree
>::_type("ParticleBSPTree",
517 OSG_FIELDTRAITS_GETTYPE(ParticleBSPTree
)
519 OSG_FIELD_DLLEXPORT_DEF1(SField
, ParticleBSPTree
)