00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "BVHSubTreeCollector.hxx"
00019
00020 #include <simgear/math/SGGeometry.hxx>
00021
00022 #include "BVHNode.hxx"
00023 #include "BVHGroup.hxx"
00024 #include "BVHTransform.hxx"
00025
00026 #include "BVHStaticData.hxx"
00027
00028 #include "BVHStaticNode.hxx"
00029 #include "BVHStaticTriangle.hxx"
00030 #include "BVHStaticBinary.hxx"
00031 #include "BVHStaticGeometry.hxx"
00032 #include "BVHBoundingBoxVisitor.hxx"
00033
00034 namespace simgear {
00035
00036 BVHSubTreeCollector::BVHSubTreeCollector(const SGSphered& sphere) :
00037 _sphere(sphere)
00038 {
00039 }
00040
00041 BVHSubTreeCollector::~BVHSubTreeCollector()
00042 {
00043 }
00044
00045 void
00046 BVHSubTreeCollector::apply(BVHGroup& group)
00047 {
00048 if (!intersects(_sphere, group.getBoundingSphere()))
00049 return;
00050
00051
00052
00053 NodeList parentNodeList;
00054 pushNodeList(parentNodeList);
00055
00056 group.traverse(*this);
00057
00058 popNodeList(parentNodeList);
00059 }
00060
00061 void
00062 BVHSubTreeCollector::apply(BVHTransform& transform)
00063 {
00064 if (!intersects(_sphere, transform.getBoundingSphere()))
00065 return;
00066
00067 SGSphered sphere = _sphere;
00068 _sphere = transform.sphereToLocal(sphere);
00069
00070 NodeList parentNodeList;
00071 pushNodeList(parentNodeList);
00072
00073 transform.traverse(*this);
00074
00075 if (haveChildren()) {
00076 BVHTransform* currentBvTransform = new BVHTransform;
00077 currentBvTransform->setTransform(transform);
00078 popNodeList(parentNodeList, currentBvTransform);
00079 } else {
00080 popNodeList(parentNodeList);
00081 }
00082
00083 _sphere = sphere;
00084 }
00085
00086 void
00087 BVHSubTreeCollector::apply(BVHMotionTransform& transform)
00088 {
00089 if (!intersects(_sphere, transform.getBoundingSphere()))
00090 return;
00091
00092 SGSphered sphere = _sphere;
00093 _sphere = transform.sphereToLocal(sphere, transform.getStartTime());
00094 _sphere.expandBy(transform.sphereToLocal(sphere, transform.getEndTime()));
00095
00096 NodeList parentNodeList;
00097 pushNodeList(parentNodeList);
00098
00099 transform.traverse(*this);
00100
00101 if (haveChildren()) {
00102 BVHMotionTransform* currentBvTransform = new BVHMotionTransform;
00103 currentBvTransform->setTransform(transform);
00104 popNodeList(parentNodeList, currentBvTransform);
00105 } else {
00106 popNodeList(parentNodeList);
00107 }
00108
00109 _sphere = sphere;
00110 }
00111
00112 void
00113 BVHSubTreeCollector::apply(BVHLineGeometry& lineSegment)
00114 {
00115 if (!intersects(_sphere, lineSegment.getBoundingSphere()))
00116 return;
00117 addNode(&lineSegment);
00118 }
00119
00120 void
00121 BVHSubTreeCollector::apply(BVHStaticGeometry& node)
00122 {
00123 if (!intersects(_sphere, node.getBoundingSphere()))
00124 return;
00125
00126 assert(!_staticNode);
00127 node.traverse(*this);
00128 if (!_staticNode)
00129 return;
00130
00131 BVHStaticGeometry* staticTree;
00132 staticTree = new BVHStaticGeometry(_staticNode, node.getStaticData());
00133 addNode(staticTree);
00134 _staticNode = 0;
00135 }
00136
00137 void
00138 BVHSubTreeCollector::apply(const BVHStaticBinary& node,
00139 const BVHStaticData& data)
00140 {
00141 assert(!_staticNode);
00142
00143 if (!intersects(_sphere, node.getBoundingBox()))
00144 return;
00145
00146 SGVec3d corner(node.getBoundingBox().getFarestCorner(_sphere.getCenter()));
00147 if (intersects(_sphere, corner)) {
00148
00149 _staticNode = &node;
00150
00151 } else {
00152
00153
00154 node.getLeftChild()->accept(*this, data);
00155 SGSharedPtr<const BVHStaticNode> leftStaticNode = _staticNode;
00156 _staticNode = 0;
00157 node.getRightChild()->accept(*this, data);
00158 SGSharedPtr<const BVHStaticNode> rightStaticNode = _staticNode;
00159 _staticNode = 0;
00160
00161 if (leftStaticNode) {
00162 if (rightStaticNode) {
00163 BVHBoundingBoxVisitor bbv;
00164 leftStaticNode->accept(bbv, data);
00165 rightStaticNode->accept(bbv, data);
00166 _staticNode
00167 = new BVHStaticBinary(node.getSplitAxis(), leftStaticNode,
00168 rightStaticNode, bbv.getBox());
00169 } else {
00170 _staticNode = leftStaticNode;
00171 }
00172 } else {
00173 if (rightStaticNode) {
00174 _staticNode = rightStaticNode;
00175 } else {
00176
00177 }
00178 }
00179 }
00180 }
00181
00182 void
00183 BVHSubTreeCollector::apply(const BVHStaticTriangle& node,
00184 const BVHStaticData& data)
00185 {
00186 if (!intersects(_sphere, node.getTriangle(data)))
00187 return;
00188 _staticNode = &node;
00189 }
00190
00191 void
00192 BVHSubTreeCollector::addNode(BVHNode* node)
00193 {
00194 if (!node)
00195 return;
00196 if (!_nodeList.capacity())
00197 _nodeList.reserve(64);
00198 _nodeList.push_back(node);
00199 }
00200
00201 void
00202 BVHSubTreeCollector::popNodeList(NodeList& parentNodeList, BVHGroup* transform)
00203 {
00204
00205 if (!_nodeList.empty()) {
00206 NodeList::const_iterator i;
00207 for (i = _nodeList.begin(); i != _nodeList.end(); ++i)
00208 transform->addChild(*i);
00209 parentNodeList.push_back(transform);
00210 }
00211 _nodeList.swap(parentNodeList);
00212 }
00213
00214 void
00215 BVHSubTreeCollector::popNodeList(NodeList& parentNodeList)
00216 {
00217
00218 if (!_nodeList.empty()) {
00219 if (_nodeList.size() == 1) {
00220 parentNodeList.push_back(_nodeList.front());
00221 } else {
00222 BVHGroup* group = new BVHGroup;
00223 NodeList::const_iterator i;
00224 for (i = _nodeList.begin(); i != _nodeList.end(); ++i)
00225 group->addChild(*i);
00226 parentNodeList.push_back(group);
00227 }
00228 }
00229 _nodeList.swap(parentNodeList);
00230 }
00231
00232 SGSharedPtr<BVHNode>
00233 BVHSubTreeCollector::getNode() const
00234 {
00235 if (_nodeList.empty())
00236 return 0;
00237
00238 if (_nodeList.size() == 1)
00239 return _nodeList.front();
00240
00241 BVHGroup* group = new BVHGroup;
00242 NodeList::const_iterator i;
00243 for (i = _nodeList.begin(); i != _nodeList.end(); ++i)
00244 group->addChild(*i);
00245 return group;
00246 }
00247
00248 }