diff options
author | Jacek Antonelli | 2008-08-15 23:45:42 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:45:42 -0500 |
commit | ce28e056c20bf2723f565bbf464b87781ec248a2 (patch) | |
tree | ef7b0501c4de4b631a916305cbc2a5fdc125e52d /linden/indra/llmath/llline.cpp | |
parent | Second Life viewer sources 1.19.1.4b (diff) | |
download | meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.zip meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.gz meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.bz2 meta-impy-ce28e056c20bf2723f565bbf464b87781ec248a2.tar.xz |
Second Life viewer sources 1.20.2
Diffstat (limited to 'linden/indra/llmath/llline.cpp')
-rw-r--r-- | linden/indra/llmath/llline.cpp | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/linden/indra/llmath/llline.cpp b/linden/indra/llmath/llline.cpp new file mode 100644 index 0000000..9c41efb --- /dev/null +++ b/linden/indra/llmath/llline.cpp | |||
@@ -0,0 +1,189 @@ | |||
1 | /** | ||
2 | * @file llline.cpp | ||
3 | * @author Andrew Meadows | ||
4 | * @brief Simple line class that can compute nearest approach between two lines | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2001&license=internal$ | ||
7 | * | ||
8 | * Copyright (c) 2001-2008, Linden Research, Inc. | ||
9 | * | ||
10 | * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of | ||
11 | * this source code is governed by the Linden Lab Source Code Disclosure | ||
12 | * Agreement ("Agreement") previously entered between you and Linden | ||
13 | * Lab. By accessing, using, copying, modifying or distributing this | ||
14 | * software, you acknowledge that you have been informed of your | ||
15 | * obligations under the Agreement and agree to abide by those obligations. | ||
16 | * | ||
17 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
18 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
19 | * COMPLETENESS OR PERFORMANCE. | ||
20 | * $/LicenseInfo$ | ||
21 | */ | ||
22 | |||
23 | #include "llline.h" | ||
24 | #include "llrand.h" | ||
25 | |||
26 | const F32 SOME_SMALL_NUMBER = 1.0e-5f; | ||
27 | const F32 SOME_VERY_SMALL_NUMBER = 1.0e-8f; | ||
28 | |||
29 | LLLine::LLLine() | ||
30 | : mPoint(0.f, 0.f, 0.f), | ||
31 | mDirection(1.f, 0.f, 0.f) | ||
32 | { } | ||
33 | |||
34 | LLLine::LLLine( const LLVector3& first_point, const LLVector3& second_point ) | ||
35 | { | ||
36 | setPoints(first_point, second_point); | ||
37 | } | ||
38 | |||
39 | void LLLine::setPoints( const LLVector3& first_point, const LLVector3& second_point ) | ||
40 | { | ||
41 | mPoint = first_point; | ||
42 | mDirection = second_point - first_point; | ||
43 | mDirection.normalize(); | ||
44 | } | ||
45 | |||
46 | void LLLine::setPointDirection( const LLVector3& first_point, const LLVector3& second_point ) | ||
47 | { | ||
48 | setPoints(first_point, first_point + second_point); | ||
49 | } | ||
50 | |||
51 | bool LLLine::intersects( const LLVector3& point, F32 radius ) const | ||
52 | { | ||
53 | LLVector3 other_direction = point - mPoint; | ||
54 | LLVector3 nearest_point = mPoint + mDirection * (other_direction * mDirection); | ||
55 | F32 nearest_approach = (nearest_point - point).length(); | ||
56 | return (nearest_approach <= radius); | ||
57 | } | ||
58 | |||
59 | // returns the point on this line that is closest to some_point | ||
60 | LLVector3 LLLine::nearestApproach( const LLVector3& some_point ) const | ||
61 | { | ||
62 | return (mPoint + mDirection * ((some_point - mPoint) * mDirection)); | ||
63 | } | ||
64 | |||
65 | // the accuracy of this method sucks when you give it two nearly | ||
66 | // parallel lines, so you should probably check for parallelism | ||
67 | // before you call this | ||
68 | // | ||
69 | // returns the point on this line that is closest to other_line | ||
70 | LLVector3 LLLine::nearestApproach( const LLLine& other_line ) const | ||
71 | { | ||
72 | LLVector3 between_points = other_line.mPoint - mPoint; | ||
73 | F32 dir_dot_dir = mDirection * other_line.mDirection; | ||
74 | F32 one_minus_dir_dot_dir = 1.0f - fabs(dir_dot_dir); | ||
75 | if ( one_minus_dir_dot_dir < SOME_VERY_SMALL_NUMBER ) | ||
76 | { | ||
77 | #ifdef LL_DEBUG | ||
78 | llwarns << "LLLine::nearestApproach() was given two very " | ||
79 | << "nearly parallel lines dir1 = " << mDirection | ||
80 | << " dir2 = " << other_line.mDirection << " with 1-dot_product = " | ||
81 | << one_minus_dir_dot_dir << llendl; | ||
82 | #endif | ||
83 | // the lines are approximately parallel | ||
84 | // We shouldn't fall in here because this check should have been made | ||
85 | // BEFORE this function was called. We dare not continue with the | ||
86 | // computations for fear of division by zero, but we have to return | ||
87 | // something so we return a bogus point -- caller beware. | ||
88 | return 0.5f * (mPoint + other_line.mPoint); | ||
89 | } | ||
90 | |||
91 | F32 odir_dot_bp = other_line.mDirection * between_points; | ||
92 | |||
93 | F32 numerator = 0; | ||
94 | F32 denominator = 0; | ||
95 | for (S32 i=0; i<3; i++) | ||
96 | { | ||
97 | F32 factor = dir_dot_dir * other_line.mDirection.mV[i] - mDirection.mV[i]; | ||
98 | numerator += ( between_points.mV[i] - odir_dot_bp * other_line.mDirection.mV[i] ) * factor; | ||
99 | denominator -= factor * factor; | ||
100 | } | ||
101 | |||
102 | F32 length_to_nearest_approach = numerator / denominator; | ||
103 | |||
104 | return mPoint + length_to_nearest_approach * mDirection; | ||
105 | } | ||
106 | |||
107 | std::ostream& operator<<( std::ostream& output_stream, const LLLine& line ) | ||
108 | { | ||
109 | output_stream << "{point=" << line.mPoint << "," << "dir=" << line.mDirection << "}"; | ||
110 | return output_stream; | ||
111 | } | ||
112 | |||
113 | |||
114 | F32 ALMOST_PARALLEL = 0.99f; | ||
115 | F32 TOO_SMALL_FOR_DIVISION = 0.0001f; | ||
116 | |||
117 | // returns 'true' if this line intersects the plane | ||
118 | // on success stores the intersection point in 'result' | ||
119 | bool LLLine::intersectsPlane( LLVector3& result, const LLLine& plane ) const | ||
120 | { | ||
121 | // p = P + l * d equation for a line | ||
122 | // | ||
123 | // N * p = D equation for a point | ||
124 | // | ||
125 | // N * (P + l * d) = D | ||
126 | // N*P + l * (N*d) = D | ||
127 | // l * (N*d) = D - N*P | ||
128 | // l = ( D - N*P ) / ( N*d ) | ||
129 | // | ||
130 | |||
131 | F32 dot = plane.mDirection * mDirection; | ||
132 | if (fabs(dot) < TOO_SMALL_FOR_DIVISION) | ||
133 | { | ||
134 | return false; | ||
135 | } | ||
136 | |||
137 | F32 plane_dot = plane.mDirection * plane.mPoint; | ||
138 | F32 length = ( plane_dot - (plane.mDirection * mPoint) ) / dot; | ||
139 | result = mPoint + length * mDirection; | ||
140 | return true; | ||
141 | } | ||
142 | |||
143 | //static | ||
144 | // returns 'true' if planes intersect, and stores the result | ||
145 | // the second and third arguments are treated as planes | ||
146 | // where mPoint is on the plane and mDirection is the normal | ||
147 | // result.mPoint will be the intersection line's closest approach | ||
148 | // to first_plane.mPoint | ||
149 | bool LLLine::getIntersectionBetweenTwoPlanes( LLLine& result, const LLLine& first_plane, const LLLine& second_plane ) | ||
150 | { | ||
151 | // TODO -- if we ever get some generic matrix solving code in our libs | ||
152 | // then we should just use that, since this problem is really just | ||
153 | // linear algebra. | ||
154 | |||
155 | F32 dot = fabs(first_plane.mDirection * second_plane.mDirection); | ||
156 | if (dot > ALMOST_PARALLEL) | ||
157 | { | ||
158 | // the planes are nearly parallel | ||
159 | return false; | ||
160 | } | ||
161 | |||
162 | LLVector3 direction = first_plane.mDirection % second_plane.mDirection; | ||
163 | direction.normalize(); | ||
164 | |||
165 | LLVector3 first_intersection; | ||
166 | { | ||
167 | LLLine intersection_line(first_plane); | ||
168 | intersection_line.mDirection = direction % first_plane.mDirection; | ||
169 | intersection_line.mDirection.normalize(); | ||
170 | intersection_line.intersectsPlane(first_intersection, second_plane); | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | LLVector3 second_intersection; | ||
175 | { | ||
176 | LLLine intersection_line(second_plane); | ||
177 | intersection_line.mDirection = direction % second_plane.mDirection; | ||
178 | intersection_line.mDirection.normalize(); | ||
179 | intersection_line.intersectsPlane(second_intersection, first_plane); | ||
180 | } | ||
181 | */ | ||
182 | |||
183 | result.mPoint = first_intersection; | ||
184 | result.mDirection = direction; | ||
185 | |||
186 | return true; | ||
187 | } | ||
188 | |||
189 | |||