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"
49 #include "OSGFieldContainer.h"
51 #include "OSGNodeCore.h"
52 #include "OSGAction.h"
53 #include "OSGIntersectAction.h"
54 #include "OSGIntersectProxyAttachment.h"
56 #include <boost/bind.hpp>
61 /***************************************************************************\
63 \***************************************************************************/
65 /*! \class OSG::IntersectAction
66 \ingroup GrpSystemAction
68 The intersect action class.
72 /***************************************************************************\
74 \***************************************************************************/
76 /***************************************************************************\
78 \***************************************************************************/
80 StatElemDesc
<StatTimeElem
> IntersectAction::statTravTime(
82 "time needed for intersect");
84 StatElemDesc
<StatIntElem
> IntersectAction::statNNodes(
86 "number of nodes visited");
88 StatElemDesc
<StatIntElem
> IntersectAction::statNTriangles(
90 "number of triangles tested");
92 IntersectAction
*IntersectAction::_prototype
= NULL
;
94 Action::FunctorStore
*IntersectAction::_defaultEnterFunctors
= NULL
;
95 Action::FunctorStore
*IntersectAction::_defaultLeaveFunctors
= NULL
;
97 /***************************************************************************\
99 \***************************************************************************/
101 bool IntersectAction::terminateEnter(void)
103 FDEBUG_GV(("Terminate IntersectAction Enter\n"));
105 delete _defaultEnterFunctors
;
107 _defaultEnterFunctors
= NULL
;
112 bool IntersectAction::terminateLeave(void)
114 FDEBUG_GV(("Terminate IntersectAction Leave\n"));
116 delete _defaultLeaveFunctors
;
118 _defaultLeaveFunctors
= NULL
;
123 /*-------------------------------------------------------------------------*\
125 \*-------------------------------------------------------------------------*/
127 void IntersectAction::registerEnterDefault(const FieldContainerType
&type
,
128 const Action::Functor
&func
)
130 if(! _defaultEnterFunctors
)
132 _defaultEnterFunctors
= new FunctorStore
;
134 addPostFactoryExitFunction(&IntersectAction::terminateEnter
);
137 while(type
.getId() >= _defaultEnterFunctors
->size())
139 _defaultEnterFunctors
->push_back(
140 &IntersectAction::_defaultEnterFunction
);
143 (*_defaultEnterFunctors
)[type
.getId()] = func
;
146 void IntersectAction::registerLeaveDefault(const FieldContainerType
&type
,
147 const Action::Functor
&func
)
149 if(! _defaultLeaveFunctors
)
151 _defaultLeaveFunctors
= new FunctorStore
;
153 addPostFactoryExitFunction(&IntersectAction::terminateLeave
);
156 while(type
.getId() >= _defaultLeaveFunctors
->size())
158 _defaultLeaveFunctors
->push_back(
159 &IntersectAction::_defaultLeaveFunction
);
162 (*_defaultLeaveFunctors
)[type
.getId()] = func
;
165 void IntersectAction::setPrototype(IntersectAction
*proto
)
170 IntersectAction
*IntersectAction::getPrototype(void)
175 StatCollector
*IntersectAction::getStatCollector(void) const
180 void IntersectAction::setStatCollector(StatCollector
*sc
)
185 bool IntersectAction::getResetStatistics(void) const
187 return _resetStatistics
;
190 void IntersectAction::setResetStatistics(bool value
)
192 _resetStatistics
= value
;
195 /*-------------------------------------------------------------------------*\
197 \*-------------------------------------------------------------------------*/
200 /*-------------------------------------------------------------------------*\
202 \*-------------------------------------------------------------------------*/
206 /***************************************************************************\
208 \***************************************************************************/
210 /*-------------------------------------------------------------------------*\
212 \*-------------------------------------------------------------------------*/
214 /*------------- constructors & destructors --------------------------------*/
216 /** \brief Constructor
219 IntersectAction::IntersectAction(void) :
223 _lineTestWidth ( 0.0),
236 _resetStatistics(true )
238 if(_defaultEnterFunctors
)
239 _enterFunctors
= *_defaultEnterFunctors
;
241 if(_defaultLeaveFunctors
)
242 _leaveFunctors
= *_defaultLeaveFunctors
;
244 _nodeEnterCB
= boost::bind(&IntersectAction::onEnterNode
, this, _1
, _2
);
245 _nodeLeaveCB
= boost::bind(&IntersectAction::onLeaveNode
, this, _1
, _2
);
249 IntersectAction::IntersectAction(const IntersectAction
& source
) :
251 _line (source
._line
),
252 _testLines (source
._testLines
),
253 _lineTestWidth (source
._lineTestWidth
),
254 _maxdist (source
._maxdist
),
256 _enterT (source
._enterT
),
257 _leaveT (source
._leaveT
),
258 _path (source
._path
),
259 _hitT (source
._hitT
),
260 _hitObject (source
._hitObject
),
261 _hitPath (source
._hitPath
),
262 _hitTriangle (source
._hitTriangle
),
263 _hitNormal (source
._hitNormal
),
264 _hitLine (source
._hitLine
),
265 _statistics (source
._statistics
),
266 _resetStatistics(source
._resetStatistics
)
268 _nodeEnterCB
= boost::bind(&IntersectAction::onEnterNode
, this, _1
, _2
);
269 _nodeLeaveCB
= boost::bind(&IntersectAction::onLeaveNode
, this, _1
, _2
);
273 /** \brief create a new action
276 IntersectAction::ObjTransitPtr
IntersectAction::create(void)
278 ObjTransitPtr
act(NULL
);
282 act
= new IntersectAction(*_prototype
);
286 act
= new IntersectAction();
293 /** \brief create a new action
296 IntersectAction::ObjTransitPtr
IntersectAction::create(const Line
&line
,
297 const Real32 maxdist
)
299 ObjTransitPtr
act(NULL
);
303 act
= new IntersectAction(*_prototype
);
307 act
= new IntersectAction();
310 act
->setLine(line
, maxdist
);
315 /** \brief Destructor
318 IntersectAction::~IntersectAction(void)
322 /*---------------------------- application --------------------------------*/
324 /*---------------------------- properties ---------------------------------*/
326 void IntersectAction::setLine(const Line
&line
, const Real32 maxdist
)
332 void IntersectAction::setTestLines( bool value
)
337 void IntersectAction::setTestLineWidth(Real32 width
)
339 _lineTestWidth
= width
;
342 Action::ResultE
IntersectAction::setEnterLeave(Real32 enter
, Real32 leave
)
344 if(leave
< 0 || enter
> _maxdist
||
345 ( _hit
&& enter
> _hitT
))
350 return Action::Continue
;
353 /** Attempt to set the new hit for the intersection.
354 * The hit is only set if this hit would be closer then the existing hit position.
355 * @param t The distance along the ray that the hit occurred.
356 * @param obj The Node object that was hit.
357 * @param triIndex The index of the triangle in the geometry hit.
358 * @param normal The normal at the hit location.
359 * @param lineIndex The index of the line in the geometry hit.
361 void IntersectAction::setHit( Real32 t
,
367 if(t
< 0 || t
> _hitT
|| t
> _maxdist
)
373 _hitTriangle
= triIndex
;
375 _hitLine
= lineIndex
;
379 void IntersectAction::scale(Real32 s
)
385 /*-------------------------- your_category---------------------------------*/
388 Action::ResultE
IntersectAction::start(void)
398 // reserve some memory for a scene depth of 20
399 // TODO: is this a sensible number?
400 _hitPath
.reserve(20);
403 if(_statistics
== NULL
)
404 _statistics
= new StatCollector
;
406 if(_resetStatistics
== true)
407 _statistics
->reset();
409 _statistics
->getElem(statTravTime
)->start();
414 Action::ResultE
IntersectAction::stop(ResultE res
)
416 _statistics
->getElem(statTravTime
)->stop();
422 /*-------------------------- assignment -----------------------------------*/
424 /*-------------------------- comparison -----------------------------------*/
426 /** \brief assignment
429 bool IntersectAction::operator < (const IntersectAction
&other
) const
431 return this < &other
;
437 bool IntersectAction::operator == (
438 const IntersectAction
&OSG_CHECK_ARG(other
)) const
446 bool IntersectAction::operator != (const IntersectAction
&other
) const
448 return ! (*this == other
);
452 /*-------------------------------------------------------------------------*\
454 \*-------------------------------------------------------------------------*/
457 Action::FunctorStore
*IntersectAction::getDefaultEnterFunctors(void)
459 return _defaultEnterFunctors
;
462 Action::FunctorStore
*IntersectAction::getDefaultLeaveFunctors(void)
464 return _defaultLeaveFunctors
;
467 /*-------------------------------------------------------------------------*\
469 \*-------------------------------------------------------------------------*/
471 Action::ResultE
IntersectAction::onEnterNode(Node
* node
, Action
* action
)
473 OSG_ASSERT(this == action
&& node
== _actNode
);
475 ResultE result
= Continue
;
477 _path
.push_back(node
);
479 _statistics
->getElem(statNNodes
)->inc();
481 IntersectProxyAttachment
* ipa
= dynamic_cast<IntersectProxyAttachment
*>(
482 node
->findAttachment(IntersectProxyAttachment::getClassType()));
486 result
= ipa
->intersectEnter(node
, this);
492 Action::ResultE
IntersectAction::onLeaveNode(Node
* node
, Action
* action
)
494 OSG_ASSERT(this == action
&& node
== _actNode
);
496 ResultE result
= Continue
;