| 1150 | | |
| | 1167 | /// <summary> |
| | 1168 | /// |
| | 1169 | /// </summary> |
| | 1170 | /// <param name="ray"></param> |
| | 1171 | /// <param name="box"></param> |
| | 1172 | /// <param name="d1"></param> |
| | 1173 | /// <param name="d2"></param> |
| | 1174 | /// <returns></returns> |
| | 1175 | public static bool Intersects(Ray ray, AxisAlignedBox box, ref Real d1, ref Real d2) |
| | 1176 | { |
| | 1177 | if (box.IsNull) |
| | 1178 | return false; |
| | 1179 | |
| | 1180 | if (box.IsInfinite) |
| | 1181 | { |
| | 1182 | if (d1 != 0) d1 = 0; |
| | 1183 | if (d2 != 0) d2 = Real.PositiveInfinity; |
| | 1184 | return true; |
| | 1185 | } |
| | 1186 | |
| | 1187 | Vector3 min = box.Minimum; |
| | 1188 | Vector3 max = box.Maximum; |
| | 1189 | Vector3 rayorig = ray.origin; |
| | 1190 | Vector3 rayDir = ray.Direction; |
| | 1191 | |
| | 1192 | Vector3 absDir = Vector3.Zero; |
| | 1193 | absDir[0] = Abs(rayDir[0]); |
| | 1194 | absDir[1] = Abs(rayDir[1]); |
| | 1195 | absDir[2] = Abs(rayDir[2]); |
| | 1196 | |
| | 1197 | // Sort the axis, ensure check minimise floating error axis first |
| | 1198 | int imax = 0, imid = 1, imin = 2; |
| | 1199 | if (absDir[0] < absDir[2]) |
| | 1200 | { |
| | 1201 | imax = 2; |
| | 1202 | imin = 0; |
| | 1203 | } |
| | 1204 | if (absDir[1] < absDir[imin]) |
| | 1205 | { |
| | 1206 | imid = imin; |
| | 1207 | imin = 1; |
| | 1208 | } |
| | 1209 | else if (absDir[1] > absDir[imax]) |
| | 1210 | { |
| | 1211 | imid = imax; |
| | 1212 | imax = 1; |
| | 1213 | } |
| | 1214 | |
| | 1215 | Real start = 0, end = Real.PositiveInfinity; |
| | 1216 | // Check each axis in turn |
| | 1217 | |
| | 1218 | if (!CalcAxis(imax, rayDir, rayorig, min, max, ref end, ref start)) |
| | 1219 | return false; |
| | 1220 | |
| | 1221 | if (absDir[imid] < Real.Epsilon) |
| | 1222 | { |
| | 1223 | // Parallel with middle and minimise axis, check bounds only |
| | 1224 | if (rayorig[imid] < min[imid] || rayorig[imid] > max[imid] || |
| | 1225 | rayorig[imin] < min[imin] || rayorig[imin] > max[imin]) |
| | 1226 | return false; |
| | 1227 | } |
| | 1228 | else |
| | 1229 | { |
| | 1230 | if (!CalcAxis(imid, rayDir, rayorig, min, max, ref end, ref start)) |
| | 1231 | return false; |
| | 1232 | |
| | 1233 | if (absDir[imin] < Real.Epsilon) |
| | 1234 | { |
| | 1235 | // Parallel with minimise axis, check bounds only |
| | 1236 | if (rayorig[imin] < min[imin] || rayorig[imin] > max[imin]) |
| | 1237 | return false; |
| | 1238 | } |
| | 1239 | else |
| | 1240 | { |
| | 1241 | if (!CalcAxis(imin, rayDir, rayorig, min, max, ref end, ref start)) |
| | 1242 | return false; |
| | 1243 | } |
| | 1244 | } |
| | 1245 | |
| | 1246 | if (d1 != 0) d1 = start; |
| | 1247 | if (d2 != 0) d2 = end; |
| | 1248 | |
| | 1249 | return true; |
| | 1250 | } |
| | 1251 | static bool CalcAxis(int i, Vector3 raydir, Vector3 rayorig, Vector3 min, Vector3 max |
| | 1252 | , ref Real end, ref Real start) |
| | 1253 | { |
| | 1254 | Real denom = 1 / raydir[i]; |
| | 1255 | Real newstart = (min[i] - rayorig[i]) * denom; |
| | 1256 | Real newend = (max[i] - rayorig[i]) * denom; |
| | 1257 | if (newstart > newend) Swap<Real>(ref newstart, ref newend); |
| | 1258 | if (newstart > end || newend < start) return false; |
| | 1259 | if (newstart > start) start = newstart; |
| | 1260 | if (newend < end) end = newend; |
| | 1261 | |
| | 1262 | return true; |
| | 1263 | } |