00001 #include <esg/explorer/RayIntExplorer.h>
00002 #include <esg/iterator/IteratorSDS.h>
00003 #include <esg/Statistics.h>
00004
00005 using namespace esg;
00006
00007 #ifdef ESG_STATISTICS
00008 #define RIE_INC_TEST { _primTestsCounter++; }
00009 #define RIE_INC_SUC_TEST { _primTestsSucCounter++; }
00010 #define RIE_UPDATE_STAT { \
00011 ((Counter*)Statistics::instance()->get(Statistics::OID_PRIM_TESTS)->receptor())->add(_primTestsCounter); \
00012 ((Counter*)Statistics::instance()->get(Statistics::OID_PRIM_TESTS_SUC)->receptor())->add(_primTestsSucCounter); \
00013 _primTestsCounter = (_primTestsSucCounter = 0); \
00014 }
00015 #else
00016 #define RIE_INC_TEST {}
00017 #define RIE_INC_SUC_TEST {}
00018 #define RIE_UPDATE_STAT {}
00019 #endif // ESG_STATISTICS
00020
00021
00022 bool RayIntExplorer::_explore(SceneGraphObject& obj)
00023 {
00024 Transform* pTr = obj.transformation();
00025
00026 if (pTr) {
00027 Matrix4* auxMat = new Matrix4(pTr->get());
00028 if (!_trStack.empty()) auxMat->mul(*_trStack.top(), *auxMat);
00029 _trStack.push(auxMat);
00030 _rMat.set(*(pTr->getRotation()));
00031 _tVec = pTr->getTranslation();
00032 _sVec = pTr->getScale();
00033 ESG_INVERSE_TR_RAY(_rMat, *_tVec, *_sVec,
00034 _origin, _trOrigin, _direction, _trDirection);
00035 }
00036
00037
00038
00039
00040 if (obj.hasSubnodes()) {
00041 _retVal = false;
00042 IteratorSDS* pIter = obj.traverseSubnodes();
00043 if (pIter) {
00044 pIter->initRayIntersection(_trOrigin,_trDirection,true,_maxDist);
00045 _pCandidate = pIter->firstChild();
00046 while (_pCandidate) {
00047 _retVal = _explore(*_pCandidate);
00048 _actDist = _pIntersector->getActDistance();
00049 if (_actDist < _maxDist) {
00050 _maxDist = _actDist;
00051 pIter->initRayIntersection(_trOrigin, _trDirection,
00052 false, _maxDist);
00053 }
00054 _pCandidate = pIter->nextChild();
00055 }
00056 delete pIter;
00057 }
00058 } else {
00059 RIE_INC_TEST;
00060 if (_pIntersector->processCandidate(&obj, _trOrigin, _trDirection)) {
00061 if (_trStack.empty())
00062 _transformed = false;
00063 else {
00064 _accumMat.set(*_trStack.top());
00065 _transformed = true;
00066 }
00067 _retVal = true;
00068 RIE_INC_SUC_TEST;
00069 } else
00070 _retVal = false;
00071 }
00072
00073
00074
00075
00076 if (pTr) {
00077 delete _trStack.top();
00078 _trStack.pop();
00079 }
00080
00081 return _retVal;
00082 }
00083
00084 RayIntExplorer::RayIntExplorer(const Vector3& o,
00085 const Vector3& d,
00086 Intersector* pI,
00087 float m)
00088 : _origin(o),
00089 _direction(d),
00090 _pIntersector(pI),
00091 _maxDist(m),
00092 _trOrigin(o),
00093 _trDirection(d),
00094 _transformed(false)
00095 {
00096 #ifdef ESG_STATISTICS
00097 _primTestsCounter = 0;
00098 _primTestsSucCounter = 0;
00099 #endif // ESG_STATISTICS
00100 }
00101
00102 void RayIntExplorer::explore(SceneGraphObject& obj)
00103 {
00104 if (!_pIntersector) return;
00105 (void) _explore(obj);
00106 }
00107
00108
00109 void RayIntExplorer::reinit(const Vector3& o,
00110 const Vector3& d,
00111 Intersector* pI,
00112 float m)
00113 {
00114 RIE_UPDATE_STAT;
00115 _transformed = false;
00116 _origin.set(o);
00117 _direction.set(d);
00118 _trOrigin.set(o);
00119 _trDirection.set(d);
00120 _pIntersector = pI;
00121 _maxDist = m;
00122 }
00123
00124 PointEnv* RayIntExplorer::result()
00125 {
00126 PointEnv* p = NULL;
00127 if (_pIntersector) p = _pIntersector->adoptIntersection();
00128 if (p && _transformed) {
00129 p->trMat.set(_accumMat);
00130 p->mask |= ENV_HAVE_TRANSFORMATION;
00131 }
00132 RIE_UPDATE_STAT;
00133 return p;
00134 }
00135
00136 #ifdef ESG_STATISTICS
00137 #undef RIE_INC_TEST
00138 #undef RIE_INC_SUC_TEST
00139 #undef RIE_UPDATE_STAT
00140 #endif // ESG_STATISTICS