00001
00032 #include "linden_common.h"
00033
00034 #include "math.h"
00035
00036 #include "v3math.h"
00037 #include "llquaternion.h"
00038 #include "m3math.h"
00039 #include "raytrace.h"
00040
00041
00042 BOOL line_plane(const LLVector3 &line_point, const LLVector3 &line_direction,
00043 const LLVector3 &plane_point, const LLVector3 plane_normal,
00044 LLVector3 &intersection)
00045 {
00046 F32 N = line_direction * plane_normal;
00047 if (0.0f == N)
00048 {
00049
00050
00051 return FALSE;
00052 }
00053
00054
00055
00056
00057 intersection = line_point - ((plane_normal * line_point - plane_point * plane_normal) / N) * line_direction;
00058 return TRUE;
00059 }
00060
00061
00062 BOOL ray_plane(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00063 const LLVector3 &plane_point, const LLVector3 plane_normal,
00064 LLVector3 &intersection)
00065 {
00066 F32 N = ray_direction * plane_normal;
00067 if (0.0f == N)
00068 {
00069
00070
00071 return FALSE;
00072 }
00073
00074
00075
00076
00077 F32 alpha = -(plane_normal * ray_point - plane_point * plane_normal) / N;
00078 if (alpha < 0.0f)
00079 {
00080
00081 return FALSE;
00082 }
00083 intersection = ray_point + alpha * ray_direction;
00084 return TRUE;
00085 }
00086
00087
00088 BOOL ray_circle(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00089 const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius,
00090 LLVector3 &intersection)
00091 {
00092 if (ray_plane(ray_point, ray_direction, circle_center, plane_normal, intersection))
00093 {
00094 if (circle_radius >= (intersection - circle_center).magVec())
00095 {
00096 return TRUE;
00097 }
00098 }
00099 return FALSE;
00100 }
00101
00102
00103 BOOL ray_triangle(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00104 const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
00105 LLVector3 &intersection, LLVector3 &intersection_normal)
00106 {
00107 LLVector3 side_01 = point_1 - point_0;
00108 LLVector3 side_12 = point_2 - point_1;
00109
00110 intersection_normal = side_01 % side_12;
00111 intersection_normal.normVec();
00112
00113 if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection))
00114 {
00115 LLVector3 side_20 = point_0 - point_2;
00116 if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f &&
00117 intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f &&
00118 intersection_normal * (side_20 % (intersection - point_2)) >= 0.0f)
00119 {
00120 return TRUE;
00121 }
00122 }
00123 return FALSE;
00124 }
00125
00126
00127
00128 BOOL ray_quadrangle(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00129 const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
00130 LLVector3 &intersection, LLVector3 &intersection_normal)
00131 {
00132 LLVector3 side_01 = point_1 - point_0;
00133 LLVector3 side_12 = point_2 - point_1;
00134
00135 intersection_normal = side_01 % side_12;
00136 intersection_normal.normVec();
00137
00138 if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection))
00139 {
00140 LLVector3 point_3 = point_0 + (side_12);
00141 LLVector3 side_23 = point_3 - point_2;
00142 LLVector3 side_30 = point_0 - point_3;
00143 if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f &&
00144 intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f &&
00145 intersection_normal * (side_23 % (intersection - point_2)) >= 0.0f &&
00146 intersection_normal * (side_30 % (intersection - point_3)) >= 0.0f)
00147 {
00148 return TRUE;
00149 }
00150 }
00151 return FALSE;
00152 }
00153
00154
00155 BOOL ray_sphere(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00156 const LLVector3 &sphere_center, F32 sphere_radius,
00157 LLVector3 &intersection, LLVector3 &intersection_normal)
00158 {
00159 LLVector3 ray_to_sphere = sphere_center - ray_point;
00160 F32 dot = ray_to_sphere * ray_direction;
00161
00162 LLVector3 closest_approach = dot * ray_direction - ray_to_sphere;
00163
00164 F32 shortest_distance = closest_approach.magVecSquared();
00165 F32 radius_squared = sphere_radius * sphere_radius;
00166 if (shortest_distance > radius_squared)
00167 {
00168 return FALSE;
00169 }
00170
00171 F32 half_chord = (F32) sqrt(radius_squared - shortest_distance);
00172 closest_approach = sphere_center + closest_approach;
00173 intersection = closest_approach + half_chord * ray_direction;
00174 dot = ray_direction * (intersection - ray_point);
00175 if (dot < 0.0f)
00176 {
00177
00178 return FALSE;
00179 }
00180
00181 shortest_distance = ray_direction * ((closest_approach - half_chord * ray_direction) - ray_point);
00182 if (shortest_distance > 0.0f)
00183 {
00184
00185 intersection = intersection - (2.0f * half_chord) * ray_direction;
00186 }
00187 else
00188 {
00189
00190
00191 }
00192
00193 intersection_normal = intersection - sphere_center;
00194 if (sphere_radius > 0.0f)
00195 {
00196 intersection_normal *= 1.0f / sphere_radius;
00197 }
00198 else
00199 {
00200 intersection_normal.setVec(0.0f, 0.0f, 0.0f);
00201 }
00202
00203 return TRUE;
00204 }
00205
00206
00207 BOOL ray_cylinder(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00208 const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation,
00209 LLVector3 &intersection, LLVector3 &intersection_normal)
00210 {
00211
00212 LLVector3 cyl_top(0.0f, 0.0f, 0.5f * cyl_scale.mV[VZ]);
00213 LLVector3 cyl_bottom(0.0f, 0.0f, -cyl_top.mV[VZ]);
00214 cyl_top = (cyl_top * cyl_rotation) + cyl_center;
00215 cyl_bottom = (cyl_bottom * cyl_rotation) + cyl_center;
00216
00217
00218 F32 cyl_radius = 0.5f * llmax(cyl_scale.mV[VX], cyl_scale.mV[VY]);
00219
00220
00221 LLVector3 cyl_axis;
00222 LLVector3 ray_to_cyl;
00223 F32 shortest_distance;
00224 F32 cyl_length;
00225 LLVector3 shortest_direction;
00226 LLVector3 temp_vector;
00227
00228 cyl_axis = cyl_bottom - cyl_top;
00229 cyl_length = cyl_axis.normVec();
00230 ray_to_cyl = ray_point - cyl_bottom;
00231 shortest_direction = ray_direction % cyl_axis;
00232 shortest_distance = shortest_direction.normVec();
00233
00234
00235 if (0.0f == shortest_distance)
00236 {
00237
00238 temp_vector = ray_to_cyl - (ray_to_cyl * cyl_axis) * cyl_axis;
00239 shortest_distance = temp_vector.magVec();
00240 if (shortest_distance <= cyl_radius)
00241 {
00242 shortest_distance = ray_to_cyl * cyl_axis;
00243 F32 dot = ray_direction * cyl_axis;
00244
00245 if (shortest_distance > 0.0)
00246 {
00247 if (dot > 0.0f)
00248 {
00249
00250 return FALSE;
00251 }
00252
00253 intersection = ray_point - shortest_distance * cyl_axis;
00254 intersection_normal = cyl_axis;
00255
00256 }
00257 else if (shortest_distance > -cyl_length)
00258 {
00259
00260 if (dot < 0.0f)
00261 {
00262
00263 intersection = ray_point - (cyl_length + shortest_distance) * cyl_axis;
00264 intersection_normal = -cyl_axis;
00265 }
00266 else
00267 {
00268
00269 intersection = ray_point - shortest_distance * cyl_axis;
00270 intersection_normal = cyl_axis;
00271 }
00272 }
00273 else
00274 {
00275 if (dot < 0.0f)
00276 {
00277
00278 return FALSE;
00279 }
00280
00281 intersection = ray_point - (shortest_distance + cyl_length) * cyl_axis;
00282 intersection_normal = -cyl_axis;
00283 }
00284 return TRUE;
00285 }
00286 return FALSE;
00287 }
00288
00289
00290 shortest_distance = (F32) fabs(ray_to_cyl * shortest_direction);
00291 if (shortest_distance <= cyl_radius)
00292 {
00293 F32 dist_to_closest_point;
00294 F32 half_chord_length;
00295 F32 in, out;
00296 temp_vector = ray_to_cyl % cyl_axis;
00297 dist_to_closest_point = - (temp_vector * shortest_direction);
00298 temp_vector = shortest_direction % cyl_axis;
00299 temp_vector.normVec();
00300 half_chord_length = (F32) fabs( sqrt(cyl_radius*cyl_radius - shortest_distance * shortest_distance) /
00301 (ray_direction * temp_vector) );
00302
00303 out = dist_to_closest_point + half_chord_length;
00304 if (out < 0.0f)
00305 {
00306
00307 return FALSE;
00308 }
00309
00310 in = dist_to_closest_point - half_chord_length;
00311 if (in < 0.0f)
00312 {
00313
00314
00315 intersection = ray_point + out * ray_direction;
00316 shortest_distance = out;
00317 }
00318 else
00319 {
00320
00321
00322 intersection = ray_point + in * ray_direction;
00323 shortest_distance = in;
00324 }
00325
00326
00327 if (0.0f == cyl_radius)
00328 {
00329 intersection_normal.setVec(0.0f, 0.0f, 0.0f);
00330 }
00331 else
00332 {
00333 temp_vector = intersection - cyl_bottom;
00334 intersection_normal = temp_vector - (temp_vector * cyl_axis) * cyl_axis;
00335 intersection_normal.normVec();
00336 }
00337
00338
00339
00340 if (line_plane(ray_point, ray_direction, cyl_top, -cyl_axis, temp_vector))
00341 {
00342 shortest_distance = (temp_vector - ray_point).magVec();
00343 if ( (ray_direction * cyl_axis) > 0.0f)
00344 {
00345
00346 if (shortest_distance > out)
00347 {
00348
00349 return FALSE;
00350 }
00351 if (shortest_distance > in)
00352 {
00353
00354 intersection = temp_vector;
00355 intersection_normal = -cyl_axis;
00356 return TRUE;
00357 }
00358 }
00359 else
00360 {
00361
00362 if (shortest_distance < in)
00363 {
00364
00365 return FALSE;
00366 }
00367 }
00368
00369
00370 line_plane(ray_point, ray_direction, cyl_bottom, cyl_axis, temp_vector);
00371 shortest_distance = (temp_vector - ray_point).magVec();
00372 if ( (ray_direction * cyl_axis) < 0.0)
00373 {
00374
00375 if (shortest_distance > out)
00376 {
00377
00378 return FALSE;
00379 }
00380 if (shortest_distance > in)
00381 {
00382
00383 intersection = temp_vector;
00384 intersection_normal = cyl_axis;
00385 return TRUE;
00386 }
00387 }
00388 else
00389 {
00390
00391 if (shortest_distance < in)
00392 {
00393
00394 return FALSE;
00395 }
00396 }
00397
00398 }
00399 else
00400 {
00401
00402 temp_vector = cyl_bottom - ray_point;
00403 shortest_distance = temp_vector * cyl_axis;
00404 if (shortest_distance < 0.0f || shortest_distance > cyl_length)
00405 {
00406
00407 return FALSE;
00408 }
00409 }
00410
00411 return TRUE;
00412 }
00413
00414 return FALSE;
00415 }
00416
00417
00418 U32 ray_box(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00419 const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation,
00420 LLVector3 &intersection, LLVector3 &intersection_normal)
00421 {
00422
00423
00424 LLQuaternion into_box_frame(box_rotation);
00425 into_box_frame.conjQuat();
00426 LLVector3 line_point = (ray_point - box_center) * into_box_frame;
00427 LLVector3 line_direction = ray_direction * into_box_frame;
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 LLVector3 line_plane_intersection;
00442
00443 F32 pointX = line_point.mV[VX];
00444 F32 pointY = line_point.mV[VY];
00445 F32 pointZ = line_point.mV[VZ];
00446
00447 F32 dirX = line_direction.mV[VX];
00448 F32 dirY = line_direction.mV[VY];
00449 F32 dirZ = line_direction.mV[VZ];
00450
00451
00452 F32 boxX = 0.5f * box_scale.mV[VX];
00453 F32 boxY = 0.5f * box_scale.mV[VY];
00454 F32 boxZ = 0.5f * box_scale.mV[VZ];
00455
00456
00457 if (pointX < -boxX ||
00458 pointX > boxX ||
00459 pointY < -boxY ||
00460 pointY > boxY ||
00461 pointZ < -boxZ ||
00462 pointZ > boxZ)
00463 {
00464
00465
00466
00467 if (pointX > 0.0f && dirX < 0.0f)
00468 {
00469
00470
00471
00472
00473
00474 line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction;
00475 if (line_plane_intersection.mV[VY] < boxY &&
00476 line_plane_intersection.mV[VY] > -boxY &&
00477 line_plane_intersection.mV[VZ] < boxZ &&
00478 line_plane_intersection.mV[VZ] > -boxZ )
00479 {
00480 intersection = (line_plane_intersection * box_rotation) + box_center;
00481 intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation;
00482 return FRONT_SIDE;
00483 }
00484 }
00485
00486
00487 if (pointX < 0.0f && dirX > 0.0f)
00488 {
00489
00490
00491
00492
00493
00494 line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction;
00495 if (line_plane_intersection.mV[VY] < boxY &&
00496 line_plane_intersection.mV[VY] > -boxY &&
00497 line_plane_intersection.mV[VZ] < boxZ &&
00498 line_plane_intersection.mV[VZ] > -boxZ )
00499 {
00500 intersection = (line_plane_intersection * box_rotation) + box_center;
00501 intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation;
00502 return BACK_SIDE;
00503 }
00504 }
00505
00506
00507 if (pointY > 0.0f && dirY < 0.0f)
00508 {
00509
00510
00511
00512
00513
00514 line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction;
00515
00516 if (line_plane_intersection.mV[VX] < boxX &&
00517 line_plane_intersection.mV[VX] > -boxX &&
00518 line_plane_intersection.mV[VZ] < boxZ &&
00519 line_plane_intersection.mV[VZ] > -boxZ )
00520 {
00521 intersection = (line_plane_intersection * box_rotation) + box_center;
00522 intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation;
00523 return LEFT_SIDE;
00524 }
00525 }
00526
00527
00528 if (pointY < 0.0f && dirY > 0.0f)
00529 {
00530
00531
00532
00533
00534
00535 line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction;
00536 if (line_plane_intersection.mV[VX] < boxX &&
00537 line_plane_intersection.mV[VX] > -boxX &&
00538 line_plane_intersection.mV[VZ] < boxZ &&
00539 line_plane_intersection.mV[VZ] > -boxZ )
00540 {
00541 intersection = (line_plane_intersection * box_rotation) + box_center;
00542 intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation;
00543 return RIGHT_SIDE;
00544 }
00545 }
00546
00547
00548 if (pointZ > 0.0f && dirZ < 0.0f)
00549 {
00550
00551
00552
00553
00554
00555 line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction;
00556 if (line_plane_intersection.mV[VX] < boxX &&
00557 line_plane_intersection.mV[VX] > -boxX &&
00558 line_plane_intersection.mV[VY] < boxY &&
00559 line_plane_intersection.mV[VY] > -boxY )
00560 {
00561 intersection = (line_plane_intersection * box_rotation) + box_center;
00562 intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation;
00563 return TOP_SIDE;
00564 }
00565 }
00566
00567
00568 if (pointZ < 0.0f && dirZ > 0.0f)
00569 {
00570
00571
00572
00573
00574
00575 line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction;
00576 if (line_plane_intersection.mV[VX] < boxX &&
00577 line_plane_intersection.mV[VX] > -boxX &&
00578 line_plane_intersection.mV[VY] < boxY &&
00579 line_plane_intersection.mV[VY] > -boxY )
00580 {
00581 intersection = (line_plane_intersection * box_rotation) + box_center;
00582 intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation;
00583 return BOTTOM_SIDE;
00584 }
00585 }
00586 return NO_SIDE;
00587 }
00588
00589
00590
00591
00592 if (dirX > 0.0f)
00593 {
00594
00595
00596
00597
00598
00599 line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction;
00600 if (line_plane_intersection.mV[VY] < boxY &&
00601 line_plane_intersection.mV[VY] > -boxY &&
00602 line_plane_intersection.mV[VZ] < boxZ &&
00603 line_plane_intersection.mV[VZ] > -boxZ )
00604 {
00605 intersection = (line_plane_intersection * box_rotation) + box_center;
00606 intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation;
00607 return FRONT_SIDE;
00608 }
00609 }
00610
00611
00612 if (dirX < 0.0f)
00613 {
00614
00615
00616
00617
00618
00619 line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction;
00620 if (line_plane_intersection.mV[VY] < boxY &&
00621 line_plane_intersection.mV[VY] > -boxY &&
00622 line_plane_intersection.mV[VZ] < boxZ &&
00623 line_plane_intersection.mV[VZ] > -boxZ )
00624 {
00625 intersection = (line_plane_intersection * box_rotation) + box_center;
00626 intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation;
00627 return BACK_SIDE;
00628 }
00629 }
00630
00631
00632 if (dirY > 0.0f)
00633 {
00634
00635
00636
00637
00638
00639 line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction;
00640
00641 if (line_plane_intersection.mV[VX] < boxX &&
00642 line_plane_intersection.mV[VX] > -boxX &&
00643 line_plane_intersection.mV[VZ] < boxZ &&
00644 line_plane_intersection.mV[VZ] > -boxZ )
00645 {
00646 intersection = (line_plane_intersection * box_rotation) + box_center;
00647 intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation;
00648 return LEFT_SIDE;
00649 }
00650 }
00651
00652
00653 if (dirY < 0.0f)
00654 {
00655
00656
00657
00658
00659
00660 line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction;
00661 if (line_plane_intersection.mV[VX] < boxX &&
00662 line_plane_intersection.mV[VX] > -boxX &&
00663 line_plane_intersection.mV[VZ] < boxZ &&
00664 line_plane_intersection.mV[VZ] > -boxZ )
00665 {
00666 intersection = (line_plane_intersection * box_rotation) + box_center;
00667 intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation;
00668 return RIGHT_SIDE;
00669 }
00670 }
00671
00672
00673 if (dirZ > 0.0f)
00674 {
00675
00676
00677
00678
00679
00680 line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction;
00681 if (line_plane_intersection.mV[VX] < boxX &&
00682 line_plane_intersection.mV[VX] > -boxX &&
00683 line_plane_intersection.mV[VY] < boxY &&
00684 line_plane_intersection.mV[VY] > -boxY )
00685 {
00686 intersection = (line_plane_intersection * box_rotation) + box_center;
00687 intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation;
00688 return TOP_SIDE;
00689 }
00690 }
00691
00692
00693 if (dirZ < 0.0f)
00694 {
00695
00696
00697
00698
00699
00700 line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction;
00701 if (line_plane_intersection.mV[VX] < boxX &&
00702 line_plane_intersection.mV[VX] > -boxX &&
00703 line_plane_intersection.mV[VY] < boxY &&
00704 line_plane_intersection.mV[VY] > -boxY )
00705 {
00706 intersection = (line_plane_intersection * box_rotation) + box_center;
00707 intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation;
00708 return BOTTOM_SIDE;
00709 }
00710 }
00711
00712
00713
00714 return NO_SIDE;
00715 }
00716
00717
00718 BOOL ray_prism(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00719 const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation,
00720 LLVector3 &intersection, LLVector3 &intersection_normal)
00721 {
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 F32 x = prism_scale.mV[VX];
00736 F32 y = prism_scale.mV[VY];
00737 F32 z = prism_scale.mV[VZ];
00738
00739 F32 tx = x * 2.0f / 3.0f;
00740 F32 ty = y * 0.5f;
00741 F32 tz = z * 2.0f / 3.0f;
00742
00743 LLVector3 point0(tx-x, ty, tz);
00744 LLVector3 point1(tx-x, -ty, tz);
00745 LLVector3 point2(tx, ty, tz-z);
00746 LLVector3 point3(tx-x, ty, tz-z);
00747 LLVector3 point4(tx-x, -ty, tz-z);
00748 LLVector3 point5(tx, -ty, tz-z);
00749
00750
00751 point0 = (point0 * prism_rotation) + prism_center;
00752 point1 = (point1 * prism_rotation) + prism_center;
00753 point2 = (point2 * prism_rotation) + prism_center;
00754 point3 = (point3 * prism_rotation) + prism_center;
00755 point4 = (point4 * prism_rotation) + prism_center;
00756 point5 = (point5 * prism_rotation) + prism_center;
00757
00758
00759 BOOL b_hit = FALSE;
00760 LLVector3 face_intersection, face_normal;
00761 F32 distance_squared = 0.0f;
00762 F32 temp;
00763
00764
00765 if (ray_direction * ( (point0 - point2) % (point5 - point2)) < 0.0f &&
00766 ray_quadrangle(ray_point, ray_direction, point5, point2, point0, intersection, intersection_normal))
00767 {
00768 distance_squared = (ray_point - intersection).magVecSquared();
00769 b_hit = TRUE;
00770 }
00771
00772
00773 if (ray_direction * ( (point0 - point3) % (point2 - point3)) < 0.0f &&
00774 ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal))
00775 {
00776 if (TRUE == b_hit)
00777 {
00778 temp = (ray_point - face_intersection).magVecSquared();
00779 if (temp < distance_squared)
00780 {
00781 distance_squared = temp;
00782 intersection = face_intersection;
00783 intersection_normal = face_normal;
00784 }
00785 }
00786 else
00787 {
00788 distance_squared = (ray_point - face_intersection).magVecSquared();
00789 intersection = face_intersection;
00790 intersection_normal = face_normal;
00791 b_hit = TRUE;
00792 }
00793 }
00794
00795
00796 if (ray_direction * ( (point1 - point4) % (point3 - point4)) < 0.0f &&
00797 ray_quadrangle(ray_point, ray_direction, point3, point4, point1, face_intersection, face_normal))
00798 {
00799 if (TRUE == b_hit)
00800 {
00801 temp = (ray_point - face_intersection).magVecSquared();
00802 if (temp < distance_squared)
00803 {
00804 distance_squared = temp;
00805 intersection = face_intersection;
00806 intersection_normal = face_normal;
00807 }
00808 }
00809 else
00810 {
00811 distance_squared = (ray_point - face_intersection).magVecSquared();
00812 intersection = face_intersection;
00813 intersection_normal = face_normal;
00814 b_hit = TRUE;
00815 }
00816 }
00817
00818
00819 if (ray_direction * ( (point5 - point4) % (point1 - point4)) < 0.0f &&
00820 ray_triangle(ray_point, ray_direction, point1, point4, point5, face_intersection, face_normal))
00821 {
00822 if (TRUE == b_hit)
00823 {
00824 temp = (ray_point - face_intersection).magVecSquared();
00825 if (temp < distance_squared)
00826 {
00827 distance_squared = temp;
00828 intersection = face_intersection;
00829 intersection_normal = face_normal;
00830 }
00831 }
00832 else
00833 {
00834 distance_squared = (ray_point - face_intersection).magVecSquared();
00835 intersection = face_intersection;
00836 intersection_normal = face_normal;
00837 b_hit = TRUE;
00838 }
00839 }
00840
00841
00842 if (ray_direction * ( (point4 - point5) % (point2 - point5)) < 0.0f &&
00843 ray_quadrangle(ray_point, ray_direction, point2, point5, point4, face_intersection, face_normal))
00844 {
00845 if (TRUE == b_hit)
00846 {
00847 temp = (ray_point - face_intersection).magVecSquared();
00848 if (temp < distance_squared)
00849 {
00850 distance_squared = temp;
00851 intersection = face_intersection;
00852 intersection_normal = face_normal;
00853 }
00854 }
00855 else
00856 {
00857 distance_squared = (ray_point - face_intersection).magVecSquared();
00858 intersection = face_intersection;
00859 intersection_normal = face_normal;
00860 b_hit = TRUE;
00861 }
00862 }
00863
00864 return b_hit;
00865 }
00866
00867
00868 BOOL ray_tetrahedron(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00869 const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation,
00870 LLVector3 &intersection, LLVector3 &intersection_normal)
00871 {
00872 F32 a = 0.5f * F_SQRT3;
00873 F32 b = 1.0f / F_SQRT3;
00874 F32 c = F_SQRT2 / F_SQRT3;
00875 F32 d = 0.5f * F_SQRT3 / F_SQRT2;
00876
00877
00878
00879 F32 oo_c = 1.0f / c;
00880 a = a * oo_c;
00881 b = b * oo_c;
00882 c = 1.0f;
00883 d = d * oo_c;
00884 F32 e = 0.5f * oo_c;
00885
00886 LLVector3 point0( 0.0f, 0.0f, t_scale.mV[VZ] * d);
00887 LLVector3 point1(t_scale.mV[VX] * b, 0.0f, t_scale.mV[VZ] * (d-c));
00888 LLVector3 point2(t_scale.mV[VX] * (b-a), e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c));
00889 LLVector3 point3(t_scale.mV[VX] * (b-a), -e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c));
00890
00891
00892 point0 = (point0 * t_rotation) + t_center;
00893 point1 = (point1 * t_rotation) + t_center;
00894 point2 = (point2 * t_rotation) + t_center;
00895 point3 = (point3 * t_rotation) + t_center;
00896
00897
00898 BOOL b_hit = FALSE;
00899 LLVector3 face_intersection, face_normal;
00900 F32 distance_squared = 1.0e12f;
00901 F32 temp;
00902
00903
00904 if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f &&
00905 ray_triangle(ray_point, ray_direction, point1, point2, point0, intersection, intersection_normal))
00906 {
00907 distance_squared = (ray_point - intersection).magVecSquared();
00908 b_hit = TRUE;
00909 }
00910
00911
00912 if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f &&
00913 ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal))
00914 {
00915 if (TRUE == b_hit)
00916 {
00917 temp = (ray_point - face_intersection).magVecSquared();
00918 if (temp < distance_squared)
00919 {
00920 distance_squared = temp;
00921 intersection = face_intersection;
00922 intersection_normal = face_normal;
00923 }
00924 }
00925 else
00926 {
00927 distance_squared = (ray_point - face_intersection).magVecSquared();
00928 intersection = face_intersection;
00929 intersection_normal = face_normal;
00930 b_hit = TRUE;
00931 }
00932 }
00933
00934
00935 if (ray_direction * ( (point1 - point3) % (point0 - point3)) < 0.0f &&
00936 ray_triangle(ray_point, ray_direction, point3, point1, point0, face_intersection, face_normal))
00937 {
00938 if (TRUE == b_hit)
00939 {
00940 temp = (ray_point - face_intersection).magVecSquared();
00941 if (temp < distance_squared)
00942 {
00943 distance_squared = temp;
00944 intersection = face_intersection;
00945 intersection_normal = face_normal;
00946 }
00947 }
00948 else
00949 {
00950 distance_squared = (ray_point - face_intersection).magVecSquared();
00951 intersection = face_intersection;
00952 intersection_normal = face_normal;
00953 b_hit = TRUE;
00954 }
00955 }
00956
00957
00958 if (ray_direction * ( (point2 - point3) % (point1 - point3)) < 0.0f &&
00959 ray_triangle(ray_point, ray_direction, point3, point2, point1, face_intersection, face_normal))
00960 {
00961 if (TRUE == b_hit)
00962 {
00963 temp = (ray_point - face_intersection).magVecSquared();
00964 if (temp < distance_squared)
00965 {
00966 intersection = face_intersection;
00967 intersection_normal = face_normal;
00968 }
00969 }
00970 else
00971 {
00972 intersection = face_intersection;
00973 intersection_normal = face_normal;
00974 b_hit = TRUE;
00975 }
00976 }
00977
00978 return b_hit;
00979 }
00980
00981
00982 BOOL ray_pyramid(const LLVector3 &ray_point, const LLVector3 &ray_direction,
00983 const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation,
00984 LLVector3 &intersection, LLVector3 &intersection_normal)
00985 {
00986
00987 F32 x = 0.5f * p_scale.mV[VX];
00988 F32 y = 0.5f * p_scale.mV[VY];
00989 F32 z = 0.25f * p_scale.mV[VZ];
00990
00991 LLVector3 point0(0.0f, 0.0f, p_scale.mV[VZ] - z);
00992 LLVector3 point1( x, y, -z);
00993 LLVector3 point2(-x, y, -z);
00994 LLVector3 point3(-x, -y, -z);
00995 LLVector3 point4( x, -y, -z);
00996
00997
00998 point0 = (point0 * p_rotation) + p_center;
00999 point1 = (point1 * p_rotation) + p_center;
01000 point2 = (point2 * p_rotation) + p_center;
01001 point3 = (point3 * p_rotation) + p_center;
01002 point4 = (point4 * p_rotation) + p_center;
01003
01004
01005 BOOL b_hit = FALSE;
01006 LLVector3 face_intersection, face_normal;
01007 F32 distance_squared = 1.0e12f;
01008 F32 temp;
01009
01010
01011 if (ray_direction * ( (point1 - point4) % (point0 - point4)) < 0.0f &&
01012 ray_triangle(ray_point, ray_direction, point4, point1, point0, intersection, intersection_normal))
01013 {
01014 distance_squared = (ray_point - intersection).magVecSquared();
01015 b_hit = TRUE;
01016 }
01017
01018
01019 if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f &&
01020 ray_triangle(ray_point, ray_direction, point1, point2, point0, face_intersection, face_normal))
01021 {
01022 if (TRUE == b_hit)
01023 {
01024 temp = (ray_point - face_intersection).magVecSquared();
01025 if (temp < distance_squared)
01026 {
01027 distance_squared = temp;
01028 intersection = face_intersection;
01029 intersection_normal = face_normal;
01030 }
01031 }
01032 else
01033 {
01034 distance_squared = (ray_point - face_intersection).magVecSquared();
01035 intersection = face_intersection;
01036 intersection_normal = face_normal;
01037 b_hit = TRUE;
01038 }
01039 }
01040
01041
01042 if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f &&
01043 ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal))
01044 {
01045 if (TRUE == b_hit)
01046 {
01047 temp = (ray_point - face_intersection).magVecSquared();
01048 if (temp < distance_squared)
01049 {
01050 distance_squared = temp;
01051 intersection = face_intersection;
01052 intersection_normal = face_normal;
01053 }
01054 }
01055 else
01056 {
01057 distance_squared = (ray_point - face_intersection).magVecSquared();
01058 intersection = face_intersection;
01059 intersection_normal = face_normal;
01060 b_hit = TRUE;
01061 }
01062 }
01063
01064
01065 if (ray_direction * ( (point4 - point3) % (point0 - point3)) < 0.0f &&
01066 ray_triangle(ray_point, ray_direction, point3, point4, point0, face_intersection, face_normal))
01067 {
01068 if (TRUE == b_hit)
01069 {
01070 temp = (ray_point - face_intersection).magVecSquared();
01071 if (temp < distance_squared)
01072 {
01073 distance_squared = temp;
01074 intersection = face_intersection;
01075 intersection_normal = face_normal;
01076 }
01077 }
01078 else
01079 {
01080 distance_squared = (ray_point - face_intersection).magVecSquared();
01081 intersection = face_intersection;
01082 intersection_normal = face_normal;
01083 b_hit = TRUE;
01084 }
01085 }
01086
01087
01088 if (ray_direction * ( (point3 - point4) % (point2 - point4)) < 0.0f &&
01089 ray_quadrangle(ray_point, ray_direction, point4, point3, point2, face_intersection, face_normal))
01090 {
01091 if (TRUE == b_hit)
01092 {
01093 temp = (ray_point - face_intersection).magVecSquared();
01094 if (temp < distance_squared)
01095 {
01096 intersection = face_intersection;
01097 intersection_normal = face_normal;
01098 }
01099 }
01100 else
01101 {
01102 intersection = face_intersection;
01103 intersection_normal = face_normal;
01104 b_hit = TRUE;
01105 }
01106 }
01107
01108 return b_hit;
01109 }
01110
01111
01112 BOOL linesegment_circle(const LLVector3 &point_a, const LLVector3 &point_b,
01113 const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius,
01114 LLVector3 &intersection)
01115 {
01116 LLVector3 ray_direction = point_b - point_a;
01117 F32 segment_length = ray_direction.normVec();
01118
01119 if (ray_circle(point_a, ray_direction, circle_center, plane_normal, circle_radius, intersection))
01120 {
01121 if (segment_length >= (point_a - intersection).magVec())
01122 {
01123 return TRUE;
01124 }
01125 }
01126 return FALSE;
01127 }
01128
01129
01130 BOOL linesegment_triangle(const LLVector3 &point_a, const LLVector3 &point_b,
01131 const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
01132 LLVector3 &intersection, LLVector3 &intersection_normal)
01133 {
01134 LLVector3 ray_direction = point_b - point_a;
01135 F32 segment_length = ray_direction.normVec();
01136
01137 if (ray_triangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal))
01138 {
01139 if (segment_length >= (point_a - intersection).magVec())
01140 {
01141 return TRUE;
01142 }
01143 }
01144 return FALSE;
01145 }
01146
01147
01148 BOOL linesegment_quadrangle(const LLVector3 &point_a, const LLVector3 &point_b,
01149 const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
01150 LLVector3 &intersection, LLVector3 &intersection_normal)
01151 {
01152 LLVector3 ray_direction = point_b - point_a;
01153 F32 segment_length = ray_direction.normVec();
01154
01155 if (ray_quadrangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal))
01156 {
01157 if (segment_length >= (point_a - intersection).magVec())
01158 {
01159 return TRUE;
01160 }
01161 }
01162 return FALSE;
01163 }
01164
01165
01166 BOOL linesegment_sphere(const LLVector3 &point_a, const LLVector3 &point_b,
01167 const LLVector3 &sphere_center, F32 sphere_radius,
01168 LLVector3 &intersection, LLVector3 &intersection_normal)
01169 {
01170 LLVector3 ray_direction = point_b - point_a;
01171 F32 segment_length = ray_direction.normVec();
01172
01173 if (ray_sphere(point_a, ray_direction, sphere_center, sphere_radius, intersection, intersection_normal))
01174 {
01175 if (segment_length >= (point_a - intersection).magVec())
01176 {
01177 return TRUE;
01178 }
01179 }
01180 return FALSE;
01181 }
01182
01183
01184 BOOL linesegment_cylinder(const LLVector3 &point_a, const LLVector3 &point_b,
01185 const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation,
01186 LLVector3 &intersection, LLVector3 &intersection_normal)
01187 {
01188 LLVector3 ray_direction = point_b - point_a;
01189 F32 segment_length = ray_direction.normVec();
01190
01191 if (ray_cylinder(point_a, ray_direction, cyl_center, cyl_scale, cyl_rotation, intersection, intersection_normal))
01192 {
01193 if (segment_length >= (point_a - intersection).magVec())
01194 {
01195 return TRUE;
01196 }
01197 }
01198 return FALSE;
01199 }
01200
01201
01202 U32 linesegment_box(const LLVector3 &point_a, const LLVector3 &point_b,
01203 const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation,
01204 LLVector3 &intersection, LLVector3 &intersection_normal)
01205 {
01206 LLVector3 direction = point_b - point_a;
01207 if (direction.isNull())
01208 {
01209 return NO_SIDE;
01210 }
01211
01212 F32 segment_length = direction.normVec();
01213 U32 box_side = ray_box(point_a, direction, box_center, box_scale, box_rotation, intersection, intersection_normal);
01214 if (NO_SIDE == box_side || segment_length < (intersection - point_a).magVec())
01215 {
01216 return NO_SIDE;
01217 }
01218
01219 return box_side;
01220 }
01221
01222
01223 BOOL linesegment_prism(const LLVector3 &point_a, const LLVector3 &point_b,
01224 const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation,
01225 LLVector3 &intersection, LLVector3 &intersection_normal)
01226 {
01227 LLVector3 ray_direction = point_b - point_a;
01228 F32 segment_length = ray_direction.normVec();
01229
01230 if (ray_prism(point_a, ray_direction, prism_center, prism_scale, prism_rotation, intersection, intersection_normal))
01231 {
01232 if (segment_length >= (point_a - intersection).magVec())
01233 {
01234 return TRUE;
01235 }
01236 }
01237 return FALSE;
01238 }
01239
01240
01241 BOOL linesegment_tetrahedron(const LLVector3 &point_a, const LLVector3 &point_b,
01242 const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation,
01243 LLVector3 &intersection, LLVector3 &intersection_normal)
01244 {
01245 LLVector3 ray_direction = point_b - point_a;
01246 F32 segment_length = ray_direction.normVec();
01247
01248 if (ray_tetrahedron(point_a, ray_direction, t_center, t_scale, t_rotation, intersection, intersection_normal))
01249 {
01250 if (segment_length >= (point_a - intersection).magVec())
01251 {
01252 return TRUE;
01253 }
01254 }
01255 return FALSE;
01256 }
01257
01258
01259 BOOL linesegment_pyramid(const LLVector3 &point_a, const LLVector3 &point_b,
01260 const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation,
01261 LLVector3 &intersection, LLVector3 &intersection_normal)
01262 {
01263 LLVector3 ray_direction = point_b - point_a;
01264 F32 segment_length = ray_direction.normVec();
01265
01266 if (ray_pyramid(point_a, ray_direction, p_center, p_scale, p_rotation, intersection, intersection_normal))
01267 {
01268 if (segment_length >= (point_a - intersection).magVec())
01269 {
01270 return TRUE;
01271 }
01272 }
01273 return FALSE;
01274 }
01275
01276
01277
01278
01279