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