00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
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
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
00123
00124
00125
00126
00127 ParticleBSPTree::ParticleBSPTree(void)
00128 {
00129 }
00130
00131 ParticleBSPTree::~ParticleBSPTree(void)
00132 {
00133 }
00134
00135
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)
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
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
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
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
00397
00398 _tree.resize(osgnextpower2(order.size()) * 2);
00399
00400
00401
00402 UInt32 nnodes = doBuild(order.begin(), order.end(), 1, pos);
00403
00404
00405
00406 if(nnodes < _tree.size())
00407 _tree.erase( _tree.begin() + nnodes, _tree.end());
00408
00409
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
00439
00440 if(begin + 1 == end)
00441 {
00442 _tree[nodeindex].setValue(*begin);
00443 return nodeindex + 1;
00444 }
00445
00446
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
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
00478 ParticleCompare comp(pos, axis);
00479
00480 std::sort(begin,end,comp);
00481
00482
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
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
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 }