Raycast method with feedback information
| 60 | |
| 61 | // Raycast method with feedback information |
| 62 | bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& /*allocator*/) const { |
| 63 | |
| 64 | Vector3 rayDirection = ray.point2 - ray.point1; |
| 65 | decimal tMin = DECIMAL_SMALLEST; |
| 66 | decimal tMax = DECIMAL_LARGEST; |
| 67 | Vector3 normalDirection(decimal(0), decimal(0), decimal(0)); |
| 68 | Vector3 currentNormal; |
| 69 | |
| 70 | // For each of the three slabs |
| 71 | for (int i=0; i<3; i++) { |
| 72 | |
| 73 | // If ray is parallel to the slab |
| 74 | if (std::abs(rayDirection[i]) < MACHINE_EPSILON) { |
| 75 | |
| 76 | // If the ray's origin is not inside the slab, there is no hit |
| 77 | if (ray.point1[i] > mHalfExtents[i] || ray.point1[i] < -mHalfExtents[i]) return false; |
| 78 | } |
| 79 | else { |
| 80 | |
| 81 | // Compute the intersection of the ray with the near and far plane of the slab |
| 82 | decimal oneOverD = decimal(1.0) / rayDirection[i]; |
| 83 | decimal t1 = (-mHalfExtents[i] - ray.point1[i]) * oneOverD; |
| 84 | decimal t2 = (mHalfExtents[i] - ray.point1[i]) * oneOverD; |
| 85 | currentNormal[0] = (i == 0) ? -mHalfExtents[i] : decimal(0.0); |
| 86 | currentNormal[1] = (i == 1) ? -mHalfExtents[i] : decimal(0.0); |
| 87 | currentNormal[2] = (i == 2) ? -mHalfExtents[i] : decimal(0.0); |
| 88 | |
| 89 | // Swap t1 and t2 if need so that t1 is intersection with near plane and |
| 90 | // t2 with far plane |
| 91 | if (t1 > t2) { |
| 92 | std::swap(t1, t2); |
| 93 | currentNormal = -currentNormal; |
| 94 | } |
| 95 | |
| 96 | // Compute the intersection of the of slab intersection interval with previous slabs |
| 97 | if (t1 > tMin) { |
| 98 | tMin = t1; |
| 99 | normalDirection = currentNormal; |
| 100 | } |
| 101 | tMax = std::min(tMax, t2); |
| 102 | |
| 103 | // If tMin is larger than the maximum raycasting fraction, we return no hit |
| 104 | if (tMin > ray.maxFraction) return false; |
| 105 | |
| 106 | // If the slabs intersection is empty, there is no hit |
| 107 | if (tMin > tMax) return false; |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // If tMin is negative, we return no hit |
| 112 | if (tMin < decimal(0.0) || tMin > ray.maxFraction) return false; |
| 113 | |
| 114 | // The ray intersects the three slabs, we compute the hit point |
| 115 | Vector3 localHitPoint = ray.point1 + tMin * rayDirection; |
| 116 | |
| 117 | raycastInfo.body = collider->getBody(); |
| 118 | raycastInfo.collider = collider; |
| 119 | raycastInfo.hitFraction = tMin; |