00001 #include "CollisionDetection_BVH.h"
00002
00003 using namespace VRUT;
00004 using namespace CollisionDetectionNamespace;
00005
00006
00007 CollisionDetection_BVH::~CollisionDetection_BVH(void)
00008 {
00009
00010 }
00011
00012
00013 struct QNode
00014 {
00015 BVHNode ** currentNode;
00016 std::deque<BVHNode *> * itemsPending;
00017 BVHNode * parent;
00018
00019 QNode(BVHNode ** n,
00020 std::deque<BVHNode *> * m,
00021 BVHNode * p) : currentNode(n), itemsPending(m), parent(p) {}
00022 };
00023
00024
00025 void CollisionDetection_BVH::UpdateBVH(CollisionDetection_BVHNode * node)
00026 {
00027 if (!node)
00028 node = root;
00029
00030
00032 if (node->GetTargetOrigTriangles()->empty())
00033 {
00034 if (!node->GetLChild() && node->GetRChild())
00035 {
00036 UpdateBVH(node->GetRChild());
00037 node->aabb = node->GetRChild()->aabb;
00038 }
00039 else if (!node->GetRChild() && node->GetLChild())
00040 {
00041 UpdateBVH(node->GetLChild());
00042 node->aabb = node->GetLChild()->aabb;
00043 }
00044 else if (node->GetLChild() && node->GetRChild())
00045 {
00046 UpdateBVH(node->GetLChild());
00047 UpdateBVH(node->GetRChild());
00048 node->aabb = node->GetLChild()->aabb + node->GetRChild()->aabb;
00049 }
00050 }
00051 else
00052 {
00053
00054 node->aabb.MinBound = VECTOR3(MAX_FLOAT,MAX_FLOAT,MAX_FLOAT);
00055 node->aabb.MaxBound = VECTOR3(MIN_FLOAT,MIN_FLOAT,MIN_FLOAT);
00056
00057 node->targetTriangles.clear();
00058 for (int i = 0; i < (int)node->targetTrianglesOrig.size(); i++)
00059 {
00060 node->targetTriangles.push_back(Triangle());
00061 node->targetTriangles[i].v1 = CurrMatrix.TransformCoord(node->targetTrianglesOrig[i].v1);
00062 node->targetTriangles[i].v2 = CurrMatrix.TransformCoord(node->targetTrianglesOrig[i].v2);
00063 node->targetTriangles[i].v3 = CurrMatrix.TransformCoord(node->targetTrianglesOrig[i].v3);
00064 calculateNode(node,node->targetTriangles[i]);
00065 }
00066 }
00067
00068 node->bSphere.Center = (node->aabb.MinBound + node->aabb.MaxBound) * 0.5f;
00069 node->bSphere.Radius = (node->aabb.MaxBound - node->aabb.MinBound).Length() * 0.5f;
00070 node->valid = true;
00071 }
00072
00073 struct MyQNode
00074 {
00075 CollisionDetection_BVHNode * currentNode;
00076 std::vector<Triangle>* itemsPending;
00077
00078
00079 MyQNode(CollisionDetection_BVHNode * n,
00080 std::vector<Triangle> * m) : currentNode(n), itemsPending(m) {}
00081 };
00082
00083 void CollisionDetection_BVH::Build(std::vector<Triangle> * items)
00084 {
00085
00086
00087
00088 std::vector<Triangle> * itemsPending = new std::vector<Triangle>();
00089 for (int i = 0; i < (int)items->size();i++)
00090 {
00091 itemsPending->push_back((*items)[i]);
00092 }
00093
00094
00096 std::deque<MyQNode> queue;
00097 root = new CollisionDetection_BVHNode();
00098
00099 MyQNode node(root, itemsPending);
00100 queue.push_back(node);
00101
00102 int index = 0;
00103 while (!queue.empty())
00104 {
00105
00106
00107 MyQNode qnode = queue.front();
00108 queue.pop_front();
00109
00110
00111
00112
00113
00114
00115
00116 if (qnode.itemsPending->size() <= TRIANGLES_IN_LEAF)
00117 {
00118
00119 qnode.currentNode->aabb.MinBound = VECTOR3(MAX_FLOAT,MAX_FLOAT,MAX_FLOAT);
00120 qnode.currentNode->aabb.MaxBound = VECTOR3(MIN_FLOAT,MIN_FLOAT,MIN_FLOAT);
00121
00122
00123 int i = 0;
00124 std::vector<Triangle>::iterator it = qnode.itemsPending->begin();
00125 while (i < TRIANGLES_IN_LEAF && it != qnode.itemsPending->end())
00126 {
00127
00128 Triangle triangle1 = (*it++);
00129
00130
00131
00132
00133 calculateNode(qnode.currentNode,triangle1);
00134
00135 qnode.currentNode->GetTargetOrigTriangles()->push_back(triangle1);
00136
00137 i++;
00138 }
00139
00140
00141
00142 if (qnode.itemsPending)
00143 {
00144 qnode.itemsPending->clear();
00145 delete qnode.itemsPending;
00146 }
00147
00148 continue;
00149 }
00150
00151
00152
00153 std::vector<Triangle > * geometryL = new std::vector<Triangle>;
00154 std::vector<Triangle > * geometryR = new std::vector<Triangle>;
00155
00156
00157
00158
00159
00160
00161
00162
00163 splitGeometry(qnode.currentNode, qnode.itemsPending, geometryL, geometryR);
00164
00165
00166
00167
00168
00169
00170 if (qnode.itemsPending)
00171 {
00172 qnode.itemsPending->clear();
00173 delete qnode.itemsPending;
00174
00175 }
00176
00177 if (!geometryL->empty())
00178 {
00179 qnode.currentNode->CreateLChild();
00180 queue.push_back(MyQNode(qnode.currentNode->GetLChild(), geometryL));
00181 }
00182
00183 if (!geometryR->empty())
00184 {
00185 qnode.currentNode->CreateRChild();
00186 queue.push_back(MyQNode(qnode.currentNode->GetRChild(), geometryR));
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 }
00196
00197
00198
00199
00200 }
00201
00202
00203 void CollisionDetection_BVH::calculateNode(CollisionDetection_BVHNode* node,Triangle triangle)
00204 {
00205 node->GetAABB()->MaxBound.x = std::max(node->aabb.MaxBound.x, std::max(triangle.v1.x,triangle.v2.x));
00206 node->GetAABB()->MaxBound.x = std::max(node->aabb.MaxBound.x, std::max(triangle.v2.x,triangle.v3.x));
00207
00208 node->GetAABB()->MaxBound.y = std::max(node->aabb.MaxBound.y, std::max(triangle.v1.y,triangle.v2.y));
00209 node->GetAABB()->MaxBound.y = std::max(node->aabb.MaxBound.y, std::max(triangle.v2.y,triangle.v3.y));
00210
00211 node->GetAABB()->MaxBound.z = std::max(node->aabb.MaxBound.z, std::max(triangle.v1.z,triangle.v2.z));
00212 node->GetAABB()->MaxBound.z = std::max(node->aabb.MaxBound.z, std::max(triangle.v2.z,triangle.v3.z));
00213
00214 node->GetAABB()->MinBound.x = std::min(node->aabb.MinBound.x, std::min(triangle.v1.x,triangle.v2.x));
00215 node->aabb.MinBound.x = std::min(node->aabb.MinBound.x, std::min(triangle.v2.x,triangle.v3.x));
00216
00217 node->aabb.MinBound.y = std::min(node->aabb.MinBound.y, std::min(triangle.v1.y,triangle.v2.y));
00218 node->aabb.MinBound.y = std::min(node->aabb.MinBound.y, std::min(triangle.v2.y,triangle.v3.y));
00219
00220 node->aabb.MinBound.z = std::min(node->aabb.MinBound.z, std::min(triangle.v1.z,triangle.v2.z));
00221 node->aabb.MinBound.z = std::min(node->aabb.MinBound.z, std::min(triangle.v2.z,triangle.v3.z));
00222
00223 }
00224
00225 void CollisionDetection_BVH::splitGeometry(CollisionDetection_BVHNode* pNode, const std::vector<Triangle > * geometry,
00226 std::vector<Triangle > * geometryL,
00227 std::vector<Triangle > * geometryR)
00228 {
00229
00230
00231
00232 if (geometry->empty())
00233 return;
00234
00235
00236
00237 double iMaxX, iMaxY, iMaxZ;
00238 iMaxX = iMaxY = iMaxZ = 0;
00240 pNode->aabb.MinBound = VECTOR3(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);
00241 pNode->aabb.MaxBound = VECTOR3(MIN_FLOAT,MIN_FLOAT,MIN_FLOAT);
00242
00243 std::vector<Triangle>::const_iterator it = geometry->begin();
00244 for (++it; it != geometry->end(); it++)
00245 {
00246 calculateNode(pNode,(*it));
00247 iMaxX += (*it).v1.x;
00248 iMaxY += (*it).v1.y;
00249 iMaxZ += (*it).v1.z;
00250
00251 iMaxX += (*it).v2.x;
00252 iMaxY += (*it).v2.y;
00253 iMaxZ += (*it).v2.z;
00254
00255 iMaxX += (*it).v3.x;
00256 iMaxY += (*it).v3.y;
00257 iMaxZ += (*it).v3.z;
00258 }
00259
00260 iMaxX = iMaxX / geometry->size();
00261 iMaxY = iMaxY / geometry->size();
00262 iMaxZ = iMaxZ / geometry->size();
00263
00264 double dMax = __max(iMaxX,iMaxY);
00265 dMax = __max(dMax,iMaxZ);
00266
00267
00268
00269
00270
00271
00272 VECTOR3 diag = pNode->aabb.MaxBound - pNode->aabb.MinBound;
00273 VECTOR3 center = pNode->aabb.MinBound + (diag * 0.5f);
00274
00275 int axis;
00276 if (diag.x >= __max(diag.y, diag.z))
00277 axis = X_AXIS;
00278 else if (diag.y >= __max(diag.x, diag.z))
00279 axis = Y_AXIS;
00280 else
00281 axis = Z_AXIS;
00282
00283 for (int a = 0;
00284 a < 3 && ( geometryL->empty() || geometryR->empty() );
00285 a++, axis = (axis + 1) % 3 )
00286 {
00287 geometryL->clear();
00288 geometryR->clear();
00289
00290 float axisVal = iMaxX / 2;
00291
00292 if (axis == 1)
00293 axisVal = iMaxY / 2;
00294 else if (axis == 2)
00295 axisVal = iMaxZ / 2;
00296
00297
00298
00299
00300 for (std::vector<Triangle>::const_iterator it = geometry->begin(); it != geometry->end(); it++)
00301 {
00302 if ((*it).v1._v[axis] + (*it).v2._v[axis] + (*it).v2._v[axis] < center._v[axis]*3)
00303 geometryL->push_back(*it);
00304 else
00305 geometryR->push_back(*it);
00306 }
00307
00308
00309
00310
00311 }
00312
00313
00314
00315
00316
00318 if (geometryL->empty() || geometryR->empty())
00319 {
00320 geometryL->clear();
00321 geometryR->clear();
00322 unsigned i;
00323 std::vector<Triangle>::const_iterator it = geometry->begin();
00324 for (i = 0; i < geometry->size()/2; i++, it++)
00325 geometryL->push_back(*it);
00326 for (; i < geometry->size(); i++, it++)
00327 geometryR->push_back(*it);
00328 }
00329
00330
00331 }
00332