/indra/llmath/raytrace.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1274 lines · 937 code · 134 blank · 203 comment · 152 complexity · 0a93002cc68a49502bd465c1102d0e49 MD5 · raw file

  1. /**
  2. * @file raytrace.cpp
  3. * @brief Functions called by box object scripts.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "math.h"
  28. //#include "vmath.h"
  29. #include "v3math.h"
  30. #include "llquaternion.h"
  31. #include "m3math.h"
  32. #include "raytrace.h"
  33. BOOL line_plane(const LLVector3 &line_point, const LLVector3 &line_direction,
  34. const LLVector3 &plane_point, const LLVector3 plane_normal,
  35. LLVector3 &intersection)
  36. {
  37. F32 N = line_direction * plane_normal;
  38. if (0.0f == N)
  39. {
  40. // line is perpendicular to plane normal
  41. // so it is either entirely on plane, or not on plane at all
  42. return FALSE;
  43. }
  44. // Ax + By, + Cz + D = 0
  45. // D = - (plane_point * plane_normal)
  46. // N = line_direction * plane_normal
  47. // intersection = line_point - ((D + plane_normal * line_point) / N) * line_direction
  48. intersection = line_point - ((plane_normal * line_point - plane_point * plane_normal) / N) * line_direction;
  49. return TRUE;
  50. }
  51. BOOL ray_plane(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  52. const LLVector3 &plane_point, const LLVector3 plane_normal,
  53. LLVector3 &intersection)
  54. {
  55. F32 N = ray_direction * plane_normal;
  56. if (0.0f == N)
  57. {
  58. // ray is perpendicular to plane normal
  59. // so it is either entirely on plane, or not on plane at all
  60. return FALSE;
  61. }
  62. // Ax + By, + Cz + D = 0
  63. // D = - (plane_point * plane_normal)
  64. // N = ray_direction * plane_normal
  65. // intersection = ray_point - ((D + plane_normal * ray_point) / N) * ray_direction
  66. F32 alpha = -(plane_normal * ray_point - plane_point * plane_normal) / N;
  67. if (alpha < 0.0f)
  68. {
  69. // ray points away from plane
  70. return FALSE;
  71. }
  72. intersection = ray_point + alpha * ray_direction;
  73. return TRUE;
  74. }
  75. BOOL ray_circle(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  76. const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius,
  77. LLVector3 &intersection)
  78. {
  79. if (ray_plane(ray_point, ray_direction, circle_center, plane_normal, intersection))
  80. {
  81. if (circle_radius >= (intersection - circle_center).magVec())
  82. {
  83. return TRUE;
  84. }
  85. }
  86. return FALSE;
  87. }
  88. BOOL ray_triangle(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  89. const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
  90. LLVector3 &intersection, LLVector3 &intersection_normal)
  91. {
  92. LLVector3 side_01 = point_1 - point_0;
  93. LLVector3 side_12 = point_2 - point_1;
  94. intersection_normal = side_01 % side_12;
  95. intersection_normal.normVec();
  96. if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection))
  97. {
  98. LLVector3 side_20 = point_0 - point_2;
  99. if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f &&
  100. intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f &&
  101. intersection_normal * (side_20 % (intersection - point_2)) >= 0.0f)
  102. {
  103. return TRUE;
  104. }
  105. }
  106. return FALSE;
  107. }
  108. // assumes a parallelogram
  109. BOOL ray_quadrangle(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  110. const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
  111. LLVector3 &intersection, LLVector3 &intersection_normal)
  112. {
  113. LLVector3 side_01 = point_1 - point_0;
  114. LLVector3 side_12 = point_2 - point_1;
  115. intersection_normal = side_01 % side_12;
  116. intersection_normal.normVec();
  117. if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection))
  118. {
  119. LLVector3 point_3 = point_0 + (side_12);
  120. LLVector3 side_23 = point_3 - point_2;
  121. LLVector3 side_30 = point_0 - point_3;
  122. if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f &&
  123. intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f &&
  124. intersection_normal * (side_23 % (intersection - point_2)) >= 0.0f &&
  125. intersection_normal * (side_30 % (intersection - point_3)) >= 0.0f)
  126. {
  127. return TRUE;
  128. }
  129. }
  130. return FALSE;
  131. }
  132. BOOL ray_sphere(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  133. const LLVector3 &sphere_center, F32 sphere_radius,
  134. LLVector3 &intersection, LLVector3 &intersection_normal)
  135. {
  136. LLVector3 ray_to_sphere = sphere_center - ray_point;
  137. F32 dot = ray_to_sphere * ray_direction;
  138. LLVector3 closest_approach = dot * ray_direction - ray_to_sphere;
  139. F32 shortest_distance = closest_approach.magVecSquared();
  140. F32 radius_squared = sphere_radius * sphere_radius;
  141. if (shortest_distance > radius_squared)
  142. {
  143. return FALSE;
  144. }
  145. F32 half_chord = (F32) sqrt(radius_squared - shortest_distance);
  146. closest_approach = sphere_center + closest_approach; // closest_approach now in absolute coordinates
  147. intersection = closest_approach + half_chord * ray_direction;
  148. dot = ray_direction * (intersection - ray_point);
  149. if (dot < 0.0f)
  150. {
  151. // ray shoots away from sphere and is not inside it
  152. return FALSE;
  153. }
  154. shortest_distance = ray_direction * ((closest_approach - half_chord * ray_direction) - ray_point);
  155. if (shortest_distance > 0.0f)
  156. {
  157. // ray enters sphere
  158. intersection = intersection - (2.0f * half_chord) * ray_direction;
  159. }
  160. else
  161. {
  162. // do nothing
  163. // ray starts inside sphere and intersects as it leaves the sphere
  164. }
  165. intersection_normal = intersection - sphere_center;
  166. if (sphere_radius > 0.0f)
  167. {
  168. intersection_normal *= 1.0f / sphere_radius;
  169. }
  170. else
  171. {
  172. intersection_normal.setVec(0.0f, 0.0f, 0.0f);
  173. }
  174. return TRUE;
  175. }
  176. BOOL ray_cylinder(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  177. const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation,
  178. LLVector3 &intersection, LLVector3 &intersection_normal)
  179. {
  180. // calculate the centers of the cylinder caps in the absolute frame
  181. LLVector3 cyl_top(0.0f, 0.0f, 0.5f * cyl_scale.mV[VZ]);
  182. LLVector3 cyl_bottom(0.0f, 0.0f, -cyl_top.mV[VZ]);
  183. cyl_top = (cyl_top * cyl_rotation) + cyl_center;
  184. cyl_bottom = (cyl_bottom * cyl_rotation) + cyl_center;
  185. // we only handle cylinders with circular cross-sections at the moment
  186. F32 cyl_radius = 0.5f * llmax(cyl_scale.mV[VX], cyl_scale.mV[VY]); // HACK until scaled cylinders are supported
  187. // This implementation is based on the intcyl() function from Graphics_Gems_IV, page 361
  188. LLVector3 cyl_axis; // axis direction (bottom toward top)
  189. LLVector3 ray_to_cyl; // ray_point to cyl_top
  190. F32 shortest_distance; // shortest distance from ray to axis
  191. F32 cyl_length;
  192. LLVector3 shortest_direction;
  193. LLVector3 temp_vector;
  194. cyl_axis = cyl_bottom - cyl_top;
  195. cyl_length = cyl_axis.normVec();
  196. ray_to_cyl = ray_point - cyl_bottom;
  197. shortest_direction = ray_direction % cyl_axis;
  198. shortest_distance = shortest_direction.normVec(); // recycle shortest_distance
  199. // check for ray parallel to cylinder axis
  200. if (0.0f == shortest_distance)
  201. {
  202. // ray is parallel to cylinder axis
  203. temp_vector = ray_to_cyl - (ray_to_cyl * cyl_axis) * cyl_axis;
  204. shortest_distance = temp_vector.magVec();
  205. if (shortest_distance <= cyl_radius)
  206. {
  207. shortest_distance = ray_to_cyl * cyl_axis;
  208. F32 dot = ray_direction * cyl_axis;
  209. if (shortest_distance > 0.0)
  210. {
  211. if (dot > 0.0f)
  212. {
  213. // ray points away from cylinder bottom
  214. return FALSE;
  215. }
  216. // ray hit bottom of cylinder from outside
  217. intersection = ray_point - shortest_distance * cyl_axis;
  218. intersection_normal = cyl_axis;
  219. }
  220. else if (shortest_distance > -cyl_length)
  221. {
  222. // ray starts inside cylinder
  223. if (dot < 0.0f)
  224. {
  225. // ray hit top from inside
  226. intersection = ray_point - (cyl_length + shortest_distance) * cyl_axis;
  227. intersection_normal = -cyl_axis;
  228. }
  229. else
  230. {
  231. // ray hit bottom from inside
  232. intersection = ray_point - shortest_distance * cyl_axis;
  233. intersection_normal = cyl_axis;
  234. }
  235. }
  236. else
  237. {
  238. if (dot < 0.0f)
  239. {
  240. // ray points away from cylinder bottom
  241. return FALSE;
  242. }
  243. // ray hit top from outside
  244. intersection = ray_point - (shortest_distance + cyl_length) * cyl_axis;
  245. intersection_normal = -cyl_axis;
  246. }
  247. return TRUE;
  248. }
  249. return FALSE;
  250. }
  251. // check for intersection with infinite cylinder
  252. shortest_distance = (F32) fabs(ray_to_cyl * shortest_direction);
  253. if (shortest_distance <= cyl_radius)
  254. {
  255. F32 dist_to_closest_point; // dist from ray_point to closest_point
  256. F32 half_chord_length; // half length of intersection chord
  257. F32 in, out; // distances to entering/exiting points
  258. temp_vector = ray_to_cyl % cyl_axis;
  259. dist_to_closest_point = - (temp_vector * shortest_direction);
  260. temp_vector = shortest_direction % cyl_axis;
  261. temp_vector.normVec();
  262. half_chord_length = (F32) fabs( sqrt(cyl_radius*cyl_radius - shortest_distance * shortest_distance) /
  263. (ray_direction * temp_vector) );
  264. out = dist_to_closest_point + half_chord_length; // dist to exiting point
  265. if (out < 0.0f)
  266. {
  267. // cylinder is behind the ray, so we return FALSE
  268. return FALSE;
  269. }
  270. in = dist_to_closest_point - half_chord_length; // dist to entering point
  271. if (in < 0.0f)
  272. {
  273. // ray_point is inside the cylinder
  274. // so we store the exiting intersection
  275. intersection = ray_point + out * ray_direction;
  276. shortest_distance = out;
  277. }
  278. else
  279. {
  280. // ray hit cylinder from outside
  281. // so we store the entering intersection
  282. intersection = ray_point + in * ray_direction;
  283. shortest_distance = in;
  284. }
  285. // calculate the normal at intersection
  286. if (0.0f == cyl_radius)
  287. {
  288. intersection_normal.setVec(0.0f, 0.0f, 0.0f);
  289. }
  290. else
  291. {
  292. temp_vector = intersection - cyl_bottom;
  293. intersection_normal = temp_vector - (temp_vector * cyl_axis) * cyl_axis;
  294. intersection_normal.normVec();
  295. }
  296. // check for intersection with end caps
  297. // calculate intersection of ray and top plane
  298. if (line_plane(ray_point, ray_direction, cyl_top, -cyl_axis, temp_vector)) // NOTE side-effect: changing temp_vector
  299. {
  300. shortest_distance = (temp_vector - ray_point).magVec();
  301. if ( (ray_direction * cyl_axis) > 0.0f)
  302. {
  303. // ray potentially enters the cylinder at top
  304. if (shortest_distance > out)
  305. {
  306. // ray missed the finite cylinder
  307. return FALSE;
  308. }
  309. if (shortest_distance > in)
  310. {
  311. // ray intersects cylinder at top plane
  312. intersection = temp_vector;
  313. intersection_normal = -cyl_axis;
  314. return TRUE;
  315. }
  316. }
  317. else
  318. {
  319. // ray potentially exits the cylinder at top
  320. if (shortest_distance < in)
  321. {
  322. // missed the finite cylinder
  323. return FALSE;
  324. }
  325. }
  326. // calculate intersection of ray and bottom plane
  327. line_plane(ray_point, ray_direction, cyl_bottom, cyl_axis, temp_vector); // NOTE side-effect: changing temp_vector
  328. shortest_distance = (temp_vector - ray_point).magVec();
  329. if ( (ray_direction * cyl_axis) < 0.0)
  330. {
  331. // ray potentially enters the cylinder at bottom
  332. if (shortest_distance > out)
  333. {
  334. // ray missed the finite cylinder
  335. return FALSE;
  336. }
  337. if (shortest_distance > in)
  338. {
  339. // ray intersects cylinder at bottom plane
  340. intersection = temp_vector;
  341. intersection_normal = cyl_axis;
  342. return TRUE;
  343. }
  344. }
  345. else
  346. {
  347. // ray potentially exits the cylinder at bottom
  348. if (shortest_distance < in)
  349. {
  350. // ray missed the finite cylinder
  351. return FALSE;
  352. }
  353. }
  354. }
  355. else
  356. {
  357. // ray is parallel to end cap planes
  358. temp_vector = cyl_bottom - ray_point;
  359. shortest_distance = temp_vector * cyl_axis;
  360. if (shortest_distance < 0.0f || shortest_distance > cyl_length)
  361. {
  362. // ray missed finite cylinder
  363. return FALSE;
  364. }
  365. }
  366. return TRUE;
  367. }
  368. return FALSE;
  369. }
  370. U32 ray_box(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  371. const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation,
  372. LLVector3 &intersection, LLVector3 &intersection_normal)
  373. {
  374. // Need to rotate into box frame
  375. LLQuaternion into_box_frame(box_rotation); // rotates things from box frame to absolute
  376. into_box_frame.conjQuat(); // now rotates things into box frame
  377. LLVector3 line_point = (ray_point - box_center) * into_box_frame;
  378. LLVector3 line_direction = ray_direction * into_box_frame;
  379. // Suppose we have a plane: Ax + By + Cz + D = 0
  380. // then, assuming [A, B, C] is a unit vector:
  381. //
  382. // plane_normal = [A, B, C]
  383. // D = - (plane_normal * plane_point)
  384. //
  385. // Suppose we have a line: X = line_point + alpha * line_direction
  386. //
  387. // the intersection of the plane and line determines alpha
  388. //
  389. // alpha = - (D + plane_normal * line_point) / (plane_normal * line_direction)
  390. LLVector3 line_plane_intersection;
  391. F32 pointX = line_point.mV[VX];
  392. F32 pointY = line_point.mV[VY];
  393. F32 pointZ = line_point.mV[VZ];
  394. F32 dirX = line_direction.mV[VX];
  395. F32 dirY = line_direction.mV[VY];
  396. F32 dirZ = line_direction.mV[VZ];
  397. // we'll be using the half-scales of the box
  398. F32 boxX = 0.5f * box_scale.mV[VX];
  399. F32 boxY = 0.5f * box_scale.mV[VY];
  400. F32 boxZ = 0.5f * box_scale.mV[VZ];
  401. // check to see if line_point is OUTSIDE the box
  402. if (pointX < -boxX ||
  403. pointX > boxX ||
  404. pointY < -boxY ||
  405. pointY > boxY ||
  406. pointZ < -boxZ ||
  407. pointZ > boxZ)
  408. {
  409. // -------------- point is OUTSIDE the box ----------------
  410. // front
  411. if (pointX > 0.0f && dirX < 0.0f)
  412. {
  413. // plane_normal = [ 1, 0, 0]
  414. // plane_normal*line_point = pointX
  415. // plane_normal*line_direction = dirX
  416. // D = -boxX
  417. // alpha = - (-boxX + pointX) / dirX
  418. line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction;
  419. if (line_plane_intersection.mV[VY] < boxY &&
  420. line_plane_intersection.mV[VY] > -boxY &&
  421. line_plane_intersection.mV[VZ] < boxZ &&
  422. line_plane_intersection.mV[VZ] > -boxZ )
  423. {
  424. intersection = (line_plane_intersection * box_rotation) + box_center;
  425. intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation;
  426. return FRONT_SIDE;
  427. }
  428. }
  429. // back
  430. if (pointX < 0.0f && dirX > 0.0f)
  431. {
  432. // plane_normal = [ -1, 0, 0]
  433. // plane_normal*line_point = -pX
  434. // plane_normal*line_direction = -direction.mV[VX]
  435. // D = -bX
  436. // alpha = - (-bX - pX) / (-dirX)
  437. line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction;
  438. if (line_plane_intersection.mV[VY] < boxY &&
  439. line_plane_intersection.mV[VY] > -boxY &&
  440. line_plane_intersection.mV[VZ] < boxZ &&
  441. line_plane_intersection.mV[VZ] > -boxZ )
  442. {
  443. intersection = (line_plane_intersection * box_rotation) + box_center;
  444. intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation;
  445. return BACK_SIDE;
  446. }
  447. }
  448. // left
  449. if (pointY > 0.0f && dirY < 0.0f)
  450. {
  451. // plane_normal = [0, 1, 0]
  452. // plane_normal*line_point = pointY
  453. // plane_normal*line_direction = dirY
  454. // D = -boxY
  455. // alpha = - (-boxY + pointY) / dirY
  456. line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction;
  457. if (line_plane_intersection.mV[VX] < boxX &&
  458. line_plane_intersection.mV[VX] > -boxX &&
  459. line_plane_intersection.mV[VZ] < boxZ &&
  460. line_plane_intersection.mV[VZ] > -boxZ )
  461. {
  462. intersection = (line_plane_intersection * box_rotation) + box_center;
  463. intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation;
  464. return LEFT_SIDE;
  465. }
  466. }
  467. // right
  468. if (pointY < 0.0f && dirY > 0.0f)
  469. {
  470. // plane_normal = [0, -1, 0]
  471. // plane_normal*line_point = -pointY
  472. // plane_normal*line_direction = -dirY
  473. // D = -boxY
  474. // alpha = - (-boxY - pointY) / (-dirY)
  475. line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction;
  476. if (line_plane_intersection.mV[VX] < boxX &&
  477. line_plane_intersection.mV[VX] > -boxX &&
  478. line_plane_intersection.mV[VZ] < boxZ &&
  479. line_plane_intersection.mV[VZ] > -boxZ )
  480. {
  481. intersection = (line_plane_intersection * box_rotation) + box_center;
  482. intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation;
  483. return RIGHT_SIDE;
  484. }
  485. }
  486. // top
  487. if (pointZ > 0.0f && dirZ < 0.0f)
  488. {
  489. // plane_normal = [0, 0, 1]
  490. // plane_normal*line_point = pointZ
  491. // plane_normal*line_direction = dirZ
  492. // D = -boxZ
  493. // alpha = - (-boxZ + pointZ) / dirZ
  494. line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction;
  495. if (line_plane_intersection.mV[VX] < boxX &&
  496. line_plane_intersection.mV[VX] > -boxX &&
  497. line_plane_intersection.mV[VY] < boxY &&
  498. line_plane_intersection.mV[VY] > -boxY )
  499. {
  500. intersection = (line_plane_intersection * box_rotation) + box_center;
  501. intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation;
  502. return TOP_SIDE;
  503. }
  504. }
  505. // bottom
  506. if (pointZ < 0.0f && dirZ > 0.0f)
  507. {
  508. // plane_normal = [0, 0, -1]
  509. // plane_normal*line_point = -pointZ
  510. // plane_normal*line_direction = -dirZ
  511. // D = -boxZ
  512. // alpha = - (-boxZ - pointZ) / (-dirZ)
  513. line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction;
  514. if (line_plane_intersection.mV[VX] < boxX &&
  515. line_plane_intersection.mV[VX] > -boxX &&
  516. line_plane_intersection.mV[VY] < boxY &&
  517. line_plane_intersection.mV[VY] > -boxY )
  518. {
  519. intersection = (line_plane_intersection * box_rotation) + box_center;
  520. intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation;
  521. return BOTTOM_SIDE;
  522. }
  523. }
  524. return NO_SIDE;
  525. }
  526. // -------------- point is INSIDE the box ----------------
  527. // front
  528. if (dirX > 0.0f)
  529. {
  530. // plane_normal = [ 1, 0, 0]
  531. // plane_normal*line_point = pointX
  532. // plane_normal*line_direction = dirX
  533. // D = -boxX
  534. // alpha = - (-boxX + pointX) / dirX
  535. line_plane_intersection = line_point - ((pointX - boxX) / dirX) * line_direction;
  536. if (line_plane_intersection.mV[VY] < boxY &&
  537. line_plane_intersection.mV[VY] > -boxY &&
  538. line_plane_intersection.mV[VZ] < boxZ &&
  539. line_plane_intersection.mV[VZ] > -boxZ )
  540. {
  541. intersection = (line_plane_intersection * box_rotation) + box_center;
  542. intersection_normal = LLVector3(1.0f, 0.0f, 0.0f) * box_rotation;
  543. return FRONT_SIDE;
  544. }
  545. }
  546. // back
  547. if (dirX < 0.0f)
  548. {
  549. // plane_normal = [ -1, 0, 0]
  550. // plane_normal*line_point = -pX
  551. // plane_normal*line_direction = -direction.mV[VX]
  552. // D = -bX
  553. // alpha = - (-bX - pX) / (-dirX)
  554. line_plane_intersection = line_point - ((boxX + pointX)/ dirX) * line_direction;
  555. if (line_plane_intersection.mV[VY] < boxY &&
  556. line_plane_intersection.mV[VY] > -boxY &&
  557. line_plane_intersection.mV[VZ] < boxZ &&
  558. line_plane_intersection.mV[VZ] > -boxZ )
  559. {
  560. intersection = (line_plane_intersection * box_rotation) + box_center;
  561. intersection_normal = LLVector3(-1.0f, 0.0f, 0.0f) * box_rotation;
  562. return BACK_SIDE;
  563. }
  564. }
  565. // left
  566. if (dirY > 0.0f)
  567. {
  568. // plane_normal = [0, 1, 0]
  569. // plane_normal*line_point = pointY
  570. // plane_normal*line_direction = dirY
  571. // D = -boxY
  572. // alpha = - (-boxY + pointY) / dirY
  573. line_plane_intersection = line_point + ((boxY - pointY)/dirY) * line_direction;
  574. if (line_plane_intersection.mV[VX] < boxX &&
  575. line_plane_intersection.mV[VX] > -boxX &&
  576. line_plane_intersection.mV[VZ] < boxZ &&
  577. line_plane_intersection.mV[VZ] > -boxZ )
  578. {
  579. intersection = (line_plane_intersection * box_rotation) + box_center;
  580. intersection_normal = LLVector3(0.0f, 1.0f, 0.0f) * box_rotation;
  581. return LEFT_SIDE;
  582. }
  583. }
  584. // right
  585. if (dirY < 0.0f)
  586. {
  587. // plane_normal = [0, -1, 0]
  588. // plane_normal*line_point = -pointY
  589. // plane_normal*line_direction = -dirY
  590. // D = -boxY
  591. // alpha = - (-boxY - pointY) / (-dirY)
  592. line_plane_intersection = line_point - ((boxY + pointY)/dirY) * line_direction;
  593. if (line_plane_intersection.mV[VX] < boxX &&
  594. line_plane_intersection.mV[VX] > -boxX &&
  595. line_plane_intersection.mV[VZ] < boxZ &&
  596. line_plane_intersection.mV[VZ] > -boxZ )
  597. {
  598. intersection = (line_plane_intersection * box_rotation) + box_center;
  599. intersection_normal = LLVector3(0.0f, -1.0f, 0.0f) * box_rotation;
  600. return RIGHT_SIDE;
  601. }
  602. }
  603. // top
  604. if (dirZ > 0.0f)
  605. {
  606. // plane_normal = [0, 0, 1]
  607. // plane_normal*line_point = pointZ
  608. // plane_normal*line_direction = dirZ
  609. // D = -boxZ
  610. // alpha = - (-boxZ + pointZ) / dirZ
  611. line_plane_intersection = line_point - ((pointZ - boxZ)/dirZ) * line_direction;
  612. if (line_plane_intersection.mV[VX] < boxX &&
  613. line_plane_intersection.mV[VX] > -boxX &&
  614. line_plane_intersection.mV[VY] < boxY &&
  615. line_plane_intersection.mV[VY] > -boxY )
  616. {
  617. intersection = (line_plane_intersection * box_rotation) + box_center;
  618. intersection_normal = LLVector3(0.0f, 0.0f, 1.0f) * box_rotation;
  619. return TOP_SIDE;
  620. }
  621. }
  622. // bottom
  623. if (dirZ < 0.0f)
  624. {
  625. // plane_normal = [0, 0, -1]
  626. // plane_normal*line_point = -pointZ
  627. // plane_normal*line_direction = -dirZ
  628. // D = -boxZ
  629. // alpha = - (-boxZ - pointZ) / (-dirZ)
  630. line_plane_intersection = line_point - ((boxZ + pointZ)/dirZ) * line_direction;
  631. if (line_plane_intersection.mV[VX] < boxX &&
  632. line_plane_intersection.mV[VX] > -boxX &&
  633. line_plane_intersection.mV[VY] < boxY &&
  634. line_plane_intersection.mV[VY] > -boxY )
  635. {
  636. intersection = (line_plane_intersection * box_rotation) + box_center;
  637. intersection_normal = LLVector3(0.0f, 0.0f, -1.0f) * box_rotation;
  638. return BOTTOM_SIDE;
  639. }
  640. }
  641. // should never get here unless line instersects at tangent point on edge or corner
  642. // however such cases will be EXTREMELY rare
  643. return NO_SIDE;
  644. }
  645. BOOL ray_prism(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  646. const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation,
  647. LLVector3 &intersection, LLVector3 &intersection_normal)
  648. {
  649. // (0) Z
  650. // /| \ .
  651. // (1)| \ /|\ _.Y
  652. // | \ \ | /|
  653. // | |\ \ | /
  654. // | | \(0)\ | /
  655. // | | \ \ |/
  656. // | | \ \ (*)----> X
  657. // |(3)---\---(2)
  658. // |/ \ /
  659. // (4)-------(5)
  660. // need to calculate the points of the prism so we can run ray tests with each face
  661. F32 x = prism_scale.mV[VX];
  662. F32 y = prism_scale.mV[VY];
  663. F32 z = prism_scale.mV[VZ];
  664. F32 tx = x * 2.0f / 3.0f;
  665. F32 ty = y * 0.5f;
  666. F32 tz = z * 2.0f / 3.0f;
  667. LLVector3 point0(tx-x, ty, tz);
  668. LLVector3 point1(tx-x, -ty, tz);
  669. LLVector3 point2(tx, ty, tz-z);
  670. LLVector3 point3(tx-x, ty, tz-z);
  671. LLVector3 point4(tx-x, -ty, tz-z);
  672. LLVector3 point5(tx, -ty, tz-z);
  673. // transform these points into absolute frame
  674. point0 = (point0 * prism_rotation) + prism_center;
  675. point1 = (point1 * prism_rotation) + prism_center;
  676. point2 = (point2 * prism_rotation) + prism_center;
  677. point3 = (point3 * prism_rotation) + prism_center;
  678. point4 = (point4 * prism_rotation) + prism_center;
  679. point5 = (point5 * prism_rotation) + prism_center;
  680. // test ray intersection for each face
  681. BOOL b_hit = FALSE;
  682. LLVector3 face_intersection, face_normal;
  683. F32 distance_squared = 0.0f;
  684. F32 temp;
  685. // face 0
  686. if (ray_direction * ( (point0 - point2) % (point5 - point2)) < 0.0f &&
  687. ray_quadrangle(ray_point, ray_direction, point5, point2, point0, intersection, intersection_normal))
  688. {
  689. distance_squared = (ray_point - intersection).magVecSquared();
  690. b_hit = TRUE;
  691. }
  692. // face 1
  693. if (ray_direction * ( (point0 - point3) % (point2 - point3)) < 0.0f &&
  694. ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal))
  695. {
  696. if (TRUE == b_hit)
  697. {
  698. temp = (ray_point - face_intersection).magVecSquared();
  699. if (temp < distance_squared)
  700. {
  701. distance_squared = temp;
  702. intersection = face_intersection;
  703. intersection_normal = face_normal;
  704. }
  705. }
  706. else
  707. {
  708. distance_squared = (ray_point - face_intersection).magVecSquared();
  709. intersection = face_intersection;
  710. intersection_normal = face_normal;
  711. b_hit = TRUE;
  712. }
  713. }
  714. // face 2
  715. if (ray_direction * ( (point1 - point4) % (point3 - point4)) < 0.0f &&
  716. ray_quadrangle(ray_point, ray_direction, point3, point4, point1, face_intersection, face_normal))
  717. {
  718. if (TRUE == b_hit)
  719. {
  720. temp = (ray_point - face_intersection).magVecSquared();
  721. if (temp < distance_squared)
  722. {
  723. distance_squared = temp;
  724. intersection = face_intersection;
  725. intersection_normal = face_normal;
  726. }
  727. }
  728. else
  729. {
  730. distance_squared = (ray_point - face_intersection).magVecSquared();
  731. intersection = face_intersection;
  732. intersection_normal = face_normal;
  733. b_hit = TRUE;
  734. }
  735. }
  736. // face 3
  737. if (ray_direction * ( (point5 - point4) % (point1 - point4)) < 0.0f &&
  738. ray_triangle(ray_point, ray_direction, point1, point4, point5, face_intersection, face_normal))
  739. {
  740. if (TRUE == b_hit)
  741. {
  742. temp = (ray_point - face_intersection).magVecSquared();
  743. if (temp < distance_squared)
  744. {
  745. distance_squared = temp;
  746. intersection = face_intersection;
  747. intersection_normal = face_normal;
  748. }
  749. }
  750. else
  751. {
  752. distance_squared = (ray_point - face_intersection).magVecSquared();
  753. intersection = face_intersection;
  754. intersection_normal = face_normal;
  755. b_hit = TRUE;
  756. }
  757. }
  758. // face 4
  759. if (ray_direction * ( (point4 - point5) % (point2 - point5)) < 0.0f &&
  760. ray_quadrangle(ray_point, ray_direction, point2, point5, point4, face_intersection, face_normal))
  761. {
  762. if (TRUE == b_hit)
  763. {
  764. temp = (ray_point - face_intersection).magVecSquared();
  765. if (temp < distance_squared)
  766. {
  767. distance_squared = temp;
  768. intersection = face_intersection;
  769. intersection_normal = face_normal;
  770. }
  771. }
  772. else
  773. {
  774. distance_squared = (ray_point - face_intersection).magVecSquared();
  775. intersection = face_intersection;
  776. intersection_normal = face_normal;
  777. b_hit = TRUE;
  778. }
  779. }
  780. return b_hit;
  781. }
  782. BOOL ray_tetrahedron(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  783. const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation,
  784. LLVector3 &intersection, LLVector3 &intersection_normal)
  785. {
  786. F32 a = 0.5f * F_SQRT3; // height of unit triangle
  787. F32 b = 1.0f / F_SQRT3; // distance of center of unit triangle to each point
  788. F32 c = F_SQRT2 / F_SQRT3; // height of unit tetrahedron
  789. F32 d = 0.5f * F_SQRT3 / F_SQRT2; // distance of center of tetrahedron to each point
  790. // if we want the tetrahedron to have unit height (c = 1.0) then we need to divide
  791. // each constant by hieght of a unit tetrahedron
  792. F32 oo_c = 1.0f / c;
  793. a = a * oo_c;
  794. b = b * oo_c;
  795. c = 1.0f;
  796. d = d * oo_c;
  797. F32 e = 0.5f * oo_c;
  798. LLVector3 point0( 0.0f, 0.0f, t_scale.mV[VZ] * d);
  799. LLVector3 point1(t_scale.mV[VX] * b, 0.0f, t_scale.mV[VZ] * (d-c));
  800. LLVector3 point2(t_scale.mV[VX] * (b-a), e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c));
  801. LLVector3 point3(t_scale.mV[VX] * (b-a), -e * t_scale.mV[VY], t_scale.mV[VZ] * (d-c));
  802. // transform these points into absolute frame
  803. point0 = (point0 * t_rotation) + t_center;
  804. point1 = (point1 * t_rotation) + t_center;
  805. point2 = (point2 * t_rotation) + t_center;
  806. point3 = (point3 * t_rotation) + t_center;
  807. // test ray intersection for each face
  808. BOOL b_hit = FALSE;
  809. LLVector3 face_intersection, face_normal;
  810. F32 distance_squared = 1.0e12f;
  811. F32 temp;
  812. // face 0
  813. if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f &&
  814. ray_triangle(ray_point, ray_direction, point1, point2, point0, intersection, intersection_normal))
  815. {
  816. distance_squared = (ray_point - intersection).magVecSquared();
  817. b_hit = TRUE;
  818. }
  819. // face 1
  820. if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f &&
  821. ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal))
  822. {
  823. if (TRUE == b_hit)
  824. {
  825. temp = (ray_point - face_intersection).magVecSquared();
  826. if (temp < distance_squared)
  827. {
  828. distance_squared = temp;
  829. intersection = face_intersection;
  830. intersection_normal = face_normal;
  831. }
  832. }
  833. else
  834. {
  835. distance_squared = (ray_point - face_intersection).magVecSquared();
  836. intersection = face_intersection;
  837. intersection_normal = face_normal;
  838. b_hit = TRUE;
  839. }
  840. }
  841. // face 2
  842. if (ray_direction * ( (point1 - point3) % (point0 - point3)) < 0.0f &&
  843. ray_triangle(ray_point, ray_direction, point3, point1, point0, face_intersection, face_normal))
  844. {
  845. if (TRUE == b_hit)
  846. {
  847. temp = (ray_point - face_intersection).magVecSquared();
  848. if (temp < distance_squared)
  849. {
  850. distance_squared = temp;
  851. intersection = face_intersection;
  852. intersection_normal = face_normal;
  853. }
  854. }
  855. else
  856. {
  857. distance_squared = (ray_point - face_intersection).magVecSquared();
  858. intersection = face_intersection;
  859. intersection_normal = face_normal;
  860. b_hit = TRUE;
  861. }
  862. }
  863. // face 3
  864. if (ray_direction * ( (point2 - point3) % (point1 - point3)) < 0.0f &&
  865. ray_triangle(ray_point, ray_direction, point3, point2, point1, face_intersection, face_normal))
  866. {
  867. if (TRUE == b_hit)
  868. {
  869. temp = (ray_point - face_intersection).magVecSquared();
  870. if (temp < distance_squared)
  871. {
  872. intersection = face_intersection;
  873. intersection_normal = face_normal;
  874. }
  875. }
  876. else
  877. {
  878. intersection = face_intersection;
  879. intersection_normal = face_normal;
  880. b_hit = TRUE;
  881. }
  882. }
  883. return b_hit;
  884. }
  885. BOOL ray_pyramid(const LLVector3 &ray_point, const LLVector3 &ray_direction,
  886. const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation,
  887. LLVector3 &intersection, LLVector3 &intersection_normal)
  888. {
  889. // center of mass of pyramid is located 1/4 its height from the base
  890. F32 x = 0.5f * p_scale.mV[VX];
  891. F32 y = 0.5f * p_scale.mV[VY];
  892. F32 z = 0.25f * p_scale.mV[VZ];
  893. LLVector3 point0(0.0f, 0.0f, p_scale.mV[VZ] - z);
  894. LLVector3 point1( x, y, -z);
  895. LLVector3 point2(-x, y, -z);
  896. LLVector3 point3(-x, -y, -z);
  897. LLVector3 point4( x, -y, -z);
  898. // transform these points into absolute frame
  899. point0 = (point0 * p_rotation) + p_center;
  900. point1 = (point1 * p_rotation) + p_center;
  901. point2 = (point2 * p_rotation) + p_center;
  902. point3 = (point3 * p_rotation) + p_center;
  903. point4 = (point4 * p_rotation) + p_center;
  904. // test ray intersection for each face
  905. BOOL b_hit = FALSE;
  906. LLVector3 face_intersection, face_normal;
  907. F32 distance_squared = 1.0e12f;
  908. F32 temp;
  909. // face 0
  910. if (ray_direction * ( (point1 - point4) % (point0 - point4)) < 0.0f &&
  911. ray_triangle(ray_point, ray_direction, point4, point1, point0, intersection, intersection_normal))
  912. {
  913. distance_squared = (ray_point - intersection).magVecSquared();
  914. b_hit = TRUE;
  915. }
  916. // face 1
  917. if (ray_direction * ( (point2 - point1) % (point0 - point1)) < 0.0f &&
  918. ray_triangle(ray_point, ray_direction, point1, point2, point0, face_intersection, face_normal))
  919. {
  920. if (TRUE == b_hit)
  921. {
  922. temp = (ray_point - face_intersection).magVecSquared();
  923. if (temp < distance_squared)
  924. {
  925. distance_squared = temp;
  926. intersection = face_intersection;
  927. intersection_normal = face_normal;
  928. }
  929. }
  930. else
  931. {
  932. distance_squared = (ray_point - face_intersection).magVecSquared();
  933. intersection = face_intersection;
  934. intersection_normal = face_normal;
  935. b_hit = TRUE;
  936. }
  937. }
  938. // face 2
  939. if (ray_direction * ( (point3 - point2) % (point0 - point2)) < 0.0f &&
  940. ray_triangle(ray_point, ray_direction, point2, point3, point0, face_intersection, face_normal))
  941. {
  942. if (TRUE == b_hit)
  943. {
  944. temp = (ray_point - face_intersection).magVecSquared();
  945. if (temp < distance_squared)
  946. {
  947. distance_squared = temp;
  948. intersection = face_intersection;
  949. intersection_normal = face_normal;
  950. }
  951. }
  952. else
  953. {
  954. distance_squared = (ray_point - face_intersection).magVecSquared();
  955. intersection = face_intersection;
  956. intersection_normal = face_normal;
  957. b_hit = TRUE;
  958. }
  959. }
  960. // face 3
  961. if (ray_direction * ( (point4 - point3) % (point0 - point3)) < 0.0f &&
  962. ray_triangle(ray_point, ray_direction, point3, point4, point0, face_intersection, face_normal))
  963. {
  964. if (TRUE == b_hit)
  965. {
  966. temp = (ray_point - face_intersection).magVecSquared();
  967. if (temp < distance_squared)
  968. {
  969. distance_squared = temp;
  970. intersection = face_intersection;
  971. intersection_normal = face_normal;
  972. }
  973. }
  974. else
  975. {
  976. distance_squared = (ray_point - face_intersection).magVecSquared();
  977. intersection = face_intersection;
  978. intersection_normal = face_normal;
  979. b_hit = TRUE;
  980. }
  981. }
  982. // face 4
  983. if (ray_direction * ( (point3 - point4) % (point2 - point4)) < 0.0f &&
  984. ray_quadrangle(ray_point, ray_direction, point4, point3, point2, face_intersection, face_normal))
  985. {
  986. if (TRUE == b_hit)
  987. {
  988. temp = (ray_point - face_intersection).magVecSquared();
  989. if (temp < distance_squared)
  990. {
  991. intersection = face_intersection;
  992. intersection_normal = face_normal;
  993. }
  994. }
  995. else
  996. {
  997. intersection = face_intersection;
  998. intersection_normal = face_normal;
  999. b_hit = TRUE;
  1000. }
  1001. }
  1002. return b_hit;
  1003. }
  1004. BOOL linesegment_circle(const LLVector3 &point_a, const LLVector3 &point_b,
  1005. const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius,
  1006. LLVector3 &intersection)
  1007. {
  1008. LLVector3 ray_direction = point_b - point_a;
  1009. F32 segment_length = ray_direction.normVec();
  1010. if (ray_circle(point_a, ray_direction, circle_center, plane_normal, circle_radius, intersection))
  1011. {
  1012. if (segment_length >= (point_a - intersection).magVec())
  1013. {
  1014. return TRUE;
  1015. }
  1016. }
  1017. return FALSE;
  1018. }
  1019. BOOL linesegment_triangle(const LLVector3 &point_a, const LLVector3 &point_b,
  1020. const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
  1021. LLVector3 &intersection, LLVector3 &intersection_normal)
  1022. {
  1023. LLVector3 ray_direction = point_b - point_a;
  1024. F32 segment_length = ray_direction.normVec();
  1025. if (ray_triangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal))
  1026. {
  1027. if (segment_length >= (point_a - intersection).magVec())
  1028. {
  1029. return TRUE;
  1030. }
  1031. }
  1032. return FALSE;
  1033. }
  1034. BOOL linesegment_quadrangle(const LLVector3 &point_a, const LLVector3 &point_b,
  1035. const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2,
  1036. LLVector3 &intersection, LLVector3 &intersection_normal)
  1037. {
  1038. LLVector3 ray_direction = point_b - point_a;
  1039. F32 segment_length = ray_direction.normVec();
  1040. if (ray_quadrangle(point_a, ray_direction, point_0, point_1, point_2, intersection, intersection_normal))
  1041. {
  1042. if (segment_length >= (point_a - intersection).magVec())
  1043. {
  1044. return TRUE;
  1045. }
  1046. }
  1047. return FALSE;
  1048. }
  1049. BOOL linesegment_sphere(const LLVector3 &point_a, const LLVector3 &point_b,
  1050. const LLVector3 &sphere_center, F32 sphere_radius,
  1051. LLVector3 &intersection, LLVector3 &intersection_normal)
  1052. {
  1053. LLVector3 ray_direction = point_b - point_a;
  1054. F32 segment_length = ray_direction.normVec();
  1055. if (ray_sphere(point_a, ray_direction, sphere_center, sphere_radius, intersection, intersection_normal))
  1056. {
  1057. if (segment_length >= (point_a - intersection).magVec())
  1058. {
  1059. return TRUE;
  1060. }
  1061. }
  1062. return FALSE;
  1063. }
  1064. BOOL linesegment_cylinder(const LLVector3 &point_a, const LLVector3 &point_b,
  1065. const LLVector3 &cyl_center, const LLVector3 &cyl_scale, const LLQuaternion &cyl_rotation,
  1066. LLVector3 &intersection, LLVector3 &intersection_normal)
  1067. {
  1068. LLVector3 ray_direction = point_b - point_a;
  1069. F32 segment_length = ray_direction.normVec();
  1070. if (ray_cylinder(point_a, ray_direction, cyl_center, cyl_scale, cyl_rotation, intersection, intersection_normal))
  1071. {
  1072. if (segment_length >= (point_a - intersection).magVec())
  1073. {
  1074. return TRUE;
  1075. }
  1076. }
  1077. return FALSE;
  1078. }
  1079. U32 linesegment_box(const LLVector3 &point_a, const LLVector3 &point_b,
  1080. const LLVector3 &box_center, const LLVector3 &box_scale, const LLQuaternion &box_rotation,
  1081. LLVector3 &intersection, LLVector3 &intersection_normal)
  1082. {
  1083. LLVector3 direction = point_b - point_a;
  1084. if (direction.isNull())
  1085. {
  1086. return NO_SIDE;
  1087. }
  1088. F32 segment_length = direction.normVec();
  1089. U32 box_side = ray_box(point_a, direction, box_center, box_scale, box_rotation, intersection, intersection_normal);
  1090. if (NO_SIDE == box_side || segment_length < (intersection - point_a).magVec())
  1091. {
  1092. return NO_SIDE;
  1093. }
  1094. return box_side;
  1095. }
  1096. BOOL linesegment_prism(const LLVector3 &point_a, const LLVector3 &point_b,
  1097. const LLVector3 &prism_center, const LLVector3 &prism_scale, const LLQuaternion &prism_rotation,
  1098. LLVector3 &intersection, LLVector3 &intersection_normal)
  1099. {
  1100. LLVector3 ray_direction = point_b - point_a;
  1101. F32 segment_length = ray_direction.normVec();
  1102. if (ray_prism(point_a, ray_direction, prism_center, prism_scale, prism_rotation, intersection, intersection_normal))
  1103. {
  1104. if (segment_length >= (point_a - intersection).magVec())
  1105. {
  1106. return TRUE;
  1107. }
  1108. }
  1109. return FALSE;
  1110. }
  1111. BOOL linesegment_tetrahedron(const LLVector3 &point_a, const LLVector3 &point_b,
  1112. const LLVector3 &t_center, const LLVector3 &t_scale, const LLQuaternion &t_rotation,
  1113. LLVector3 &intersection, LLVector3 &intersection_normal)
  1114. {
  1115. LLVector3 ray_direction = point_b - point_a;
  1116. F32 segment_length = ray_direction.normVec();
  1117. if (ray_tetrahedron(point_a, ray_direction, t_center, t_scale, t_rotation, intersection, intersection_normal))
  1118. {
  1119. if (segment_length >= (point_a - intersection).magVec())
  1120. {
  1121. return TRUE;
  1122. }
  1123. }
  1124. return FALSE;
  1125. }
  1126. BOOL linesegment_pyramid(const LLVector3 &point_a, const LLVector3 &point_b,
  1127. const LLVector3 &p_center, const LLVector3 &p_scale, const LLQuaternion &p_rotation,
  1128. LLVector3 &intersection, LLVector3 &intersection_normal)
  1129. {
  1130. LLVector3 ray_direction = point_b - point_a;
  1131. F32 segment_length = ray_direction.normVec();
  1132. if (ray_pyramid(point_a, ray_direction, p_center, p_scale, p_rotation, intersection, intersection_normal))
  1133. {
  1134. if (segment_length >= (point_a - intersection).magVec())
  1135. {
  1136. return TRUE;
  1137. }
  1138. }
  1139. return FALSE;
  1140. }