http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/
| 56 | |
| 57 | // http://www.opengl-tutorial.org/miscellaneous/clicking-on-objects/picking-with-custom-ray-obb-function/ |
| 58 | f32 ray_obb_intersection(const Vector3 &from, const Vector3 &dir, const Matrix4x4 &tm, const Vector3 &half_extents) |
| 59 | { |
| 60 | f32 tmin = 0.0f; |
| 61 | f32 tmax = FLT_MAX; |
| 62 | |
| 63 | const Vector3 obb_pos = { tm.t.x, tm.t.y, tm.t.z }; |
| 64 | const Vector3 obb_scl = scale(tm); |
| 65 | const Vector3 obb_world_half = { half_extents.x * obb_scl.x, half_extents.y * obb_scl.y, half_extents.z * obb_scl.z }; |
| 66 | const Vector3 delta = obb_pos - from; |
| 67 | |
| 68 | { |
| 69 | Vector3 xaxis = { tm.x.x, tm.x.y, tm.x.z }; |
| 70 | normalize(xaxis); |
| 71 | const f32 e = dot(xaxis, delta); |
| 72 | const f32 f = dot(dir, xaxis); |
| 73 | |
| 74 | if (fabs(f) > 0.001f) { |
| 75 | f32 t1 = (e - obb_world_half.x)/f; |
| 76 | f32 t2 = (e + obb_world_half.x)/f; |
| 77 | |
| 78 | if (t1 > t2) |
| 79 | exchange(t1, t2); |
| 80 | if (t2 < tmax) |
| 81 | tmax = t2; |
| 82 | if (t1 > tmin) |
| 83 | tmin = t1; |
| 84 | |
| 85 | if (tmax < tmin) |
| 86 | return -1.0f; |
| 87 | } else { |
| 88 | if (-e - obb_world_half.x > 0.0f || -e + obb_world_half.x < 0.0f) |
| 89 | return -1.0f; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | { |
| 94 | Vector3 yaxis = { tm.y.x, tm.y.y, tm.y.z }; |
| 95 | normalize(yaxis); |
| 96 | const f32 e = dot(yaxis, delta); |
| 97 | const f32 f = dot(dir, yaxis); |
| 98 | |
| 99 | if (fabs(f) > 0.001f) { |
| 100 | f32 t1 = (e - obb_world_half.y)/f; |
| 101 | f32 t2 = (e + obb_world_half.y)/f; |
| 102 | |
| 103 | if (t1 > t2) |
| 104 | exchange(t1, t2); |
| 105 | if (t2 < tmax) |
| 106 | tmax = t2; |
| 107 | if (t1 > tmin) |
| 108 | tmin = t1; |
| 109 | |
| 110 | if (tmin > tmax) |
| 111 | return -1.0f; |
| 112 | } else { |
| 113 | if (-e - obb_world_half.y > 0.0f || -e + obb_world_half.y < 0.0f) |
| 114 | return -1.0f; |
| 115 | } |