| 368 | //---------------------------------------------------------------------------- |
| 369 | |
| 370 | bool Polytope::findCollision(const VectorF& vec,Polytope::Collision *best) |
| 371 | { |
| 372 | if (mVolumeList.size() <= 1) |
| 373 | return false; |
| 374 | if (!best->object) |
| 375 | best->distance = 1.0E30f; |
| 376 | S32 bestVertex = -1; |
| 377 | Polytope::Volume* bestVolume = NULL; |
| 378 | sideCount++; |
| 379 | |
| 380 | // Find the closest point |
| 381 | for (Volume* vol = mVolumeList.begin() + 1; |
| 382 | vol < mVolumeList.end(); vol++) { |
| 383 | for (S32 e = vol->edgeList; e >= 0; e = mEdgeList[e].next) { |
| 384 | Edge& edge = mEdgeList[e]; |
| 385 | if (mFaceList[edge.face[0]].original && |
| 386 | mFaceList[edge.face[1]].original) |
| 387 | continue; |
| 388 | for (S32 v = 0; v < 2; v++) { |
| 389 | S32 vi = edge.vertex[v]; |
| 390 | Vertex& vr = mVertexList[vi]; |
| 391 | if (vr.side != sideCount) { |
| 392 | vr.side = sideCount; |
| 393 | F32 dist = mDot(vr.point,vec); |
| 394 | if (dist < best->distance) { |
| 395 | best->distance = dist; |
| 396 | bestVertex = vi; |
| 397 | bestVolume = vol; |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | if (bestVertex == -1) |
| 405 | return false; |
| 406 | |
| 407 | // Fill in the return value |
| 408 | best->point = mVertexList[bestVertex].point; |
| 409 | best->object = bestVolume->object; |
| 410 | best->material = bestVolume->material; |
| 411 | |
| 412 | // Pick the best face |
| 413 | F32 bestFaceDot = 1; |
| 414 | for (S32 e = bestVolume->edgeList; e >= 0; e = mEdgeList[e].next) { |
| 415 | Edge& edge = mEdgeList[e]; |
| 416 | if (edge.vertex[0] == bestVertex || edge.vertex[1] == bestVertex) { |
| 417 | for (S32 f = 0; f < 2; f++) { |
| 418 | Face& tf = mFaceList[edge.face[f]]; |
| 419 | F32 fd = mDot(tf.plane,vec); |
| 420 | if (fd < bestFaceDot) { |
| 421 | bestFaceDot = fd; |
| 422 | best->plane = tf.plane; |
| 423 | } |
| 424 | } |
| 425 | } |
| 426 | } |
| 427 | return true; |