| 287 | } |
| 288 | |
| 289 | static bool DoRayBox(const GameVector& origin, const GameVector& target, const GameBoundingBox& bounds, |
| 290 | const Pose& objectPose, Vector3i& hitPos, int closestItemNumber) |
| 291 | { |
| 292 | auto box = bounds.ToBoundingOrientedBox(objectPose); |
| 293 | |
| 294 | auto rayOrigin = origin.ToVector3(); |
| 295 | auto rayDir = (target - origin).ToVector3(); |
| 296 | rayDir.Normalize(); |
| 297 | |
| 298 | // Don't test spheres if no intersection. |
| 299 | float dist = 0.0f; |
| 300 | if (rayDir == Vector3::Zero || !box.Intersects(rayOrigin, rayDir, dist)) |
| 301 | return false; |
| 302 | |
| 303 | // Get raw collision point. |
| 304 | auto collidedPoint = Geometry::TranslatePoint(rayOrigin, rayDir, dist); |
| 305 | hitPos.x = collidedPoint.x - objectPose.Position.x; |
| 306 | hitPos.y = collidedPoint.y - objectPose.Position.y; |
| 307 | hitPos.z = collidedPoint.z - objectPose.Position.z; |
| 308 | |
| 309 | // Test single spheres in case of items. |
| 310 | int meshIndex = 0; |
| 311 | int bit = 0; |
| 312 | int sp = -2; |
| 313 | float minDist = FLT_MAX; |
| 314 | |
| 315 | if (closestItemNumber < 0) |
| 316 | { |
| 317 | // Static meshes don't require further tests. |
| 318 | sp = -1; |
| 319 | minDist = dist; |
| 320 | } |
| 321 | else |
| 322 | { |
| 323 | // Test spheres instead for items. |
| 324 | auto* item = &g_Level.Items[closestItemNumber]; |
| 325 | auto* object = &Objects[item->ObjectNumber]; |
| 326 | |
| 327 | if (object->nmeshes <= 0) |
| 328 | return false; |
| 329 | |
| 330 | meshIndex = object->meshIndex; |
| 331 | |
| 332 | auto spheres = item->GetSpheres(); |
| 333 | for (int i = 0; i < object->nmeshes; i++) |
| 334 | { |
| 335 | // If mesh is visible. |
| 336 | if (item->MeshBits & (1 << i)) |
| 337 | { |
| 338 | const auto& sphere = spheres[i]; |
| 339 | |
| 340 | float dist = 0.0f; |
| 341 | if (sphere.Intersects(rayOrigin, rayDir, dist)) |
| 342 | { |
| 343 | // Test for minimum distance. |
| 344 | if (dist < minDist) |
| 345 | { |
| 346 | minDist = dist; |
no test coverage detected