diff options
Diffstat (limited to '')
27 files changed, 1867 insertions, 291 deletions
diff --git a/linden/indra/llmath/files.lst b/linden/indra/llmath/files.lst index cfd635a..1001a6d 100644 --- a/linden/indra/llmath/files.lst +++ b/linden/indra/llmath/files.lst | |||
@@ -2,11 +2,13 @@ llmath/llbboxlocal.cpp | |||
2 | llmath/llcamera.cpp | 2 | llmath/llcamera.cpp |
3 | llmath/llcoordframe.cpp | 3 | llmath/llcoordframe.cpp |
4 | llmath/llcrc.cpp | 4 | llmath/llcrc.cpp |
5 | llmath/llline.cpp | ||
5 | llmath/llmd5.cpp | 6 | llmath/llmd5.cpp |
6 | llmath/llperlin.cpp | 7 | llmath/llperlin.cpp |
7 | llmath/llquaternion.cpp | 8 | llmath/llquaternion.cpp |
8 | llmath/llrand.cpp | 9 | llmath/llrand.cpp |
9 | llmath/llrect.cpp | 10 | llmath/llrect.cpp |
11 | llmath/llsphere.cpp | ||
10 | llmath/lluuid.cpp | 12 | llmath/lluuid.cpp |
11 | llmath/llvolume.cpp | 13 | llmath/llvolume.cpp |
12 | llmath/llvolumemgr.cpp | 14 | llmath/llvolumemgr.cpp |
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 | |||
diff --git a/linden/indra/llmath/llline.h b/linden/indra/llmath/llline.h new file mode 100644 index 0000000..ca454c5 --- /dev/null +++ b/linden/indra/llmath/llline.h | |||
@@ -0,0 +1,75 @@ | |||
1 | // llline.h | ||
2 | /** | ||
3 | * @file llline.cpp | ||
4 | * @author Andrew Meadows | ||
5 | * @brief Simple line for computing nearest approach between two infinite lines | ||
6 | * | ||
7 | * $LicenseInfo:firstyear=2006&license=internal$ | ||
8 | * | ||
9 | * Copyright (c) 2006-2008, Linden Research, Inc. | ||
10 | * | ||
11 | * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of | ||
12 | * this source code is governed by the Linden Lab Source Code Disclosure | ||
13 | * Agreement ("Agreement") previously entered between you and Linden | ||
14 | * Lab. By accessing, using, copying, modifying or distributing this | ||
15 | * software, you acknowledge that you have been informed of your | ||
16 | * obligations under the Agreement and agree to abide by those obligations. | ||
17 | * | ||
18 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
19 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
20 | * COMPLETENESS OR PERFORMANCE. | ||
21 | * $/LicenseInfo$ | ||
22 | */ | ||
23 | |||
24 | #ifndef LL_LINE_H | ||
25 | #define LL_LINE_H | ||
26 | |||
27 | #include <iostream> | ||
28 | #include "stdtypes.h" | ||
29 | #include "v3math.h" | ||
30 | |||
31 | const F32 DEFAULT_INTERSECTION_ERROR = 0.000001f; | ||
32 | |||
33 | class LLLine | ||
34 | { | ||
35 | public: | ||
36 | LLLine(); | ||
37 | LLLine( const LLVector3& first_point, const LLVector3& second_point ); | ||
38 | virtual ~LLLine() {}; | ||
39 | |||
40 | void setPointDirection( const LLVector3& first_point, const LLVector3& second_point ); | ||
41 | void setPoints( const LLVector3& first_point, const LLVector3& second_point ); | ||
42 | |||
43 | bool intersects( const LLVector3& point, F32 radius = DEFAULT_INTERSECTION_ERROR ) const; | ||
44 | |||
45 | // returns the point on this line that is closest to some_point | ||
46 | LLVector3 nearestApproach( const LLVector3& some_point ) const; | ||
47 | |||
48 | // returns the point on this line that is closest to other_line | ||
49 | LLVector3 nearestApproach( const LLLine& other_line ) const; | ||
50 | |||
51 | friend std::ostream& operator<<( std::ostream& output_stream, const LLLine& line ); | ||
52 | |||
53 | // returns 'true' if this line intersects the plane | ||
54 | // on success stores the intersection point in 'result' | ||
55 | bool intersectsPlane( LLVector3& result, const LLLine& plane ) const; | ||
56 | |||
57 | // returns 'true' if planes intersect, and stores the result | ||
58 | // the second and third arguments are treated as planes | ||
59 | // where mPoint is on the plane and mDirection is the normal | ||
60 | // result.mPoint will be the intersection line's closest approach | ||
61 | // to first_plane.mPoint | ||
62 | static bool getIntersectionBetweenTwoPlanes( LLLine& result, const LLLine& first_plane, const LLLine& second_plane ); | ||
63 | |||
64 | const LLVector3& getPoint() const { return mPoint; } | ||
65 | const LLVector3& getDirection() const { return mDirection; } | ||
66 | |||
67 | protected: | ||
68 | // these are protected because some code assumes that the normal is | ||
69 | // always correct and properly normalized. | ||
70 | LLVector3 mPoint; | ||
71 | LLVector3 mDirection; | ||
72 | }; | ||
73 | |||
74 | |||
75 | #endif | ||
diff --git a/linden/indra/llmath/llmath.h b/linden/indra/llmath/llmath.h index d3c0d86..4a6358d 100644 --- a/linden/indra/llmath/llmath.h +++ b/linden/indra/llmath/llmath.h | |||
@@ -32,8 +32,14 @@ | |||
32 | #ifndef LLMATH_H | 32 | #ifndef LLMATH_H |
33 | #define LLMATH_H | 33 | #define LLMATH_H |
34 | 34 | ||
35 | #include <cmath> | ||
36 | //#include <math.h> | ||
37 | //#include <stdlib.h> | ||
38 | #include "lldefs.h" | ||
39 | |||
35 | // work around for Windows & older gcc non-standard function names. | 40 | // work around for Windows & older gcc non-standard function names. |
36 | #if LL_WINDOWS | 41 | #if LL_WINDOWS |
42 | #include <float.h> | ||
37 | #define llisnan(val) _isnan(val) | 43 | #define llisnan(val) _isnan(val) |
38 | #define llfinite(val) _finite(val) | 44 | #define llfinite(val) _finite(val) |
39 | #elif (LL_LINUX && __GNUC__ <= 2) | 45 | #elif (LL_LINUX && __GNUC__ <= 2) |
@@ -99,6 +105,12 @@ inline BOOL is_approx_equal(F32 x, F32 y) | |||
99 | return (abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); | 105 | return (abs((S32) ((U32&)x - (U32&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); |
100 | } | 106 | } |
101 | 107 | ||
108 | inline BOOL is_approx_equal(F64 x, F64 y) | ||
109 | { | ||
110 | const S64 COMPARE_MANTISSA_UP_TO_BIT = 0x02; | ||
111 | return (abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT); | ||
112 | } | ||
113 | |||
102 | inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) | 114 | inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) |
103 | { | 115 | { |
104 | BOOL ret = TRUE; | 116 | BOOL ret = TRUE; |
@@ -120,6 +132,27 @@ inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) | |||
120 | return ret; | 132 | return ret; |
121 | } | 133 | } |
122 | 134 | ||
135 | inline BOOL is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits) | ||
136 | { | ||
137 | BOOL ret = TRUE; | ||
138 | F64 diff = (F64) fabs(x - y); | ||
139 | |||
140 | S32 diffInt = (S32) diff; | ||
141 | S32 diffFracTolerance = (S32) ((diff - (F64) diffInt) * (1 << frac_bits)); | ||
142 | |||
143 | // if integer portion is not equal, not enough bits were used for packing | ||
144 | // so error out since either the use case is not correct OR there is | ||
145 | // an issue with pack/unpack. should fail in either case. | ||
146 | // for decimal portion, make sure that the delta is no more than 1 | ||
147 | // based on the number of bits used for packing decimal portion. | ||
148 | if (diffInt != 0 || diffFracTolerance > 1) | ||
149 | { | ||
150 | ret = FALSE; | ||
151 | } | ||
152 | |||
153 | return ret; | ||
154 | } | ||
155 | |||
123 | inline S32 llabs(const S32 a) | 156 | inline S32 llabs(const S32 a) |
124 | { | 157 | { |
125 | return S32(labs(a)); | 158 | return S32(labs(a)); |
diff --git a/linden/indra/llmath/llmath.vcproj b/linden/indra/llmath/llmath.vcproj index 79e472a..d05505e 100644 --- a/linden/indra/llmath/llmath.vcproj +++ b/linden/indra/llmath/llmath.vcproj | |||
@@ -164,6 +164,9 @@ | |||
164 | RelativePath=".\llcrc.cpp"> | 164 | RelativePath=".\llcrc.cpp"> |
165 | </File> | 165 | </File> |
166 | <File | 166 | <File |
167 | RelativePath=".\llline.cpp"> | ||
168 | </File> | ||
169 | <File | ||
167 | RelativePath=".\llmd5.cpp"> | 170 | RelativePath=".\llmd5.cpp"> |
168 | </File> | 171 | </File> |
169 | <File | 172 | <File |
@@ -179,6 +182,9 @@ | |||
179 | RelativePath=".\llrect.cpp"> | 182 | RelativePath=".\llrect.cpp"> |
180 | </File> | 183 | </File> |
181 | <File | 184 | <File |
185 | RelativePath=".\llsphere.cpp"> | ||
186 | </File> | ||
187 | <File | ||
182 | RelativePath=".\lluuid.cpp"> | 188 | RelativePath=".\lluuid.cpp"> |
183 | </File> | 189 | </File> |
184 | <File | 190 | <File |
@@ -244,6 +250,9 @@ | |||
244 | RelativePath=".\llinterp.h"> | 250 | RelativePath=".\llinterp.h"> |
245 | </File> | 251 | </File> |
246 | <File | 252 | <File |
253 | RelativePath=".\llline.h"> | ||
254 | </File> | ||
255 | <File | ||
247 | RelativePath=".\llmath.h"> | 256 | RelativePath=".\llmath.h"> |
248 | </File> | 257 | </File> |
249 | <File | 258 | <File |
@@ -268,6 +277,9 @@ | |||
268 | RelativePath=".\llrect.h"> | 277 | RelativePath=".\llrect.h"> |
269 | </File> | 278 | </File> |
270 | <File | 279 | <File |
280 | RelativePath=".\llsphere.h"> | ||
281 | </File> | ||
282 | <File | ||
271 | RelativePath=".\lltreenode.h"> | 283 | RelativePath=".\lltreenode.h"> |
272 | </File> | 284 | </File> |
273 | <File | 285 | <File |
diff --git a/linden/indra/llmath/llquaternion.cpp b/linden/indra/llmath/llquaternion.cpp index ea51e28..ab4855b 100644 --- a/linden/indra/llmath/llquaternion.cpp +++ b/linden/indra/llmath/llquaternion.cpp | |||
@@ -51,19 +51,19 @@ const LLQuaternion LLQuaternion::DEFAULT; | |||
51 | LLQuaternion::LLQuaternion(const LLMatrix4 &mat) | 51 | LLQuaternion::LLQuaternion(const LLMatrix4 &mat) |
52 | { | 52 | { |
53 | *this = mat.quaternion(); | 53 | *this = mat.quaternion(); |
54 | normQuat(); | 54 | normalize(); |
55 | } | 55 | } |
56 | 56 | ||
57 | LLQuaternion::LLQuaternion(const LLMatrix3 &mat) | 57 | LLQuaternion::LLQuaternion(const LLMatrix3 &mat) |
58 | { | 58 | { |
59 | *this = mat.quaternion(); | 59 | *this = mat.quaternion(); |
60 | normQuat(); | 60 | normalize(); |
61 | } | 61 | } |
62 | 62 | ||
63 | LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) | 63 | LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) |
64 | { | 64 | { |
65 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); | 65 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); |
66 | v.normVec(); | 66 | v.normalize(); |
67 | 67 | ||
68 | F32 c, s; | 68 | F32 c, s; |
69 | c = cosf(angle*0.5f); | 69 | c = cosf(angle*0.5f); |
@@ -73,13 +73,13 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) | |||
73 | mQ[VY] = v.mV[VY] * s; | 73 | mQ[VY] = v.mV[VY] * s; |
74 | mQ[VZ] = v.mV[VZ] * s; | 74 | mQ[VZ] = v.mV[VZ] * s; |
75 | mQ[VW] = c; | 75 | mQ[VW] = c; |
76 | normQuat(); | 76 | normalize(); |
77 | } | 77 | } |
78 | 78 | ||
79 | LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) | 79 | LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) |
80 | { | 80 | { |
81 | LLVector3 v(vec); | 81 | LLVector3 v(vec); |
82 | v.normVec(); | 82 | v.normalize(); |
83 | 83 | ||
84 | F32 c, s; | 84 | F32 c, s; |
85 | c = cosf(angle*0.5f); | 85 | c = cosf(angle*0.5f); |
@@ -89,7 +89,7 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) | |||
89 | mQ[VY] = v.mV[VY] * s; | 89 | mQ[VY] = v.mV[VY] * s; |
90 | mQ[VZ] = v.mV[VZ] * s; | 90 | mQ[VZ] = v.mV[VZ] * s; |
91 | mQ[VW] = c; | 91 | mQ[VW] = c; |
92 | normQuat(); | 92 | normalize(); |
93 | } | 93 | } |
94 | 94 | ||
95 | LLQuaternion::LLQuaternion(const LLVector3 &x_axis, | 95 | LLQuaternion::LLQuaternion(const LLVector3 &x_axis, |
@@ -99,7 +99,7 @@ LLQuaternion::LLQuaternion(const LLVector3 &x_axis, | |||
99 | LLMatrix3 mat; | 99 | LLMatrix3 mat; |
100 | mat.setRows(x_axis, y_axis, z_axis); | 100 | mat.setRows(x_axis, y_axis, z_axis); |
101 | *this = mat.quaternion(); | 101 | *this = mat.quaternion(); |
102 | normQuat(); | 102 | normalize(); |
103 | } | 103 | } |
104 | 104 | ||
105 | // Quatizations | 105 | // Quatizations |
@@ -138,10 +138,93 @@ void LLQuaternion::quantize8(F32 lower, F32 upper) | |||
138 | 138 | ||
139 | // Set LLQuaternion routines | 139 | // Set LLQuaternion routines |
140 | 140 | ||
141 | const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, F32 x, F32 y, F32 z) | ||
142 | { | ||
143 | LLVector3 vec(x, y, z); | ||
144 | vec.normalize(); | ||
145 | |||
146 | angle *= 0.5f; | ||
147 | F32 c, s; | ||
148 | c = cosf(angle); | ||
149 | s = sinf(angle); | ||
150 | |||
151 | mQ[VX] = vec.mV[VX]*s; | ||
152 | mQ[VY] = vec.mV[VY]*s; | ||
153 | mQ[VZ] = vec.mV[VZ]*s; | ||
154 | mQ[VW] = c; | ||
155 | |||
156 | normalize(); | ||
157 | return (*this); | ||
158 | } | ||
159 | |||
160 | const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector3 &vec) | ||
161 | { | ||
162 | LLVector3 v(vec); | ||
163 | v.normalize(); | ||
164 | |||
165 | angle *= 0.5f; | ||
166 | F32 c, s; | ||
167 | c = cosf(angle); | ||
168 | s = sinf(angle); | ||
169 | |||
170 | mQ[VX] = v.mV[VX]*s; | ||
171 | mQ[VY] = v.mV[VY]*s; | ||
172 | mQ[VZ] = v.mV[VZ]*s; | ||
173 | mQ[VW] = c; | ||
174 | |||
175 | normalize(); | ||
176 | return (*this); | ||
177 | } | ||
178 | |||
179 | const LLQuaternion& LLQuaternion::setAngleAxis(F32 angle, const LLVector4 &vec) | ||
180 | { | ||
181 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); | ||
182 | v.normalize(); | ||
183 | |||
184 | F32 c, s; | ||
185 | c = cosf(angle*0.5f); | ||
186 | s = sinf(angle*0.5f); | ||
187 | |||
188 | mQ[VX] = v.mV[VX]*s; | ||
189 | mQ[VY] = v.mV[VY]*s; | ||
190 | mQ[VZ] = v.mV[VZ]*s; | ||
191 | mQ[VW] = c; | ||
192 | |||
193 | normalize(); | ||
194 | return (*this); | ||
195 | } | ||
196 | |||
197 | const LLQuaternion& LLQuaternion::setEulerAngles(F32 roll, F32 pitch, F32 yaw) | ||
198 | { | ||
199 | LLMatrix3 rot_mat(roll, pitch, yaw); | ||
200 | rot_mat.orthogonalize(); | ||
201 | *this = rot_mat.quaternion(); | ||
202 | |||
203 | normalize(); | ||
204 | return (*this); | ||
205 | } | ||
206 | |||
207 | // deprecated | ||
208 | const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat) | ||
209 | { | ||
210 | *this = mat.quaternion(); | ||
211 | normalize(); | ||
212 | return (*this); | ||
213 | } | ||
214 | |||
215 | // deprecated | ||
216 | const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat) | ||
217 | { | ||
218 | *this = mat.quaternion(); | ||
219 | normalize(); | ||
220 | return (*this); | ||
221 | } | ||
222 | |||
223 | // deprecated | ||
141 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) | 224 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) |
142 | { | 225 | { |
143 | LLVector3 vec(x, y, z); | 226 | LLVector3 vec(x, y, z); |
144 | vec.normVec(); | 227 | vec.normalize(); |
145 | 228 | ||
146 | angle *= 0.5f; | 229 | angle *= 0.5f; |
147 | F32 c, s; | 230 | F32 c, s; |
@@ -153,14 +236,15 @@ const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) | |||
153 | mQ[VZ] = vec.mV[VZ]*s; | 236 | mQ[VZ] = vec.mV[VZ]*s; |
154 | mQ[VW] = c; | 237 | mQ[VW] = c; |
155 | 238 | ||
156 | normQuat(); | 239 | normalize(); |
157 | return (*this); | 240 | return (*this); |
158 | } | 241 | } |
159 | 242 | ||
243 | // deprecated | ||
160 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) | 244 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) |
161 | { | 245 | { |
162 | LLVector3 v(vec); | 246 | LLVector3 v(vec); |
163 | v.normVec(); | 247 | v.normalize(); |
164 | 248 | ||
165 | angle *= 0.5f; | 249 | angle *= 0.5f; |
166 | F32 c, s; | 250 | F32 c, s; |
@@ -172,14 +256,14 @@ const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) | |||
172 | mQ[VZ] = v.mV[VZ]*s; | 256 | mQ[VZ] = v.mV[VZ]*s; |
173 | mQ[VW] = c; | 257 | mQ[VW] = c; |
174 | 258 | ||
175 | normQuat(); | 259 | normalize(); |
176 | return (*this); | 260 | return (*this); |
177 | } | 261 | } |
178 | 262 | ||
179 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) | 263 | const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) |
180 | { | 264 | { |
181 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); | 265 | LLVector3 v(vec.mV[VX], vec.mV[VY], vec.mV[VZ]); |
182 | v.normVec(); | 266 | v.normalize(); |
183 | 267 | ||
184 | F32 c, s; | 268 | F32 c, s; |
185 | c = cosf(angle*0.5f); | 269 | c = cosf(angle*0.5f); |
@@ -190,7 +274,7 @@ const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) | |||
190 | mQ[VZ] = v.mV[VZ]*s; | 274 | mQ[VZ] = v.mV[VZ]*s; |
191 | mQ[VW] = c; | 275 | mQ[VW] = c; |
192 | 276 | ||
193 | normQuat(); | 277 | normalize(); |
194 | return (*this); | 278 | return (*this); |
195 | } | 279 | } |
196 | 280 | ||
@@ -200,7 +284,21 @@ const LLQuaternion& LLQuaternion::setQuat(F32 roll, F32 pitch, F32 yaw) | |||
200 | rot_mat.orthogonalize(); | 284 | rot_mat.orthogonalize(); |
201 | *this = rot_mat.quaternion(); | 285 | *this = rot_mat.quaternion(); |
202 | 286 | ||
203 | normQuat(); | 287 | normalize(); |
288 | return (*this); | ||
289 | } | ||
290 | |||
291 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) | ||
292 | { | ||
293 | *this = mat.quaternion(); | ||
294 | normalize(); | ||
295 | return (*this); | ||
296 | } | ||
297 | |||
298 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) | ||
299 | { | ||
300 | *this = mat.quaternion(); | ||
301 | normalize(); | ||
204 | return (*this); | 302 | return (*this); |
205 | //#if 1 | 303 | //#if 1 |
206 | // // NOTE: LLQuaternion's are actually inverted with respect to | 304 | // // NOTE: LLQuaternion's are actually inverted with respect to |
@@ -337,8 +435,8 @@ void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) | |||
337 | 435 | ||
338 | // Make sure neither vector is zero length. Also normalize | 436 | // Make sure neither vector is zero length. Also normalize |
339 | // the vectors while we are at it. | 437 | // the vectors while we are at it. |
340 | F32 vec_a_mag = vec_a.normVec(); | 438 | F32 vec_a_mag = vec_a.normalize(); |
341 | F32 vec_b_mag = vec_b.normVec(); | 439 | F32 vec_b_mag = vec_b.normalize(); |
342 | if (vec_a_mag < F_APPROXIMATELY_ZERO || | 440 | if (vec_a_mag < F_APPROXIMATELY_ZERO || |
343 | vec_b_mag < F_APPROXIMATELY_ZERO) | 441 | vec_b_mag < F_APPROXIMATELY_ZERO) |
344 | { | 442 | { |
@@ -370,7 +468,7 @@ void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) | |||
370 | ortho_axis -= proj; | 468 | ortho_axis -= proj; |
371 | 469 | ||
372 | // Turn this into an orthonormal axis. | 470 | // Turn this into an orthonormal axis. |
373 | F32 ortho_length = ortho_axis.normVec(); | 471 | F32 ortho_length = ortho_axis.normalize(); |
374 | // If the axis' length is 0, then our guess at an orthogonal axis | 472 | // If the axis' length is 0, then our guess at an orthogonal axis |
375 | // was wrong (a is parallel to the x-axis). | 473 | // was wrong (a is parallel to the x-axis). |
376 | if (ortho_length < F_APPROXIMATELY_ZERO) | 474 | if (ortho_length < F_APPROXIMATELY_ZERO) |
@@ -391,7 +489,7 @@ void LLQuaternion::shortestArc(const LLVector3 &a, const LLVector3 &b) | |||
391 | // Return the rotation between these vectors. | 489 | // Return the rotation between these vectors. |
392 | F32 theta = (F32)acos(cos_theta); | 490 | F32 theta = (F32)acos(cos_theta); |
393 | 491 | ||
394 | setQuat(theta, axis); | 492 | setAngleAxis(theta, axis); |
395 | } | 493 | } |
396 | } | 494 | } |
397 | 495 | ||
@@ -516,7 +614,7 @@ LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) | |||
516 | { | 614 | { |
517 | LLQuaternion r; | 615 | LLQuaternion r; |
518 | r = t * (q - p) + p; | 616 | r = t * (q - p) + p; |
519 | r.normQuat(); | 617 | r.normalize(); |
520 | return r; | 618 | return r; |
521 | } | 619 | } |
522 | #endif | 620 | #endif |
@@ -529,7 +627,7 @@ LLQuaternion lerp(F32 t, const LLQuaternion &q) | |||
529 | r.mQ[VY] = t * q.mQ[VY]; | 627 | r.mQ[VY] = t * q.mQ[VY]; |
530 | r.mQ[VZ] = t * q.mQ[VZ]; | 628 | r.mQ[VZ] = t * q.mQ[VZ]; |
531 | r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; | 629 | r.mQ[VW] = t * (q.mQ[VZ] - 1.f) + 1.f; |
532 | r.normQuat(); | 630 | r.normalize(); |
533 | return r; | 631 | return r; |
534 | } | 632 | } |
535 | 633 | ||
@@ -544,7 +642,7 @@ LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) | |||
544 | r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); | 642 | r.mQ[VY] = t * q.mQ[VY] + (inv_t * p.mQ[VY]); |
545 | r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); | 643 | r.mQ[VZ] = t * q.mQ[VZ] + (inv_t * p.mQ[VZ]); |
546 | r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); | 644 | r.mQ[VW] = t * q.mQ[VW] + (inv_t * p.mQ[VW]); |
547 | r.normQuat(); | 645 | r.normalize(); |
548 | return r; | 646 | return r; |
549 | } | 647 | } |
550 | 648 | ||
@@ -640,8 +738,8 @@ LLQuaternion slerp(F32 t, const LLQuaternion &q) | |||
640 | // when c < 0.0 then theta > PI/2 | 738 | // when c < 0.0 then theta > PI/2 |
641 | // since quat and -quat are the same rotation we invert one of | 739 | // since quat and -quat are the same rotation we invert one of |
642 | // p or q to reduce unecessary spins | 740 | // p or q to reduce unecessary spins |
643 | // A equivalent way to do it is to convert acos(c) as if it had been negative, | 741 | // A equivalent way to do it is to convert acos(c) as if it had |
644 | // and to negate stp | 742 | // been negative, and to negate stp |
645 | angle = (F32) acos(-c); | 743 | angle = (F32) acos(-c); |
646 | stp = -(F32) sin(angle * (1.f - t)); | 744 | stp = -(F32) sin(angle * (1.f - t)); |
647 | stq = (F32) sin(angle * t); | 745 | stq = (F32) sin(angle * t); |
@@ -742,20 +840,6 @@ LLQuaternion::Order StringToOrder( const char *str ) | |||
742 | return LLQuaternion::XYZ; | 840 | return LLQuaternion::XYZ; |
743 | } | 841 | } |
744 | 842 | ||
745 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat) | ||
746 | { | ||
747 | *this = mat.quaternion(); | ||
748 | normQuat(); | ||
749 | return (*this); | ||
750 | } | ||
751 | |||
752 | const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat) | ||
753 | { | ||
754 | *this = mat.quaternion(); | ||
755 | normQuat(); | ||
756 | return (*this); | ||
757 | } | ||
758 | |||
759 | void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const | 843 | void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const |
760 | { | 844 | { |
761 | F32 cos_a = mQ[VW]; | 845 | F32 cos_a = mQ[VW]; |
@@ -769,10 +853,28 @@ void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const | |||
769 | else | 853 | else |
770 | sin_a = 1.f/sin_a; | 854 | sin_a = 1.f/sin_a; |
771 | 855 | ||
772 | *angle = 2.0f * (F32) acos( cos_a ); | 856 | F32 temp_angle = 2.0f * (F32) acos( cos_a ); |
773 | vec.mV[VX] = mQ[VX] * sin_a; | 857 | if (temp_angle > F_PI) |
774 | vec.mV[VY] = mQ[VY] * sin_a; | 858 | { |
775 | vec.mV[VZ] = mQ[VZ] * sin_a; | 859 | // The (angle,axis) pair should never have angles outside [PI, -PI] |
860 | // since we want the _shortest_ (angle,axis) solution. | ||
861 | // Since acos is defined for [0, PI], and we multiply by 2.0, we | ||
862 | // can push the angle outside the acceptible range. | ||
863 | // When this happens we set the angle to the other portion of a | ||
864 | // full 2PI rotation, and negate the axis, which reverses the | ||
865 | // direction of the rotation (by the right-hand rule). | ||
866 | *angle = 2.f * F_PI - temp_angle; | ||
867 | vec.mV[VX] = - mQ[VX] * sin_a; | ||
868 | vec.mV[VY] = - mQ[VY] * sin_a; | ||
869 | vec.mV[VZ] = - mQ[VZ] * sin_a; | ||
870 | } | ||
871 | else | ||
872 | { | ||
873 | *angle = temp_angle; | ||
874 | vec.mV[VX] = mQ[VX] * sin_a; | ||
875 | vec.mV[VY] = mQ[VY] * sin_a; | ||
876 | vec.mV[VZ] = mQ[VZ] * sin_a; | ||
877 | } | ||
776 | } | 878 | } |
777 | 879 | ||
778 | 880 | ||
@@ -846,7 +948,7 @@ BOOL LLQuaternion::parseQuat(const char* buf, LLQuaternion* value) | |||
846 | S32 count = sscanf( buf, "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); | 948 | S32 count = sscanf( buf, "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 ); |
847 | if( 4 == count ) | 949 | if( 4 == count ) |
848 | { | 950 | { |
849 | value->setQuat( quat ); | 951 | value->set( quat ); |
850 | return TRUE; | 952 | return TRUE; |
851 | } | 953 | } |
852 | 954 | ||
diff --git a/linden/indra/llmath/llquaternion.h b/linden/indra/llmath/llquaternion.h index 6805437..048db2d 100644 --- a/linden/indra/llmath/llquaternion.h +++ b/linden/indra/llmath/llquaternion.h | |||
@@ -57,10 +57,10 @@ public: | |||
57 | LLQuaternion(); // Initializes Quaternion to (0,0,0,1) | 57 | LLQuaternion(); // Initializes Quaternion to (0,0,0,1) |
58 | explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 | 58 | explicit LLQuaternion(const LLMatrix4 &mat); // Initializes Quaternion from Matrix4 |
59 | explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 | 59 | explicit LLQuaternion(const LLMatrix3 &mat); // Initializes Quaternion from Matrix3 |
60 | LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normQuat(x, y, z, w) | 60 | LLQuaternion(F32 x, F32 y, F32 z, F32 w); // Initializes Quaternion to normalize(x, y, z, w) |
61 | LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) | 61 | LLQuaternion(F32 angle, const LLVector4 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) |
62 | LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) | 62 | LLQuaternion(F32 angle, const LLVector3 &vec); // Initializes Quaternion to axis_angle2quat(angle, vec) |
63 | LLQuaternion(const F32 *q); // Initializes Quaternion to normQuat(x, y, z, w) | 63 | LLQuaternion(const F32 *q); // Initializes Quaternion to normalize(x, y, z, w) |
64 | LLQuaternion(const LLVector3 &x_axis, | 64 | LLQuaternion(const LLVector3 &x_axis, |
65 | const LLVector3 &y_axis, | 65 | const LLVector3 &y_axis, |
66 | const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] | 66 | const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis] |
@@ -71,15 +71,27 @@ public: | |||
71 | void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization | 71 | void quantize16(F32 lower, F32 upper); // changes the vector to reflect quatization |
72 | void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization | 72 | void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization |
73 | void loadIdentity(); // Loads the quaternion that represents the identity rotation | 73 | void loadIdentity(); // Loads the quaternion that represents the identity rotation |
74 | const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normQuat(x, y, z, w) | 74 | |
75 | const LLQuaternion& setQuat(const LLQuaternion &quat); // Copies Quaternion | 75 | const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w) |
76 | const LLQuaternion& setQuat(const F32 *q); // Sets Quaternion to normQuat(quat[VX], quat[VY], quat[VZ], quat[VW]) | 76 | const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion |
77 | const LLQuaternion& setQuat(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) | 77 | const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW]) |
78 | const LLQuaternion& setQuat(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) | 78 | const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat) |
79 | const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) | 79 | const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat) |
80 | const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) | 80 | |
81 | const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) | 81 | const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z) |
82 | const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) | 82 | const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) |
83 | const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec) | ||
84 | const LLQuaternion& setEulerAngles(F32 roll, F32 pitch, F32 yaw); // Sets Quaternion to euler2quat(pitch, yaw, roll) | ||
85 | |||
86 | const LLQuaternion& setQuatInit(F32 x, F32 y, F32 z, F32 w); // deprecated | ||
87 | const LLQuaternion& setQuat(const LLQuaternion &quat); // deprecated | ||
88 | const LLQuaternion& setQuat(const F32 *q); // deprecated | ||
89 | const LLQuaternion& setQuat(const LLMatrix3 &mat); // deprecated | ||
90 | const LLQuaternion& setQuat(const LLMatrix4 &mat); // deprecated | ||
91 | const LLQuaternion& setQuat(F32 angle, F32 x, F32 y, F32 z); // deprecated | ||
92 | const LLQuaternion& setQuat(F32 angle, const LLVector3 &vec); // deprecated | ||
93 | const LLQuaternion& setQuat(F32 angle, const LLVector4 &vec); // deprecated | ||
94 | const LLQuaternion& setQuat(F32 roll, F32 pitch, F32 yaw); // deprecated | ||
83 | 95 | ||
84 | LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion | 96 | LLMatrix4 getMatrix4(void) const; // Returns the Matrix4 equivalent of Quaternion |
85 | LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion | 97 | LLMatrix3 getMatrix3(void) const; // Returns the Matrix3 equivalent of Quaternion |
@@ -87,11 +99,16 @@ public: | |||
87 | void getAngleAxis(F32* angle, LLVector3 &vec) const; | 99 | void getAngleAxis(F32* angle, LLVector3 &vec) const; |
88 | void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; | 100 | void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const; |
89 | 101 | ||
90 | F32 normQuat(); // Normalizes Quaternion and returns magnitude | 102 | F32 normalize(); // Normalizes Quaternion and returns magnitude |
91 | const LLQuaternion& conjQuat(void); // Conjugates Quaternion and returns result | 103 | F32 normQuat(); // deprecated |
104 | |||
105 | const LLQuaternion& conjugate(void); // Conjugates Quaternion and returns result | ||
106 | const LLQuaternion& conjQuat(void); // deprecated | ||
92 | 107 | ||
93 | // Other useful methods | 108 | // Other useful methods |
94 | const LLQuaternion& transQuat(); // Transpose | 109 | const LLQuaternion& transpose(); // transpose (same as conjugate) |
110 | const LLQuaternion& transQuat(); // deprecated | ||
111 | |||
95 | void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b | 112 | void shortestArc(const LLVector3 &a, const LLVector3 &b); // shortest rotation from a to b |
96 | const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians | 113 | const LLQuaternion& constrain(F32 radians); // constrains rotation to a cone angle specified in radians |
97 | 114 | ||
@@ -189,7 +206,7 @@ inline LLQuaternion::LLQuaternion(F32 x, F32 y, F32 z, F32 w) | |||
189 | mQ[VS] = w; | 206 | mQ[VS] = w; |
190 | 207 | ||
191 | //RN: don't normalize this case as its used mainly for temporaries during calculations | 208 | //RN: don't normalize this case as its used mainly for temporaries during calculations |
192 | //normQuat(); | 209 | //normalize(); |
193 | /* | 210 | /* |
194 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | 211 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); |
195 | mag -= 1.f; | 212 | mag -= 1.f; |
@@ -205,7 +222,7 @@ inline LLQuaternion::LLQuaternion(const F32 *q) | |||
205 | mQ[VZ] = q[VZ]; | 222 | mQ[VZ] = q[VZ]; |
206 | mQ[VS] = q[VW]; | 223 | mQ[VS] = q[VW]; |
207 | 224 | ||
208 | normQuat(); | 225 | normalize(); |
209 | /* | 226 | /* |
210 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | 227 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); |
211 | mag -= 1.f; | 228 | mag -= 1.f; |
@@ -224,33 +241,67 @@ inline void LLQuaternion::loadIdentity() | |||
224 | } | 241 | } |
225 | 242 | ||
226 | 243 | ||
244 | inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w) | ||
245 | { | ||
246 | mQ[VX] = x; | ||
247 | mQ[VY] = y; | ||
248 | mQ[VZ] = z; | ||
249 | mQ[VS] = w; | ||
250 | normalize(); | ||
251 | return (*this); | ||
252 | } | ||
253 | |||
254 | inline const LLQuaternion& LLQuaternion::set(const LLQuaternion &quat) | ||
255 | { | ||
256 | mQ[VX] = quat.mQ[VX]; | ||
257 | mQ[VY] = quat.mQ[VY]; | ||
258 | mQ[VZ] = quat.mQ[VZ]; | ||
259 | mQ[VW] = quat.mQ[VW]; | ||
260 | normalize(); | ||
261 | return (*this); | ||
262 | } | ||
263 | |||
264 | inline const LLQuaternion& LLQuaternion::set(const F32 *q) | ||
265 | { | ||
266 | mQ[VX] = q[VX]; | ||
267 | mQ[VY] = q[VY]; | ||
268 | mQ[VZ] = q[VZ]; | ||
269 | mQ[VS] = q[VW]; | ||
270 | normalize(); | ||
271 | return (*this); | ||
272 | } | ||
273 | |||
274 | |||
275 | // deprecated | ||
227 | inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) | 276 | inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) |
228 | { | 277 | { |
229 | mQ[VX] = x; | 278 | mQ[VX] = x; |
230 | mQ[VY] = y; | 279 | mQ[VY] = y; |
231 | mQ[VZ] = z; | 280 | mQ[VZ] = z; |
232 | mQ[VS] = w; | 281 | mQ[VS] = w; |
233 | normQuat(); | 282 | normalize(); |
234 | return (*this); | 283 | return (*this); |
235 | } | 284 | } |
236 | 285 | ||
286 | // deprecated | ||
237 | inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) | 287 | inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) |
238 | { | 288 | { |
239 | mQ[VX] = quat.mQ[VX]; | 289 | mQ[VX] = quat.mQ[VX]; |
240 | mQ[VY] = quat.mQ[VY]; | 290 | mQ[VY] = quat.mQ[VY]; |
241 | mQ[VZ] = quat.mQ[VZ]; | 291 | mQ[VZ] = quat.mQ[VZ]; |
242 | mQ[VW] = quat.mQ[VW]; | 292 | mQ[VW] = quat.mQ[VW]; |
243 | normQuat(); | 293 | normalize(); |
244 | return (*this); | 294 | return (*this); |
245 | } | 295 | } |
246 | 296 | ||
297 | // deprecated | ||
247 | inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) | 298 | inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) |
248 | { | 299 | { |
249 | mQ[VX] = q[VX]; | 300 | mQ[VX] = q[VX]; |
250 | mQ[VY] = q[VY]; | 301 | mQ[VY] = q[VY]; |
251 | mQ[VZ] = q[VZ]; | 302 | mQ[VZ] = q[VZ]; |
252 | mQ[VS] = q[VW]; | 303 | mQ[VS] = q[VW]; |
253 | normQuat(); | 304 | normalize(); |
254 | return (*this); | 305 | return (*this); |
255 | } | 306 | } |
256 | 307 | ||
@@ -270,10 +321,36 @@ inline void LLQuaternion::getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const | |||
270 | else | 321 | else |
271 | sin_a = 1.f/sin_a; | 322 | sin_a = 1.f/sin_a; |
272 | 323 | ||
273 | *angle = 2.0f * (F32) acos( cos_a ); | 324 | F32 temp_angle = 2.0f * (F32) acos( cos_a ); |
274 | *x = mQ[VX] * sin_a; | 325 | if (temp_angle > F_PI) |
275 | *y = mQ[VY] * sin_a; | 326 | { |
276 | *z = mQ[VZ] * sin_a; | 327 | // The (angle,axis) pair should never have angles outside [PI, -PI] |
328 | // since we want the _shortest_ (angle,axis) solution. | ||
329 | // Since acos is defined for [0, PI], and we multiply by 2.0, we | ||
330 | // can push the angle outside the acceptible range. | ||
331 | // When this happens we set the angle to the other portion of a | ||
332 | // full 2PI rotation, and negate the axis, which reverses the | ||
333 | // direction of the rotation (by the right-hand rule). | ||
334 | *angle = 2.f * F_PI - temp_angle; | ||
335 | *x = - mQ[VX] * sin_a; | ||
336 | *y = - mQ[VY] * sin_a; | ||
337 | *z = - mQ[VZ] * sin_a; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | *angle = temp_angle; | ||
342 | *x = mQ[VX] * sin_a; | ||
343 | *y = mQ[VY] * sin_a; | ||
344 | *z = mQ[VZ] * sin_a; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | inline const LLQuaternion& LLQuaternion::conjugate() | ||
349 | { | ||
350 | mQ[VX] *= -1.f; | ||
351 | mQ[VY] *= -1.f; | ||
352 | mQ[VZ] *= -1.f; | ||
353 | return (*this); | ||
277 | } | 354 | } |
278 | 355 | ||
279 | inline const LLQuaternion& LLQuaternion::conjQuat() | 356 | inline const LLQuaternion& LLQuaternion::conjQuat() |
@@ -285,12 +362,21 @@ inline const LLQuaternion& LLQuaternion::conjQuat() | |||
285 | } | 362 | } |
286 | 363 | ||
287 | // Transpose | 364 | // Transpose |
365 | inline const LLQuaternion& LLQuaternion::transpose() | ||
366 | { | ||
367 | mQ[VX] *= -1.f; | ||
368 | mQ[VY] *= -1.f; | ||
369 | mQ[VZ] *= -1.f; | ||
370 | return (*this); | ||
371 | } | ||
372 | |||
373 | // deprecated | ||
288 | inline const LLQuaternion& LLQuaternion::transQuat() | 374 | inline const LLQuaternion& LLQuaternion::transQuat() |
289 | { | 375 | { |
290 | mQ[VX] = -mQ[VX]; | 376 | mQ[VX] *= -1.f; |
291 | mQ[VY] = -mQ[VY]; | 377 | mQ[VY] *= -1.f; |
292 | mQ[VZ] = -mQ[VZ]; | 378 | mQ[VZ] *= -1.f; |
293 | return *this; | 379 | return (*this); |
294 | } | 380 | } |
295 | 381 | ||
296 | 382 | ||
@@ -382,6 +468,30 @@ inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b) | |||
382 | return a; | 468 | return a; |
383 | } | 469 | } |
384 | 470 | ||
471 | inline F32 LLQuaternion::normalize() | ||
472 | { | ||
473 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | ||
474 | |||
475 | if (mag > FP_MAG_THRESHOLD) | ||
476 | { | ||
477 | F32 oomag = 1.f/mag; | ||
478 | mQ[VX] *= oomag; | ||
479 | mQ[VY] *= oomag; | ||
480 | mQ[VZ] *= oomag; | ||
481 | mQ[VS] *= oomag; | ||
482 | } | ||
483 | else | ||
484 | { | ||
485 | mQ[VX] = 0.f; | ||
486 | mQ[VY] = 0.f; | ||
487 | mQ[VZ] = 0.f; | ||
488 | mQ[VS] = 1.f; | ||
489 | } | ||
490 | |||
491 | return mag; | ||
492 | } | ||
493 | |||
494 | // deprecated | ||
385 | inline F32 LLQuaternion::normQuat() | 495 | inline F32 LLQuaternion::normQuat() |
386 | { | 496 | { |
387 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); | 497 | F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]); |
diff --git a/linden/indra/llmath/llrect.h b/linden/indra/llmath/llrect.h index 9aadf9f..f2a5d75 100644 --- a/linden/indra/llmath/llrect.h +++ b/linden/indra/llmath/llrect.h | |||
@@ -227,6 +227,11 @@ public: | |||
227 | return mLeft == mRight || mBottom == mTop; | 227 | return mLeft == mRight || mBottom == mTop; |
228 | } | 228 | } |
229 | 229 | ||
230 | bool notNull() const | ||
231 | { | ||
232 | return !isNull(); | ||
233 | } | ||
234 | |||
230 | LLRectBase& unionWith(const LLRectBase &other) | 235 | LLRectBase& unionWith(const LLRectBase &other) |
231 | { | 236 | { |
232 | mLeft = llmin(mLeft, other.mLeft); | 237 | mLeft = llmin(mLeft, other.mLeft); |
diff --git a/linden/indra/llmath/llsphere.cpp b/linden/indra/llmath/llsphere.cpp new file mode 100644 index 0000000..62f6e27 --- /dev/null +++ b/linden/indra/llmath/llsphere.cpp | |||
@@ -0,0 +1,364 @@ | |||
1 | /** | ||
2 | * @file llsphere.cpp | ||
3 | * @author Andrew Meadows | ||
4 | * @brief Simple line class that can compute nearest approach between two lines | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2006&license=internal$ | ||
7 | * | ||
8 | * Copyright (c) 2006-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 "llsphere.h" | ||
24 | |||
25 | LLSphere::LLSphere() | ||
26 | : mCenter(0.f, 0.f, 0.f), | ||
27 | mRadius(0.f) | ||
28 | { } | ||
29 | |||
30 | LLSphere::LLSphere( const LLVector3& center, F32 radius) | ||
31 | { | ||
32 | set(center, radius); | ||
33 | } | ||
34 | |||
35 | void LLSphere::set( const LLVector3& center, F32 radius ) | ||
36 | { | ||
37 | mCenter = center; | ||
38 | setRadius(radius); | ||
39 | } | ||
40 | |||
41 | void LLSphere::setCenter( const LLVector3& center) | ||
42 | { | ||
43 | mCenter = center; | ||
44 | } | ||
45 | |||
46 | void LLSphere::setRadius( F32 radius) | ||
47 | { | ||
48 | if (radius < 0.f) | ||
49 | { | ||
50 | radius = -radius; | ||
51 | } | ||
52 | mRadius = radius; | ||
53 | } | ||
54 | |||
55 | const LLVector3& LLSphere::getCenter() const | ||
56 | { | ||
57 | return mCenter; | ||
58 | } | ||
59 | |||
60 | F32 LLSphere::getRadius() const | ||
61 | { | ||
62 | return mRadius; | ||
63 | } | ||
64 | |||
65 | // returns 'TRUE' if this sphere completely contains other_sphere | ||
66 | BOOL LLSphere::contains(const LLSphere& other_sphere) const | ||
67 | { | ||
68 | F32 separation = (mCenter - other_sphere.mCenter).length(); | ||
69 | return (mRadius >= separation + other_sphere.mRadius) ? TRUE : FALSE; | ||
70 | } | ||
71 | |||
72 | // returns 'TRUE' if this sphere completely contains other_sphere | ||
73 | BOOL LLSphere::overlaps(const LLSphere& other_sphere) const | ||
74 | { | ||
75 | F32 separation = (mCenter - other_sphere.mCenter).length(); | ||
76 | return (separation <= mRadius + other_sphere.mRadius) ? TRUE : FALSE; | ||
77 | } | ||
78 | |||
79 | // returns overlap | ||
80 | // negative overlap is closest approach | ||
81 | F32 LLSphere::getOverlap(const LLSphere& other_sphere) const | ||
82 | { | ||
83 | // separation is distance from other_sphere's edge and this center | ||
84 | return (mCenter - other_sphere.mCenter).length() - mRadius - other_sphere.mRadius; | ||
85 | } | ||
86 | |||
87 | bool LLSphere::operator==(const LLSphere& rhs) const | ||
88 | { | ||
89 | // TODO? -- use approximate equality for centers? | ||
90 | return (mRadius == rhs.mRadius | ||
91 | && mCenter == rhs.mCenter); | ||
92 | } | ||
93 | |||
94 | std::ostream& operator<<( std::ostream& output_stream, const LLSphere& sphere) | ||
95 | { | ||
96 | output_stream << "{center=" << sphere.mCenter << "," << "radius=" << sphere.mRadius << "}"; | ||
97 | return output_stream; | ||
98 | } | ||
99 | |||
100 | // static | ||
101 | // removes any spheres that are contained in others | ||
102 | void LLSphere::collapse(std::vector<LLSphere>& sphere_list) | ||
103 | { | ||
104 | std::vector<LLSphere>::iterator first_itr = sphere_list.begin(); | ||
105 | while (first_itr != sphere_list.end()) | ||
106 | { | ||
107 | bool delete_from_front = false; | ||
108 | |||
109 | std::vector<LLSphere>::iterator second_itr = first_itr; | ||
110 | ++second_itr; | ||
111 | while (second_itr != sphere_list.end()) | ||
112 | { | ||
113 | if (second_itr->contains(*first_itr)) | ||
114 | { | ||
115 | delete_from_front = true; | ||
116 | break; | ||
117 | } | ||
118 | else if (first_itr->contains(*second_itr)) | ||
119 | { | ||
120 | sphere_list.erase(second_itr++); | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | ++second_itr; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | if (delete_from_front) | ||
129 | { | ||
130 | sphere_list.erase(first_itr++); | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | ++first_itr; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | // static | ||
140 | // returns the bounding sphere that contains both spheres | ||
141 | LLSphere LLSphere::getBoundingSphere(const LLSphere& first_sphere, const LLSphere& second_sphere) | ||
142 | { | ||
143 | LLVector3 direction = second_sphere.mCenter - first_sphere.mCenter; | ||
144 | |||
145 | // HACK -- it is possible to get enough floating point error in the | ||
146 | // other getBoundingSphere() method that we have to add some slop | ||
147 | // at the end. Unfortunately, this breaks the link-order invarience | ||
148 | // for the linkability tests... unless we also apply the same slop | ||
149 | // here. | ||
150 | F32 half_milimeter = 0.0005f; | ||
151 | |||
152 | F32 distance = direction.length(); | ||
153 | if (0.f == distance) | ||
154 | { | ||
155 | direction.setVec(1.f, 0.f, 0.f); | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | direction.normVec(); | ||
160 | } | ||
161 | // the 'edge' is measured from the first_sphere's center | ||
162 | F32 max_edge = 0.f; | ||
163 | F32 min_edge = 0.f; | ||
164 | |||
165 | max_edge = llmax(max_edge + first_sphere.getRadius(), max_edge + distance + second_sphere.getRadius() + half_milimeter); | ||
166 | min_edge = llmin(min_edge - first_sphere.getRadius(), min_edge + distance - second_sphere.getRadius() - half_milimeter); | ||
167 | F32 radius = 0.5f * (max_edge - min_edge); | ||
168 | LLVector3 center = first_sphere.mCenter + (0.5f * (max_edge + min_edge)) * direction; | ||
169 | return LLSphere(center, radius); | ||
170 | } | ||
171 | |||
172 | // static | ||
173 | // returns the bounding sphere that contains an arbitrary set of spheres | ||
174 | LLSphere LLSphere::getBoundingSphere(const std::vector<LLSphere>& sphere_list) | ||
175 | { | ||
176 | // this algorithm can get relatively inaccurate when the sphere | ||
177 | // collection is 'small' (contained within a bounding sphere of about | ||
178 | // 2 meters or less) | ||
179 | // TODO -- improve the accuracy for small collections of spheres | ||
180 | |||
181 | LLSphere bounding_sphere( LLVector3(0.f, 0.f, 0.f), 0.f ); | ||
182 | S32 sphere_count = sphere_list.size(); | ||
183 | if (1 == sphere_count) | ||
184 | { | ||
185 | // trivial case -- single sphere | ||
186 | std::vector<LLSphere>::const_iterator sphere_itr = sphere_list.begin(); | ||
187 | bounding_sphere = *sphere_itr; | ||
188 | } | ||
189 | else if (2 == sphere_count) | ||
190 | { | ||
191 | // trivial case -- two spheres | ||
192 | std::vector<LLSphere>::const_iterator first_sphere = sphere_list.begin(); | ||
193 | std::vector<LLSphere>::const_iterator second_sphere = first_sphere; | ||
194 | ++second_sphere; | ||
195 | bounding_sphere = LLSphere::getBoundingSphere(*first_sphere, *second_sphere); | ||
196 | } | ||
197 | else if (sphere_count > 0) | ||
198 | { | ||
199 | // non-trivial case -- we will approximate the solution | ||
200 | // | ||
201 | // NOTE -- there is a fancy/fast way to do this for large | ||
202 | // numbers of arbirary N-dimensional spheres -- you can look it | ||
203 | // up on the net. We're dealing with 3D spheres at collection | ||
204 | // sizes of 256 spheres or smaller, so we just use this | ||
205 | // brute force method. | ||
206 | |||
207 | // TODO -- perhaps would be worthwile to test for the solution where | ||
208 | // the largest spanning radius just happens to work. That is, where | ||
209 | // there are really two spheres that determine the bounding sphere, | ||
210 | // and all others are contained therein. | ||
211 | |||
212 | // compute the AABB | ||
213 | std::vector<LLSphere>::const_iterator first_itr = sphere_list.begin(); | ||
214 | LLVector3 max_corner = first_itr->getCenter() + first_itr->getRadius() * LLVector3(1.f, 1.f, 1.f); | ||
215 | LLVector3 min_corner = first_itr->getCenter() - first_itr->getRadius() * LLVector3(1.f, 1.f, 1.f); | ||
216 | { | ||
217 | std::vector<LLSphere>::const_iterator sphere_itr = sphere_list.begin(); | ||
218 | for (++sphere_itr; sphere_itr != sphere_list.end(); ++sphere_itr) | ||
219 | { | ||
220 | LLVector3 center = sphere_itr->getCenter(); | ||
221 | F32 radius = sphere_itr->getRadius(); | ||
222 | for (S32 i=0; i<3; ++i) | ||
223 | { | ||
224 | if (center.mV[i] + radius > max_corner.mV[i]) | ||
225 | { | ||
226 | max_corner.mV[i] = center.mV[i] + radius; | ||
227 | } | ||
228 | if (center.mV[i] - radius < min_corner.mV[i]) | ||
229 | { | ||
230 | min_corner.mV[i] = center.mV[i] - radius; | ||
231 | } | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | // get the starting center and radius from the AABB | ||
237 | LLVector3 diagonal = max_corner - min_corner; | ||
238 | F32 bounding_radius = 0.5f * diagonal.length(); | ||
239 | LLVector3 bounding_center = 0.5f * (max_corner + min_corner); | ||
240 | |||
241 | // compute the starting step-size | ||
242 | F32 minimum_radius = 0.5f * llmin(diagonal.mV[VX], llmin(diagonal.mV[VY], diagonal.mV[VZ])); | ||
243 | F32 step_length = bounding_radius - minimum_radius; | ||
244 | S32 step_count = 0; | ||
245 | S32 max_step_count = 12; | ||
246 | F32 half_milimeter = 0.0005f; | ||
247 | |||
248 | // wander the center around in search of tighter solutions | ||
249 | S32 last_dx = 2; // 2 is out of bounds --> no match | ||
250 | S32 last_dy = 2; | ||
251 | S32 last_dz = 2; | ||
252 | |||
253 | while (step_length > half_milimeter | ||
254 | && step_count < max_step_count) | ||
255 | { | ||
256 | // the algorithm for testing the maximum radius could be expensive enough | ||
257 | // that it makes sense to NOT duplicate testing when possible, so we keep | ||
258 | // track of where we last tested, and only test the new points | ||
259 | |||
260 | S32 best_dx = 0; | ||
261 | S32 best_dy = 0; | ||
262 | S32 best_dz = 0; | ||
263 | |||
264 | // sample near the center of the box | ||
265 | bool found_better_center = false; | ||
266 | for (S32 dx = -1; dx < 2; ++dx) | ||
267 | { | ||
268 | for (S32 dy = -1; dy < 2; ++dy) | ||
269 | { | ||
270 | for (S32 dz = -1; dz < 2; ++dz) | ||
271 | { | ||
272 | if (dx == 0 && dy == 0 && dz == 0) | ||
273 | { | ||
274 | continue; | ||
275 | } | ||
276 | |||
277 | // count the number of indecies that match the last_*'s | ||
278 | S32 match_count = 0; | ||
279 | if (last_dx == dx) ++match_count; | ||
280 | if (last_dy == dy) ++match_count; | ||
281 | if (last_dz == dz) ++match_count; | ||
282 | if (match_count == 2) | ||
283 | { | ||
284 | // we've already tested this point | ||
285 | continue; | ||
286 | } | ||
287 | |||
288 | LLVector3 center = bounding_center; | ||
289 | center.mV[VX] += (F32) dx * step_length; | ||
290 | center.mV[VY] += (F32) dy * step_length; | ||
291 | center.mV[VZ] += (F32) dz * step_length; | ||
292 | |||
293 | // compute the radius of the bounding sphere | ||
294 | F32 max_radius = 0.f; | ||
295 | std::vector<LLSphere>::const_iterator sphere_itr; | ||
296 | for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) | ||
297 | { | ||
298 | F32 radius = (sphere_itr->getCenter() - center).length() + sphere_itr->getRadius(); | ||
299 | if (radius > max_radius) | ||
300 | { | ||
301 | max_radius = radius; | ||
302 | } | ||
303 | } | ||
304 | if (max_radius < bounding_radius) | ||
305 | { | ||
306 | best_dx = dx; | ||
307 | best_dy = dy; | ||
308 | best_dz = dz; | ||
309 | bounding_center = center; | ||
310 | bounding_radius = max_radius; | ||
311 | found_better_center = true; | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | } | ||
316 | if (found_better_center) | ||
317 | { | ||
318 | // remember where we came from so we can avoid retesting | ||
319 | last_dx = -best_dx; | ||
320 | last_dy = -best_dy; | ||
321 | last_dz = -best_dz; | ||
322 | } | ||
323 | else | ||
324 | { | ||
325 | // reduce the step size | ||
326 | step_length *= 0.5f; | ||
327 | //++step_count; | ||
328 | // reset the last_*'s | ||
329 | last_dx = 2; // 2 is out of bounds --> no match | ||
330 | last_dy = 2; | ||
331 | last_dz = 2; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | // HACK -- it is possible to get enough floating point error for the | ||
336 | // bounding sphere to too small on the order of 10e-6, but we only need | ||
337 | // it to be accurate to within about half a millimeter | ||
338 | bounding_radius += half_milimeter; | ||
339 | |||
340 | // this algorithm can get relatively inaccurate when the sphere | ||
341 | // collection is 'small' (contained within a bounding sphere of about | ||
342 | // 2 meters or less) | ||
343 | // TODO -- fix this | ||
344 | /* debug code | ||
345 | { | ||
346 | std::vector<LLSphere>::const_iterator sphere_itr; | ||
347 | for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr) | ||
348 | { | ||
349 | F32 radius = (sphere_itr->getCenter() - bounding_center).length() + sphere_itr->getRadius(); | ||
350 | if (radius + 0.1f > bounding_radius) | ||
351 | { | ||
352 | std::cout << " rad = " << radius << " bounding - rad = " << (bounding_radius - radius) << std::endl; | ||
353 | } | ||
354 | } | ||
355 | std::cout << "\n" << std::endl; | ||
356 | } | ||
357 | */ | ||
358 | |||
359 | bounding_sphere.set(bounding_center, bounding_radius); | ||
360 | } | ||
361 | return bounding_sphere; | ||
362 | } | ||
363 | |||
364 | |||
diff --git a/linden/indra/llmath/llsphere.h b/linden/indra/llmath/llsphere.h new file mode 100644 index 0000000..4d7cd7a --- /dev/null +++ b/linden/indra/llmath/llsphere.h | |||
@@ -0,0 +1,72 @@ | |||
1 | // llsphere.h | ||
2 | /** | ||
3 | * @file llsphere.cpp | ||
4 | * @author Andrew Meadows | ||
5 | * @brief Simple sphere implementation for basic geometric operations | ||
6 | * | ||
7 | * $LicenseInfo:firstyear=2001&license=internal$ | ||
8 | * | ||
9 | * Copyright (c) 2001-2008, Linden Research, Inc. | ||
10 | * | ||
11 | * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of | ||
12 | * this source code is governed by the Linden Lab Source Code Disclosure | ||
13 | * Agreement ("Agreement") previously entered between you and Linden | ||
14 | * Lab. By accessing, using, copying, modifying or distributing this | ||
15 | * software, you acknowledge that you have been informed of your | ||
16 | * obligations under the Agreement and agree to abide by those obligations. | ||
17 | * | ||
18 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
19 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
20 | * COMPLETENESS OR PERFORMANCE. | ||
21 | * $/LicenseInfo$ | ||
22 | */ | ||
23 | |||
24 | #ifndef LL_SPHERE_H | ||
25 | #define LL_SPHERE_H | ||
26 | |||
27 | #include "stdtypes.h" | ||
28 | #include "v3math.h" | ||
29 | #include <iostream> | ||
30 | #include <vector> | ||
31 | |||
32 | class LLSphere | ||
33 | { | ||
34 | public: | ||
35 | LLSphere(); | ||
36 | LLSphere( const LLVector3& center, F32 radius ); | ||
37 | |||
38 | void set( const LLVector3& center, F32 radius ); | ||
39 | void setCenter( const LLVector3& center ); | ||
40 | void setRadius( F32 radius ); | ||
41 | |||
42 | const LLVector3& getCenter() const; | ||
43 | F32 getRadius() const; | ||
44 | |||
45 | // returns TRUE if this sphere completely contains other_sphere | ||
46 | BOOL contains(const LLSphere& other_sphere) const; | ||
47 | |||
48 | // returns TRUE if this sphere overlaps other_sphere | ||
49 | BOOL overlaps(const LLSphere& other_sphere) const; | ||
50 | |||
51 | // returns overlap distance | ||
52 | // negative overlap is closest approach | ||
53 | F32 getOverlap(const LLSphere& other_sphere) const; | ||
54 | |||
55 | // removes any spheres that are contained in others | ||
56 | static void collapse(std::vector<LLSphere>& sphere_list); | ||
57 | |||
58 | // returns minimum sphere bounding sphere for a set of spheres | ||
59 | static LLSphere getBoundingSphere(const LLSphere& first_sphere, const LLSphere& second_sphere); | ||
60 | static LLSphere getBoundingSphere(const std::vector<LLSphere>& sphere_list); | ||
61 | |||
62 | bool operator==(const LLSphere& rhs) const; | ||
63 | |||
64 | friend std::ostream& operator<<( std::ostream& output_stream, const LLSphere& line ); | ||
65 | |||
66 | protected: | ||
67 | LLVector3 mCenter; | ||
68 | F32 mRadius; | ||
69 | }; | ||
70 | |||
71 | |||
72 | #endif | ||
diff --git a/linden/indra/llmath/lluuid.cpp b/linden/indra/llmath/lluuid.cpp index db9e869..d835cbc 100644 --- a/linden/indra/llmath/lluuid.cpp +++ b/linden/indra/llmath/lluuid.cpp | |||
@@ -867,6 +867,11 @@ void LLUUID::generate() | |||
867 | time_last = timestamp; | 867 | time_last = timestamp; |
868 | } | 868 | } |
869 | 869 | ||
870 | void LLUUID::generate(std::string hash_string) | ||
871 | { | ||
872 | LLMD5 md5_uuid((U8*)hash_string.c_str()); | ||
873 | md5_uuid.raw_digest(mData); | ||
874 | } | ||
870 | 875 | ||
871 | U32 LLUUID::getRandomSeed() | 876 | U32 LLUUID::getRandomSeed() |
872 | { | 877 | { |
diff --git a/linden/indra/llmath/lluuid.h b/linden/indra/llmath/lluuid.h index 190b772..48308f2 100644 --- a/linden/indra/llmath/lluuid.h +++ b/linden/indra/llmath/lluuid.h | |||
@@ -64,6 +64,7 @@ public: | |||
64 | // MANIPULATORS | 64 | // MANIPULATORS |
65 | // | 65 | // |
66 | void generate(); // Generate a new UUID | 66 | void generate(); // Generate a new UUID |
67 | void generate(std::string stream); //Generate a new UUID based on hash of input stream | ||
67 | BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings | 68 | BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings |
68 | BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings | 69 | BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings |
69 | void setNull(); // Faster than setting to LLUUID::null. | 70 | void setNull(); // Faster than setting to LLUUID::null. |
diff --git a/linden/indra/llmath/llvolume.cpp b/linden/indra/llmath/llvolume.cpp index 4f1c260..9c19220 100644 --- a/linden/indra/llmath/llvolume.cpp +++ b/linden/indra/llmath/llvolume.cpp | |||
@@ -1858,9 +1858,6 @@ inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, | |||
1858 | { | 1858 | { |
1859 | U32 index = (x + y * sculpt_width) * sculpt_components; | 1859 | U32 index = (x + y * sculpt_width) * sculpt_components; |
1860 | 1860 | ||
1861 | // attempt to resolve DEV-11158 - remove assert later. | ||
1862 | //llassert(index < sculpt_width * sculpt_height * sculpt_components); | ||
1863 | |||
1864 | return index; | 1861 | return index; |
1865 | } | 1862 | } |
1866 | 1863 | ||
@@ -2513,12 +2510,19 @@ bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 h | |||
2513 | return true; | 2510 | return true; |
2514 | } | 2511 | } |
2515 | 2512 | ||
2516 | #define MAX_INDEX 10000 | ||
2517 | S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | 2513 | S32 *LLVolume::getTriangleIndices(U32 &num_indices) const |
2518 | { | 2514 | { |
2519 | S32 index[MAX_INDEX]; | 2515 | S32 expected_num_triangle_indices = getNumTriangleIndices(); |
2516 | if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES) | ||
2517 | { | ||
2518 | // we don't allow LLVolumes with this many vertices | ||
2519 | llwarns << "Couldn't allocate triangle indices" << llendl; | ||
2520 | num_indices = 0; | ||
2521 | return NULL; | ||
2522 | } | ||
2523 | |||
2524 | S32* index = new S32[expected_num_triangle_indices]; | ||
2520 | S32 count = 0; | 2525 | S32 count = 0; |
2521 | S32 *indices = NULL; | ||
2522 | 2526 | ||
2523 | // Let's do this totally diffently, as we don't care about faces... | 2527 | // Let's do this totally diffently, as we don't care about faces... |
2524 | // Counter-clockwise triangles are forward facing... | 2528 | // Counter-clockwise triangles are forward facing... |
@@ -2532,6 +2536,9 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2532 | size_s_out = getProfile().getTotalOut(); | 2536 | size_s_out = getProfile().getTotalOut(); |
2533 | size_t = getPath().mPath.size(); | 2537 | size_t = getPath().mPath.size(); |
2534 | 2538 | ||
2539 | // NOTE -- if the construction of the triangles below ever changes | ||
2540 | // then getNumTriangleIndices() method may also have to be updated. | ||
2541 | |||
2535 | if (open) /* Flawfinder: ignore */ | 2542 | if (open) /* Flawfinder: ignore */ |
2536 | { | 2543 | { |
2537 | if (hollow) | 2544 | if (hollow) |
@@ -2539,9 +2546,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2539 | // Open hollow -- much like the closed solid, except we | 2546 | // Open hollow -- much like the closed solid, except we |
2540 | // we need to stitch up the gap between s=0 and s=size_s-1 | 2547 | // we need to stitch up the gap between s=0 and s=size_s-1 |
2541 | 2548 | ||
2542 | if ( (size_t - 1) * (((size_s -1) * 6) + 6) >= MAX_INDEX) | ||
2543 | goto noindices; | ||
2544 | |||
2545 | for (t = 0; t < size_t - 1; t++) | 2549 | for (t = 0; t < size_t - 1; t++) |
2546 | { | 2550 | { |
2547 | // The outer face, first cut, and inner face | 2551 | // The outer face, first cut, and inner face |
@@ -2655,8 +2659,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2655 | 2659 | ||
2656 | if (use_tri1a2) | 2660 | if (use_tri1a2) |
2657 | { | 2661 | { |
2658 | if (count + 3 >= MAX_INDEX) | ||
2659 | goto noindices; | ||
2660 | index[count++] = pt1 + i; | 2662 | index[count++] = pt1 + i; |
2661 | index[count++] = pt1 + 1 + i; | 2663 | index[count++] = pt1 + 1 + i; |
2662 | index[count++] = pt2 + i; | 2664 | index[count++] = pt2 + i; |
@@ -2664,8 +2666,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2664 | } | 2666 | } |
2665 | else | 2667 | else |
2666 | { | 2668 | { |
2667 | if (count + 3 >= MAX_INDEX) | ||
2668 | goto noindices; | ||
2669 | index[count++] = pt1 + i; | 2669 | index[count++] = pt1 + i; |
2670 | index[count++] = pt2 - 1 + i; | 2670 | index[count++] = pt2 - 1 + i; |
2671 | index[count++] = pt2 + i; | 2671 | index[count++] = pt2 + i; |
@@ -2756,8 +2756,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2756 | 2756 | ||
2757 | if (use_tri1a2) | 2757 | if (use_tri1a2) |
2758 | { | 2758 | { |
2759 | if (count + 3 >= MAX_INDEX) | ||
2760 | goto noindices; | ||
2761 | index[count++] = pt1; | 2759 | index[count++] = pt1; |
2762 | index[count++] = pt2; | 2760 | index[count++] = pt2; |
2763 | index[count++] = pt1 + 1; | 2761 | index[count++] = pt1 + 1; |
@@ -2765,8 +2763,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2765 | } | 2763 | } |
2766 | else | 2764 | else |
2767 | { | 2765 | { |
2768 | if (count + 3 >= MAX_INDEX) | ||
2769 | goto noindices; | ||
2770 | index[count++] = pt1; | 2766 | index[count++] = pt1; |
2771 | index[count++] = pt2; | 2767 | index[count++] = pt2; |
2772 | index[count++] = pt2 - 1; | 2768 | index[count++] = pt2 - 1; |
@@ -2779,9 +2775,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2779 | { | 2775 | { |
2780 | // Open solid | 2776 | // Open solid |
2781 | 2777 | ||
2782 | if ( (size_t - 1) * (((size_s -1) * 6) + 6) >= MAX_INDEX) | ||
2783 | goto noindices; | ||
2784 | |||
2785 | for (t = 0; t < size_t - 1; t++) | 2778 | for (t = 0; t < size_t - 1; t++) |
2786 | { | 2779 | { |
2787 | // Outer face + 1 cut face | 2780 | // Outer face + 1 cut face |
@@ -2811,8 +2804,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2811 | // Do the top and bottom caps, if necessary | 2804 | // Do the top and bottom caps, if necessary |
2812 | if (path_open) | 2805 | if (path_open) |
2813 | { | 2806 | { |
2814 | if ( count + (size_s - 2) * 3 >= MAX_INDEX) | ||
2815 | goto noindices; | ||
2816 | for (s = 0; s < size_s - 2; s++) | 2807 | for (s = 0; s < size_s - 2; s++) |
2817 | { | 2808 | { |
2818 | index[count++] = s+1; | 2809 | index[count++] = s+1; |
@@ -2822,8 +2813,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2822 | 2813 | ||
2823 | // We've got a top cap | 2814 | // We've got a top cap |
2824 | S32 offset = (size_t - 1)*size_s; | 2815 | S32 offset = (size_t - 1)*size_s; |
2825 | if ( count + (size_s - 2) * 3 >= MAX_INDEX) | ||
2826 | goto noindices; | ||
2827 | for (s = 0; s < size_s - 2; s++) | 2816 | for (s = 0; s < size_s - 2; s++) |
2828 | { | 2817 | { |
2829 | // Inverted ordering from bottom cap. | 2818 | // Inverted ordering from bottom cap. |
@@ -2839,8 +2828,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2839 | // Closed hollow | 2828 | // Closed hollow |
2840 | // Outer face | 2829 | // Outer face |
2841 | 2830 | ||
2842 | if ( (size_t - 1) * (size_s_out - 1) * 6 >= MAX_INDEX) | ||
2843 | goto noindices; | ||
2844 | for (t = 0; t < size_t - 1; t++) | 2831 | for (t = 0; t < size_t - 1; t++) |
2845 | { | 2832 | { |
2846 | for (s = 0; s < size_s_out - 1; s++) | 2833 | for (s = 0; s < size_s_out - 1; s++) |
@@ -2859,8 +2846,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2859 | 2846 | ||
2860 | // Inner face | 2847 | // Inner face |
2861 | // Invert facing from outer face | 2848 | // Invert facing from outer face |
2862 | if ( count + (size_t - 1) * ((size_s - 1) - size_s_out) * 6 >= MAX_INDEX) | ||
2863 | goto noindices; | ||
2864 | for (t = 0; t < size_t - 1; t++) | 2849 | for (t = 0; t < size_t - 1; t++) |
2865 | { | 2850 | { |
2866 | for (s = size_s_out; s < size_s - 1; s++) | 2851 | for (s = size_s_out; s < size_s - 1; s++) |
@@ -2965,8 +2950,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2965 | 2950 | ||
2966 | if (use_tri1a2) | 2951 | if (use_tri1a2) |
2967 | { | 2952 | { |
2968 | if (count + 3 >= MAX_INDEX) | ||
2969 | goto noindices; | ||
2970 | index[count++] = pt1 + i; | 2953 | index[count++] = pt1 + i; |
2971 | index[count++] = pt1 + 1 + i; | 2954 | index[count++] = pt1 + 1 + i; |
2972 | index[count++] = pt2 + i; | 2955 | index[count++] = pt2 + i; |
@@ -2974,8 +2957,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
2974 | } | 2957 | } |
2975 | else | 2958 | else |
2976 | { | 2959 | { |
2977 | if (count + 3 >= MAX_INDEX) | ||
2978 | goto noindices; | ||
2979 | index[count++] = pt1 + i; | 2960 | index[count++] = pt1 + i; |
2980 | index[count++] = pt2 - 1 + i; | 2961 | index[count++] = pt2 - 1 + i; |
2981 | index[count++] = pt2 + i; | 2962 | index[count++] = pt2 + i; |
@@ -3066,8 +3047,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3066 | 3047 | ||
3067 | if (use_tri1a2) | 3048 | if (use_tri1a2) |
3068 | { | 3049 | { |
3069 | if (count + 3 >= MAX_INDEX) | ||
3070 | goto noindices; | ||
3071 | index[count++] = pt1; | 3050 | index[count++] = pt1; |
3072 | index[count++] = pt2; | 3051 | index[count++] = pt2; |
3073 | index[count++] = pt1 + 1; | 3052 | index[count++] = pt1 + 1; |
@@ -3075,8 +3054,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3075 | } | 3054 | } |
3076 | else | 3055 | else |
3077 | { | 3056 | { |
3078 | if (count + 3 >= MAX_INDEX) | ||
3079 | goto noindices; | ||
3080 | index[count++] = pt1; | 3057 | index[count++] = pt1; |
3081 | index[count++] = pt2; | 3058 | index[count++] = pt2; |
3082 | index[count++] = pt2 - 1; | 3059 | index[count++] = pt2 - 1; |
@@ -3088,8 +3065,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3088 | else | 3065 | else |
3089 | { | 3066 | { |
3090 | // Closed solid. Easy case. | 3067 | // Closed solid. Easy case. |
3091 | if ( (size_t - 1) * (size_s - 1) * 6 > MAX_INDEX) | ||
3092 | goto noindices; | ||
3093 | for (t = 0; t < size_t - 1; t++) | 3068 | for (t = 0; t < size_t - 1; t++) |
3094 | { | 3069 | { |
3095 | for (s = 0; s < size_s - 1; s++) | 3070 | for (s = 0; s < size_s - 1; s++) |
@@ -3111,8 +3086,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3111 | if (path_open) | 3086 | if (path_open) |
3112 | { | 3087 | { |
3113 | // bottom cap | 3088 | // bottom cap |
3114 | if ( count + (size_s - 2 - 1) * 3 >= MAX_INDEX) | ||
3115 | goto noindices; | ||
3116 | for (s = 1; s < size_s - 2; s++) | 3089 | for (s = 1; s < size_s - 2; s++) |
3117 | { | 3090 | { |
3118 | index[count++] = s+1; | 3091 | index[count++] = s+1; |
@@ -3122,8 +3095,6 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3122 | 3095 | ||
3123 | // top cap | 3096 | // top cap |
3124 | S32 offset = (size_t - 1)*size_s; | 3097 | S32 offset = (size_t - 1)*size_s; |
3125 | if ( count + (size_s - 2 - 1) * 3 >= MAX_INDEX) | ||
3126 | goto noindices; | ||
3127 | for (s = 1; s < size_s - 2; s++) | 3098 | for (s = 1; s < size_s - 2; s++) |
3128 | { | 3099 | { |
3129 | // Inverted ordering from bottom cap. | 3100 | // Inverted ordering from bottom cap. |
@@ -3134,7 +3105,18 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3134 | } | 3105 | } |
3135 | } | 3106 | } |
3136 | 3107 | ||
3108 | #ifdef LL_DEBUG | ||
3109 | // assert that we computed the correct number of indices | ||
3110 | if (count != expected_num_triangle_indices ) | ||
3111 | { | ||
3112 | llerrs << "bad index count prediciton:" | ||
3113 | << " expected=" << expected_num_triangle_indices | ||
3114 | << " actual=" << count << llendl; | ||
3115 | } | ||
3116 | #endif | ||
3117 | |||
3137 | #if 0 | 3118 | #if 0 |
3119 | // verify that each index does not point beyond the size of the mesh | ||
3138 | S32 num_vertices = mMesh.size(); | 3120 | S32 num_vertices = mMesh.size(); |
3139 | for (i = 0; i < count; i+=3) | 3121 | for (i = 0; i < count; i+=3) |
3140 | { | 3122 | { |
@@ -3145,17 +3127,65 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const | |||
3145 | } | 3127 | } |
3146 | #endif | 3128 | #endif |
3147 | 3129 | ||
3148 | indices = new S32[count]; | 3130 | num_indices = count; |
3149 | noindices: | 3131 | return index; |
3150 | if (!indices) | 3132 | } |
3133 | |||
3134 | S32 LLVolume::getNumTriangleIndices() const | ||
3135 | { | ||
3136 | BOOL profile_open = getProfile().isOpen(); | ||
3137 | BOOL hollow = getProfile().isHollow(); | ||
3138 | BOOL path_open = getPath().isOpen(); | ||
3139 | |||
3140 | S32 size_s, size_s_out, size_t; | ||
3141 | size_s = getProfile().getTotal(); | ||
3142 | size_s_out = getProfile().getTotalOut(); | ||
3143 | size_t = getPath().mPath.size(); | ||
3144 | |||
3145 | S32 count = 0; | ||
3146 | if (profile_open) /* Flawfinder: ignore */ | ||
3151 | { | 3147 | { |
3152 | llwarns << "Couldn't allocate triangle indices" << llendl; | 3148 | if (hollow) |
3153 | num_indices = 0; | 3149 | { |
3154 | return NULL; | 3150 | // Open hollow -- much like the closed solid, except we |
3151 | // we need to stitch up the gap between s=0 and s=size_s-1 | ||
3152 | count = (size_t - 1) * (((size_s -1) * 6) + 6); | ||
3153 | } | ||
3154 | else | ||
3155 | { | ||
3156 | count = (size_t - 1) * (((size_s -1) * 6) + 6); | ||
3157 | } | ||
3155 | } | 3158 | } |
3156 | num_indices = count; | 3159 | else if (hollow) |
3157 | memcpy(indices, index, count * sizeof(S32)); /* Flawfinder: ignore */ | 3160 | { |
3158 | return indices; | 3161 | // Closed hollow |
3162 | // Outer face | ||
3163 | count = (size_t - 1) * (size_s_out - 1) * 6; | ||
3164 | |||
3165 | // Inner face | ||
3166 | count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6; | ||
3167 | } | ||
3168 | else | ||
3169 | { | ||
3170 | // Closed solid. Easy case. | ||
3171 | count = (size_t - 1) * (size_s - 1) * 6; | ||
3172 | } | ||
3173 | |||
3174 | if (path_open) | ||
3175 | { | ||
3176 | S32 cap_triangle_count = size_s - 3; | ||
3177 | if ( profile_open | ||
3178 | || hollow ) | ||
3179 | { | ||
3180 | cap_triangle_count = size_s - 2; | ||
3181 | } | ||
3182 | if ( cap_triangle_count > 0 ) | ||
3183 | { | ||
3184 | // top and bottom caps | ||
3185 | count += cap_triangle_count * 2 * 3; | ||
3186 | } | ||
3187 | } | ||
3188 | return count; | ||
3159 | } | 3189 | } |
3160 | 3190 | ||
3161 | //----------------------------------------------------------------------------- | 3191 | //----------------------------------------------------------------------------- |
@@ -3486,7 +3516,7 @@ struct lessTriangle | |||
3486 | 3516 | ||
3487 | BOOL equalTriangle(const S32 *a, const S32 *b) | 3517 | BOOL equalTriangle(const S32 *a, const S32 *b) |
3488 | { | 3518 | { |
3489 | if ((*a == *b) && (*(a+1) == *(b+1)) && ((*a+2) == (*b+2))) | 3519 | if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) |
3490 | { | 3520 | { |
3491 | return TRUE; | 3521 | return TRUE; |
3492 | } | 3522 | } |
@@ -3502,6 +3532,21 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices, | |||
3502 | S32 &num_output_triangles, | 3532 | S32 &num_output_triangles, |
3503 | S32 **output_triangles) | 3533 | S32 **output_triangles) |
3504 | { | 3534 | { |
3535 | /* Testing: avoid any cleanup | ||
3536 | num_output_vertices = num_input_vertices; | ||
3537 | num_output_triangles = num_input_triangles; | ||
3538 | |||
3539 | *output_vertices = new LLVector3[num_input_vertices]; | ||
3540 | for (S32 i = 0; i < num_input_vertices; i++) | ||
3541 | { | ||
3542 | (*output_vertices)[i] = input_vertices[i].mPos; | ||
3543 | } | ||
3544 | |||
3545 | *output_triangles = new S32[num_input_triangles*3]; | ||
3546 | memcpy(*output_triangles, input_triangles, 3*num_input_triangles*sizeof(S32)); // Flawfinder: ignore | ||
3547 | return TRUE; | ||
3548 | */ | ||
3549 | |||
3505 | // Here's how we do this: | 3550 | // Here's how we do this: |
3506 | // Create a structure which contains the original vertex index and the | 3551 | // Create a structure which contains the original vertex index and the |
3507 | // LLVector3 data. | 3552 | // LLVector3 data. |
@@ -3552,7 +3597,7 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices, | |||
3552 | } | 3597 | } |
3553 | else | 3598 | else |
3554 | { | 3599 | { |
3555 | //llinfos << "Removed duplicate vertex " << pairp->mVertex << llendl; | 3600 | //llinfos << "Removed duplicate vertex " << pairp->mVertex << ", distance magVecSquared() is " << (pairp->mVertex - prev_pairp->mVertex).magVecSquared() << llendl; |
3556 | } | 3601 | } |
3557 | vertex_mapping[pairp->mIndex] = new_num_vertices - 1; | 3602 | vertex_mapping[pairp->mIndex] = new_num_vertices - 1; |
3558 | } | 3603 | } |
@@ -3564,50 +3609,54 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices, | |||
3564 | 3609 | ||
3565 | for (i = 0; i < num_input_triangles; i++) | 3610 | for (i = 0; i < num_input_triangles; i++) |
3566 | { | 3611 | { |
3567 | //llinfos << "Checking triangle " << input_triangles[i*3] << ":" << input_triangles[i*3+1] << ":" << input_triangles[i*3+2] << llendl; | 3612 | S32 v1 = i*3; |
3568 | input_triangles[i*3] = vertex_mapping[input_triangles[i*3]]; | 3613 | S32 v2 = i*3 + 1; |
3569 | input_triangles[i*3+1] = vertex_mapping[input_triangles[i*3+1]]; | 3614 | S32 v3 = i*3 + 2; |
3570 | input_triangles[i*3+2] = vertex_mapping[input_triangles[i*3+2]]; | 3615 | |
3616 | //llinfos << "Checking triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl; | ||
3617 | input_triangles[v1] = vertex_mapping[input_triangles[v1]]; | ||
3618 | input_triangles[v2] = vertex_mapping[input_triangles[v2]]; | ||
3619 | input_triangles[v3] = vertex_mapping[input_triangles[v3]]; | ||
3571 | 3620 | ||
3572 | if ((input_triangles[i*3] == input_triangles[i*3+1]) | 3621 | if ((input_triangles[v1] == input_triangles[v2]) |
3573 | || (input_triangles[i*3] == input_triangles[i*3+2]) | 3622 | || (input_triangles[v1] == input_triangles[v3]) |
3574 | || (input_triangles[i*3+1] == input_triangles[i*3+2])) | 3623 | || (input_triangles[v2] == input_triangles[v3])) |
3575 | { | 3624 | { |
3576 | //llinfos << "Removing degenerate triangle " << input_triangles[i*3] << ":" << input_triangles[i*3+1] << ":" << input_triangles[i*3+2] << llendl; | 3625 | //llinfos << "Removing degenerate triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl; |
3577 | // Degenerate triangle, skip | 3626 | // Degenerate triangle, skip |
3578 | continue; | 3627 | continue; |
3579 | } | 3628 | } |
3580 | 3629 | ||
3581 | if (input_triangles[i*3] < input_triangles[i*3+1]) | 3630 | if (input_triangles[v1] < input_triangles[v2]) |
3582 | { | 3631 | { |
3583 | if (input_triangles[i*3] < input_triangles[i*3+2]) | 3632 | if (input_triangles[v1] < input_triangles[v3]) |
3584 | { | 3633 | { |
3585 | // (0 < 1) && (0 < 2) | 3634 | // (0 < 1) && (0 < 2) |
3586 | new_triangles[new_num_triangles*3] = input_triangles[i*3]; | 3635 | new_triangles[new_num_triangles*3] = input_triangles[v1]; |
3587 | new_triangles[new_num_triangles*3+1] = input_triangles[i*3+1]; | 3636 | new_triangles[new_num_triangles*3+1] = input_triangles[v2]; |
3588 | new_triangles[new_num_triangles*3+2] = input_triangles[i*3+2]; | 3637 | new_triangles[new_num_triangles*3+2] = input_triangles[v3]; |
3589 | } | 3638 | } |
3590 | else | 3639 | else |
3591 | { | 3640 | { |
3592 | // (0 < 1) && (2 < 0) | 3641 | // (0 < 1) && (2 < 0) |
3593 | new_triangles[new_num_triangles*3] = input_triangles[i*3+2]; | 3642 | new_triangles[new_num_triangles*3] = input_triangles[v3]; |
3594 | new_triangles[new_num_triangles*3+1] = input_triangles[i*3]; | 3643 | new_triangles[new_num_triangles*3+1] = input_triangles[v1]; |
3595 | new_triangles[new_num_triangles*3+2] = input_triangles[i*3+1]; | 3644 | new_triangles[new_num_triangles*3+2] = input_triangles[v2]; |
3596 | } | 3645 | } |
3597 | } | 3646 | } |
3598 | else if (input_triangles[i*3+1] < input_triangles[i*3+2]) | 3647 | else if (input_triangles[v2] < input_triangles[v3]) |
3599 | { | 3648 | { |
3600 | // (1 < 0) && (1 < 2) | 3649 | // (1 < 0) && (1 < 2) |
3601 | new_triangles[new_num_triangles*3] = input_triangles[i*3+1]; | 3650 | new_triangles[new_num_triangles*3] = input_triangles[v2]; |
3602 | new_triangles[new_num_triangles*3+1] = input_triangles[i*3+2]; | 3651 | new_triangles[new_num_triangles*3+1] = input_triangles[v3]; |
3603 | new_triangles[new_num_triangles*3+2] = input_triangles[i*3]; | 3652 | new_triangles[new_num_triangles*3+2] = input_triangles[v1]; |
3604 | } | 3653 | } |
3605 | else | 3654 | else |
3606 | { | 3655 | { |
3607 | // (1 < 0) && (2 < 1) | 3656 | // (1 < 0) && (2 < 1) |
3608 | new_triangles[new_num_triangles*3] = input_triangles[i*3+2]; | 3657 | new_triangles[new_num_triangles*3] = input_triangles[v3]; |
3609 | new_triangles[new_num_triangles*3+1] = input_triangles[i*3]; | 3658 | new_triangles[new_num_triangles*3+1] = input_triangles[v1]; |
3610 | new_triangles[new_num_triangles*3+2] = input_triangles[i*3+1]; | 3659 | new_triangles[new_num_triangles*3+2] = input_triangles[v2]; |
3611 | } | 3660 | } |
3612 | new_num_triangles++; | 3661 | new_num_triangles++; |
3613 | } | 3662 | } |
@@ -3848,23 +3897,44 @@ void LLVolumeParams::reduceT(F32 begin, F32 end) | |||
3848 | mPathParams.setEnd(a + end * (b - a)); | 3897 | mPathParams.setEnd(a + end * (b - a)); |
3849 | } | 3898 | } |
3850 | 3899 | ||
3900 | const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity | ||
3901 | const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity | ||
3902 | |||
3903 | // returns TRUE if the shape can be approximated with a convex shape | ||
3904 | // for collison purposes | ||
3851 | BOOL LLVolumeParams::isConvex() const | 3905 | BOOL LLVolumeParams::isConvex() const |
3852 | { | 3906 | { |
3853 | // The logic for determining convexity is a little convoluted. | 3907 | F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); |
3854 | 3908 | ||
3855 | // Do we need to take getTwistBegin into account? DK 08/12/04 | 3909 | if ( mPathParams.getTwist() != mPathParams.getTwistBegin() |
3856 | if ( mProfileParams.getHollow() != 0.0f | 3910 | && path_length > MIN_CONCAVE_PATH_WEDGE ) |
3857 | || mPathParams.getTwist() != mPathParams.getTwistBegin() ) | ||
3858 | { | 3911 | { |
3859 | // hollow or twist gaurantees concavity | 3912 | // twist along a "not too short" path is concave |
3860 | return FALSE; | 3913 | return FALSE; |
3861 | } | 3914 | } |
3862 | 3915 | ||
3863 | F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); | 3916 | F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); |
3864 | BOOL concave_profile = (profile_length < 1.0f) && (profile_length > 0.5f); | 3917 | F32 hollow = mProfileParams.getHollow(); |
3865 | if (concave_profile) | 3918 | BOOL same_hole = hollow == 0.f |
3919 | || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; | ||
3920 | |||
3921 | F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; | ||
3922 | U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; | ||
3923 | if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) | ||
3866 | { | 3924 | { |
3867 | // concave profile | 3925 | // it is a sphere and spheres get twice the minimum profile wedge |
3926 | min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; | ||
3927 | } | ||
3928 | |||
3929 | BOOL convex_profile = ( ( profile_length == 1.f | ||
3930 | || profile_length <= 0.5f ) | ||
3931 | && hollow == 0.f ) // trivially convex | ||
3932 | || ( profile_length <= min_profile_wedge | ||
3933 | && same_hole ); // effectvely convex (even when hollow) | ||
3934 | |||
3935 | if (!convex_profile) | ||
3936 | { | ||
3937 | // profile is concave | ||
3868 | return FALSE; | 3938 | return FALSE; |
3869 | } | 3939 | } |
3870 | 3940 | ||
@@ -3875,7 +3945,6 @@ BOOL LLVolumeParams::isConvex() const | |||
3875 | return TRUE; | 3945 | return TRUE; |
3876 | } | 3946 | } |
3877 | 3947 | ||
3878 | F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); | ||
3879 | BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f); | 3948 | BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f); |
3880 | if (concave_path) | 3949 | if (concave_path) |
3881 | { | 3950 | { |
@@ -3883,17 +3952,43 @@ BOOL LLVolumeParams::isConvex() const | |||
3883 | } | 3952 | } |
3884 | 3953 | ||
3885 | // we're left with spheres, toroids and tubes | 3954 | // we're left with spheres, toroids and tubes |
3886 | // only the spheres can be convex | ||
3887 | U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; | ||
3888 | if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) | 3955 | if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) |
3889 | { | 3956 | { |
3957 | // at this stage all spheres must be convex | ||
3890 | return TRUE; | 3958 | return TRUE; |
3891 | } | 3959 | } |
3892 | 3960 | ||
3893 | // it's a toroid or tube | 3961 | // it's a toroid or tube |
3962 | if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) | ||
3963 | { | ||
3964 | // effectively convex | ||
3965 | return TRUE; | ||
3966 | } | ||
3967 | |||
3894 | return FALSE; | 3968 | return FALSE; |
3895 | } | 3969 | } |
3896 | 3970 | ||
3971 | // debug | ||
3972 | void LLVolumeParams::setCube() | ||
3973 | { | ||
3974 | mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); | ||
3975 | mProfileParams.setBegin(0.f); | ||
3976 | mProfileParams.setEnd(1.f); | ||
3977 | mProfileParams.setHollow(0.f); | ||
3978 | |||
3979 | mPathParams.setBegin(0.f); | ||
3980 | mPathParams.setEnd(1.f); | ||
3981 | mPathParams.setScale(1.f, 1.f); | ||
3982 | mPathParams.setShear(0.f, 0.f); | ||
3983 | mPathParams.setCurveType(LL_PCODE_PATH_LINE); | ||
3984 | mPathParams.setTwistBegin(0.f); | ||
3985 | mPathParams.setTwistEnd(0.f); | ||
3986 | mPathParams.setRadiusOffset(0.f); | ||
3987 | mPathParams.setTaper(0.f, 0.f); | ||
3988 | mPathParams.setRevolutions(0.f); | ||
3989 | mPathParams.setSkew(0.f); | ||
3990 | } | ||
3991 | |||
3897 | LLFaceID LLVolume::generateFaceMask() | 3992 | LLFaceID LLVolume::generateFaceMask() |
3898 | { | 3993 | { |
3899 | LLFaceID new_mask = 0x0000; | 3994 | LLFaceID new_mask = 0x0000; |
diff --git a/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h index 5ec7997..9dbea7a 100644 --- a/linden/indra/llmath/llvolume.h +++ b/linden/indra/llmath/llvolume.h | |||
@@ -72,6 +72,8 @@ const F32 TAPER_QUANTA = 0.01f; | |||
72 | const F32 REV_QUANTA = 0.015f; | 72 | const F32 REV_QUANTA = 0.015f; |
73 | const F32 HOLLOW_QUANTA = 0.00002f; | 73 | const F32 HOLLOW_QUANTA = 0.00002f; |
74 | 74 | ||
75 | const S32 MAX_VOLUME_TRIANGLE_INDICES = 10000; | ||
76 | |||
75 | //============================================================================ | 77 | //============================================================================ |
76 | 78 | ||
77 | // useful masks | 79 | // useful masks |
@@ -187,10 +189,10 @@ class LLProfileParams | |||
187 | public: | 189 | public: |
188 | LLProfileParams() | 190 | LLProfileParams() |
189 | { | 191 | { |
190 | mBegin = 0; | ||
191 | mEnd = 1; | ||
192 | mHollow = 0; | ||
193 | mCurveType = LL_PCODE_PROFILE_SQUARE; | 192 | mCurveType = LL_PCODE_PROFILE_SQUARE; |
193 | mBegin = 0.f; | ||
194 | mEnd = 1.f; | ||
195 | mHollow = 0.f; | ||
194 | } | 196 | } |
195 | 197 | ||
196 | LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) | 198 | LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) |
@@ -307,17 +309,17 @@ class LLPathParams | |||
307 | public: | 309 | public: |
308 | LLPathParams() | 310 | LLPathParams() |
309 | { | 311 | { |
310 | mBegin = 0; | 312 | mBegin = 0.f; |
311 | mEnd = 1; | 313 | mEnd = 1.f; |
312 | mScale.setVec(1,1); | 314 | mScale.setVec(1.f,1.f); |
313 | mShear.setVec(0,0); | 315 | mShear.setVec(0.f,0.f); |
314 | mCurveType = LL_PCODE_PATH_LINE; | 316 | mCurveType = LL_PCODE_PATH_LINE; |
315 | mTwistBegin = 0; | 317 | mTwistBegin = 0.f; |
316 | mTwistEnd = 0; | 318 | mTwistEnd = 0.f; |
317 | mRadiusOffset = 0; | 319 | mRadiusOffset = 0.f; |
318 | mTaper.setVec(0,0); | 320 | mTaper.setVec(0.f,0.f); |
319 | mRevolutions = 1; | 321 | mRevolutions = 1.f; |
320 | mSkew = 0; | 322 | mSkew = 0.f; |
321 | } | 323 | } |
322 | 324 | ||
323 | LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew) | 325 | LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew) |
@@ -627,6 +629,9 @@ public: | |||
627 | 629 | ||
628 | friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); | 630 | friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); |
629 | 631 | ||
632 | // debug helper functions | ||
633 | void setCube(); | ||
634 | |||
630 | protected: | 635 | protected: |
631 | LLProfileParams mProfileParams; | 636 | LLProfileParams mProfileParams; |
632 | LLPathParams mPathParams; | 637 | LLPathParams mPathParams; |
@@ -869,6 +874,10 @@ public: | |||
869 | S32 getSculptLevel() const { return mSculptLevel; } | 874 | S32 getSculptLevel() const { return mSculptLevel; } |
870 | 875 | ||
871 | S32 *getTriangleIndices(U32 &num_indices) const; | 876 | S32 *getTriangleIndices(U32 &num_indices) const; |
877 | |||
878 | // returns number of triangle indeces required for path/profile mesh | ||
879 | S32 getNumTriangleIndices() const; | ||
880 | |||
872 | void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec, | 881 | void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec, |
873 | const LLMatrix4& mat, | 882 | const LLMatrix4& mat, |
874 | const LLMatrix3& norm_mat); | 883 | const LLMatrix3& norm_mat); |
diff --git a/linden/indra/llmath/llvolumemgr.cpp b/linden/indra/llmath/llvolumemgr.cpp index db99959..d9bca70 100644 --- a/linden/indra/llmath/llvolumemgr.cpp +++ b/linden/indra/llmath/llvolumemgr.cpp | |||
@@ -36,7 +36,7 @@ | |||
36 | 36 | ||
37 | //#define DEBUG_VOLUME | 37 | //#define DEBUG_VOLUME |
38 | 38 | ||
39 | LLVolumeMgr* gVolumeMgr = 0; | 39 | //LLVolumeMgr* gVolumeMgr = 0; |
40 | 40 | ||
41 | const F32 BASE_THRESHOLD = 0.03f; | 41 | const F32 BASE_THRESHOLD = 0.03f; |
42 | 42 | ||
@@ -49,37 +49,23 @@ F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD, | |||
49 | //static | 49 | //static |
50 | F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; | 50 | F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; |
51 | 51 | ||
52 | //============================================================================ | ||
53 | //static | ||
54 | void LLVolumeMgr::initClass() | ||
55 | { | ||
56 | gVolumeMgr = new LLVolumeMgr(); | ||
57 | } | ||
58 | |||
59 | //static | ||
60 | BOOL LLVolumeMgr::cleanupClass() | ||
61 | { | ||
62 | BOOL res = FALSE; | ||
63 | if (gVolumeMgr) { | ||
64 | res = gVolumeMgr->cleanup(); | ||
65 | delete gVolumeMgr; | ||
66 | gVolumeMgr = 0; | ||
67 | } | ||
68 | return res; | ||
69 | } | ||
70 | 52 | ||
71 | //============================================================================ | 53 | //============================================================================ |
72 | 54 | ||
73 | LLVolumeMgr::LLVolumeMgr() | 55 | LLVolumeMgr::LLVolumeMgr() |
56 | : mDataMutex(NULL) | ||
74 | { | 57 | { |
75 | mDataMutex = new LLMutex(gAPRPoolp); | 58 | // the LLMutex magic interferes with easy unit testing, |
76 | // mNumVolumes = 0; | 59 | // so you now must manually call useMutex() to use it |
60 | //mDataMutex = new LLMutex(gAPRPoolp); | ||
77 | } | 61 | } |
78 | 62 | ||
79 | LLVolumeMgr::~LLVolumeMgr() | 63 | LLVolumeMgr::~LLVolumeMgr() |
80 | { | 64 | { |
81 | cleanup(); | 65 | cleanup(); |
66 | |||
82 | delete mDataMutex; | 67 | delete mDataMutex; |
68 | mDataMutex = NULL; | ||
83 | } | 69 | } |
84 | 70 | ||
85 | BOOL LLVolumeMgr::cleanup() | 71 | BOOL LLVolumeMgr::cleanup() |
@@ -90,7 +76,10 @@ BOOL LLVolumeMgr::cleanup() | |||
90 | } | 76 | } |
91 | #endif | 77 | #endif |
92 | BOOL no_refs = TRUE; | 78 | BOOL no_refs = TRUE; |
93 | mDataMutex->lock(); | 79 | if (mDataMutex) |
80 | { | ||
81 | mDataMutex->lock(); | ||
82 | } | ||
94 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), | 83 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), |
95 | end = mVolumeLODGroups.end(); | 84 | end = mVolumeLODGroups.end(); |
96 | iter != end; iter++) | 85 | iter != end; iter++) |
@@ -106,29 +95,37 @@ BOOL LLVolumeMgr::cleanup() | |||
106 | volgroupp->unref();// this ); | 95 | volgroupp->unref();// this ); |
107 | } | 96 | } |
108 | mVolumeLODGroups.clear(); | 97 | mVolumeLODGroups.clear(); |
109 | mDataMutex->unlock(); | 98 | if (mDataMutex) |
99 | { | ||
100 | mDataMutex->unlock(); | ||
101 | } | ||
110 | return no_refs; | 102 | return no_refs; |
111 | } | 103 | } |
112 | 104 | ||
105 | // whatever calls getVolume() never owns the LLVolume* and | ||
106 | // cannot keep references for long since it may be deleted | ||
107 | // later. For best results hold it in an LLPointer<LLVolume>. | ||
113 | LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail) | 108 | LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail) |
114 | { | 109 | { |
115 | LLVolumeLODGroup* volgroupp; | 110 | LLVolumeLODGroup* volgroupp; |
116 | mDataMutex->lock(); | 111 | if (mDataMutex) |
112 | { | ||
113 | mDataMutex->lock(); | ||
114 | } | ||
117 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); | 115 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(&volume_params); |
118 | if( iter == mVolumeLODGroups.end() ) | 116 | if( iter == mVolumeLODGroups.end() ) |
119 | { | 117 | { |
120 | volgroupp = new LLVolumeLODGroup(volume_params); | 118 | volgroupp = createNewGroup(volume_params); |
121 | const LLVolumeParams* params = &(volgroupp->getParams()); | ||
122 | mVolumeLODGroups[params] = volgroupp; | ||
123 | volgroupp->ref(); // initial reference | ||
124 | } | 119 | } |
125 | else | 120 | else |
126 | { | 121 | { |
127 | volgroupp = iter->second; | 122 | volgroupp = iter->second; |
128 | } | 123 | } |
129 | volgroupp->ref();// this ); | 124 | volgroupp->ref(); |
130 | mDataMutex->unlock(); | 125 | if (mDataMutex) |
131 | // mNumVolumes++; | 126 | { |
127 | mDataMutex->unlock(); | ||
128 | } | ||
132 | #ifdef DEBUG_VOLUME | 129 | #ifdef DEBUG_VOLUME |
133 | { | 130 | { |
134 | lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl; | 131 | lldebugs << "LLVolumeMgr::getVolume() " << (*this) << llendl; |
@@ -137,6 +134,27 @@ LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 | |||
137 | return volgroupp->getLOD(detail); | 134 | return volgroupp->getLOD(detail); |
138 | } | 135 | } |
139 | 136 | ||
137 | // virtual | ||
138 | LLVolumeLODGroup* LLVolumeMgr::getGroup( const LLVolumeParams& volume_params ) const | ||
139 | { | ||
140 | LLVolumeLODGroup* volgroupp = NULL; | ||
141 | if (mDataMutex) | ||
142 | { | ||
143 | mDataMutex->lock(); | ||
144 | } | ||
145 | volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.find(&volume_params); | ||
146 | if( iter != mVolumeLODGroups.end() ) | ||
147 | { | ||
148 | volgroupp = iter->second; | ||
149 | } | ||
150 | if (mDataMutex) | ||
151 | { | ||
152 | mDataMutex->unlock(); | ||
153 | } | ||
154 | return volgroupp; | ||
155 | } | ||
156 | |||
157 | // virtual | ||
140 | void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | 158 | void LLVolumeMgr::cleanupVolume(LLVolume *volumep) |
141 | { | 159 | { |
142 | if (volumep->isUnique()) | 160 | if (volumep->isUnique()) |
@@ -145,12 +163,18 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | |||
145 | return; | 163 | return; |
146 | } | 164 | } |
147 | LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams()); | 165 | LLVolumeParams* params = (LLVolumeParams*) &(volumep->getParams()); |
148 | mDataMutex->lock(); | 166 | if (mDataMutex) |
167 | { | ||
168 | mDataMutex->lock(); | ||
169 | } | ||
149 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); | 170 | volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); |
150 | if( iter == mVolumeLODGroups.end() ) | 171 | if( iter == mVolumeLODGroups.end() ) |
151 | { | 172 | { |
152 | llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; | 173 | llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; |
153 | mDataMutex->unlock(); | 174 | if (mDataMutex) |
175 | { | ||
176 | mDataMutex->unlock(); | ||
177 | } | ||
154 | return; | 178 | return; |
155 | } | 179 | } |
156 | else | 180 | else |
@@ -164,9 +188,11 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | |||
164 | mVolumeLODGroups.erase(params); | 188 | mVolumeLODGroups.erase(params); |
165 | volgroupp->unref();// this ); | 189 | volgroupp->unref();// this ); |
166 | } | 190 | } |
167 | // mNumVolumes--; | ||
168 | } | 191 | } |
169 | mDataMutex->unlock(); | 192 | if (mDataMutex) |
193 | { | ||
194 | mDataMutex->unlock(); | ||
195 | } | ||
170 | 196 | ||
171 | #ifdef DEBUG_VOLUME | 197 | #ifdef DEBUG_VOLUME |
172 | { | 198 | { |
@@ -175,10 +201,43 @@ void LLVolumeMgr::cleanupVolume(LLVolume *volumep) | |||
175 | #endif | 201 | #endif |
176 | } | 202 | } |
177 | 203 | ||
204 | #ifdef DEBUG_VOLUME | ||
205 | S32 LLVolumeMgr::getTotalRefCount() const | ||
206 | { | ||
207 | S32 total_ref_count = 0; | ||
208 | for ( volume_lod_group_map_t::const_iterator iter = mVolumeLODGroups.begin(), | ||
209 | end = mVolumeLODGroups.end(); | ||
210 | iter != end; iter++) | ||
211 | { | ||
212 | total_ref_count += iter->second->getTotalVolumeRefCount(); | ||
213 | } | ||
214 | return total_ref_count; | ||
215 | } | ||
216 | |||
217 | S32 LLVolumeMgr::getGroupCount() const | ||
218 | { | ||
219 | return mVolumeLODGroups.size(); | ||
220 | } | ||
221 | #endif | ||
222 | |||
223 | // protected | ||
224 | LLVolumeLODGroup* LLVolumeMgr::createNewGroup(const LLVolumeParams& volume_params) | ||
225 | { | ||
226 | LLVolumeLODGroup* group = new LLVolumeLODGroup(volume_params); | ||
227 | const LLVolumeParams* params = &(group->getParams()); | ||
228 | mVolumeLODGroups[params] = group; | ||
229 | group->ref(); // initial reference | ||
230 | return group; | ||
231 | } | ||
232 | |||
233 | // virtual | ||
178 | void LLVolumeMgr::dump() | 234 | void LLVolumeMgr::dump() |
179 | { | 235 | { |
180 | F32 avg = 0.f; | 236 | F32 avg = 0.f; |
181 | mDataMutex->lock(); | 237 | if (mDataMutex) |
238 | { | ||
239 | mDataMutex->lock(); | ||
240 | } | ||
182 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), | 241 | for (volume_lod_group_map_t::iterator iter = mVolumeLODGroups.begin(), |
183 | end = mVolumeLODGroups.end(); | 242 | end = mVolumeLODGroups.end(); |
184 | iter != end; iter++) | 243 | iter != end; iter++) |
@@ -188,16 +247,30 @@ void LLVolumeMgr::dump() | |||
188 | } | 247 | } |
189 | int count = (int)mVolumeLODGroups.size(); | 248 | int count = (int)mVolumeLODGroups.size(); |
190 | avg = count ? avg / (F32)count : 0.0f; | 249 | avg = count ? avg / (F32)count : 0.0f; |
191 | mDataMutex->unlock(); | 250 | if (mDataMutex) |
251 | { | ||
252 | mDataMutex->unlock(); | ||
253 | } | ||
192 | llinfos << "Average usage of LODs " << avg << llendl; | 254 | llinfos << "Average usage of LODs " << avg << llendl; |
193 | } | 255 | } |
194 | 256 | ||
257 | void LLVolumeMgr::useMutex() | ||
258 | { | ||
259 | if (!mDataMutex) | ||
260 | { | ||
261 | mDataMutex = new LLMutex(gAPRPoolp); | ||
262 | } | ||
263 | } | ||
264 | |||
195 | std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) | 265 | std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) |
196 | { | 266 | { |
197 | s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; | 267 | s << "{ numLODgroups=" << volume_mgr.mVolumeLODGroups.size() << ", "; |
198 | 268 | ||
199 | S32 total_refs = 0; | 269 | S32 total_refs = 0; |
200 | volume_mgr.mDataMutex->lock(); | 270 | if (volume_mgr.mDataMutex) |
271 | { | ||
272 | volume_mgr.mDataMutex->lock(); | ||
273 | } | ||
201 | 274 | ||
202 | LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin(); | 275 | LLVolumeMgr::volume_lod_group_map_iter iter = volume_mgr.mVolumeLODGroups.begin(); |
203 | LLVolumeMgr::volume_lod_group_map_iter end = volume_mgr.mVolumeLODGroups.end(); | 276 | LLVolumeMgr::volume_lod_group_map_iter end = volume_mgr.mVolumeLODGroups.end(); |
@@ -208,7 +281,10 @@ std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) | |||
208 | s << ", " << (*volgroupp); | 281 | s << ", " << (*volgroupp); |
209 | } | 282 | } |
210 | 283 | ||
211 | volume_mgr.mDataMutex->unlock(); | 284 | if (volume_mgr.mDataMutex) |
285 | { | ||
286 | volume_mgr.mDataMutex->unlock(); | ||
287 | } | ||
212 | 288 | ||
213 | s << ", total_refs=" << total_refs << " }"; | 289 | s << ", total_refs=" << total_refs << " }"; |
214 | return s; | 290 | return s; |
@@ -222,15 +298,39 @@ LLVolumeLODGroup::LLVolumeLODGroup(const LLVolumeParams ¶ms) | |||
222 | for (i = 0; i < NUM_LODS; i++) | 298 | for (i = 0; i < NUM_LODS; i++) |
223 | { | 299 | { |
224 | mLODRefs[i] = 0; | 300 | mLODRefs[i] = 0; |
225 | mVolumeLODs[i] = NULL; | 301 | // no need to initialize mVolumeLODs, they are smart pointers |
302 | //mVolumeLODs[i] = NULL; | ||
226 | mAccessCount[i] = 0; | 303 | mAccessCount[i] = 0; |
227 | } | 304 | } |
228 | } | 305 | } |
229 | 306 | ||
307 | #ifdef DEBUG_VOLUME | ||
308 | S32 LLVolumeLODGroup::getTotalVolumeRefCount() const | ||
309 | { | ||
310 | S32 total_ref_count = 0; | ||
311 | for (S32 i = 0; i < NUM_LODS; i++) | ||
312 | { | ||
313 | total_ref_count += mLODRefs[i]; | ||
314 | } | ||
315 | return total_ref_count; | ||
316 | } | ||
317 | #endif | ||
318 | |||
319 | // protected | ||
230 | LLVolumeLODGroup::~LLVolumeLODGroup() | 320 | LLVolumeLODGroup::~LLVolumeLODGroup() |
231 | { | 321 | { |
322 | destroy(); | ||
232 | } | 323 | } |
233 | 324 | ||
325 | // protected | ||
326 | void LLVolumeLODGroup::destroy() | ||
327 | { | ||
328 | for (S32 i = 0; i < NUM_LODS; i++) | ||
329 | { | ||
330 | // remember that mVolumeLODs are smart pointers! | ||
331 | mVolumeLODs[i] = NULL; | ||
332 | } | ||
333 | } | ||
234 | 334 | ||
235 | LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) | 335 | LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) |
236 | { | 336 | { |
@@ -242,7 +342,7 @@ LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) | |||
242 | mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]); | 342 | mVolumeLODs[detail] = new LLVolume(mParams, mDetailScales[detail]); |
243 | } | 343 | } |
244 | mLODRefs[detail]++; | 344 | mLODRefs[detail]++; |
245 | return mVolumeLODs[detail]; | 345 | return mVolumeLODs[detail].get(); |
246 | } | 346 | } |
247 | 347 | ||
248 | BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) | 348 | BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) |
diff --git a/linden/indra/llmath/llvolumemgr.h b/linden/indra/llmath/llvolumemgr.h index 889bc56..0a2249e 100644 --- a/linden/indra/llmath/llvolumemgr.h +++ b/linden/indra/llmath/llvolumemgr.h | |||
@@ -43,9 +43,6 @@ class LLVolumeLODGroup; | |||
43 | 43 | ||
44 | class LLVolumeLODGroup : public LLThreadSafeRefCount | 44 | class LLVolumeLODGroup : public LLThreadSafeRefCount |
45 | { | 45 | { |
46 | protected: | ||
47 | ~LLVolumeLODGroup(); | ||
48 | |||
49 | public: | 46 | public: |
50 | enum | 47 | enum |
51 | { | 48 | { |
@@ -60,11 +57,19 @@ public: | |||
60 | static F32 getVolumeScaleFromDetail(const S32 detail); | 57 | static F32 getVolumeScaleFromDetail(const S32 detail); |
61 | 58 | ||
62 | LLVolume *getLOD(const S32 detail); | 59 | LLVolume *getLOD(const S32 detail); |
63 | const LLVolumeParams &getParams() const { return mParams; }; | 60 | const LLVolumeParams& getParams() const { return mParams; }; |
64 | 61 | ||
65 | F32 dump(); | 62 | F32 dump(); |
66 | friend std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup); | 63 | friend std::ostream& operator<<(std::ostream& s, const LLVolumeLODGroup& volgroup); |
67 | 64 | ||
65 | #ifdef DEBUG_VOLUME | ||
66 | S32 getTotalVolumeRefCount() const; | ||
67 | #endif | ||
68 | |||
69 | protected: | ||
70 | virtual ~LLVolumeLODGroup(); | ||
71 | void destroy(); | ||
72 | |||
68 | protected: | 73 | protected: |
69 | LLVolumeParams mParams; | 74 | LLVolumeParams mParams; |
70 | 75 | ||
@@ -77,30 +82,50 @@ protected: | |||
77 | 82 | ||
78 | class LLVolumeMgr | 83 | class LLVolumeMgr |
79 | { | 84 | { |
80 | public: | 85 | //public: |
81 | static void initClass(); | 86 | // static void initClass(); |
82 | static BOOL cleanupClass(); | 87 | // static BOOL cleanupClass(); |
83 | 88 | ||
84 | public: | 89 | public: |
85 | LLVolumeMgr(); | 90 | LLVolumeMgr(); |
86 | ~LLVolumeMgr(); | 91 | virtual ~LLVolumeMgr(); |
87 | BOOL cleanup(); // Cleanup all volumes being managed, returns TRUE if no dangling references | 92 | BOOL cleanup(); // Cleanup all volumes being managed, returns TRUE if no dangling references |
93 | |||
94 | virtual LLVolumeLODGroup* getGroup( const LLVolumeParams& volume_params ) const; | ||
95 | |||
96 | // whatever calls getVolume() never owns the LLVolume* and | ||
97 | // cannot keep references for long since it may be deleted | ||
98 | // later. For best results hold it in an LLPointer<LLVolume>. | ||
88 | LLVolume *getVolume(const LLVolumeParams &volume_params, const S32 detail); | 99 | LLVolume *getVolume(const LLVolumeParams &volume_params, const S32 detail); |
100 | |||
89 | void cleanupVolume(LLVolume *volumep); | 101 | void cleanupVolume(LLVolume *volumep); |
90 | 102 | ||
91 | void dump(); | 103 | void dump(); |
104 | |||
105 | // manually call this for mutex magic | ||
106 | void useMutex(); | ||
107 | |||
108 | #ifdef DEBUG_VOLUME | ||
109 | S32 getTotalRefCount() const; | ||
110 | S32 getGroupCount() const; | ||
111 | #endif | ||
92 | friend std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr); | 112 | friend std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr); |
93 | 113 | ||
94 | protected: | 114 | protected: |
115 | virtual LLVolumeLODGroup* createNewGroup(const LLVolumeParams& volume_params); | ||
116 | |||
117 | protected: | ||
95 | typedef std::map<const LLVolumeParams*, LLVolumeLODGroup*, LLVolumeParams::compare> volume_lod_group_map_t; | 118 | typedef std::map<const LLVolumeParams*, LLVolumeLODGroup*, LLVolumeParams::compare> volume_lod_group_map_t; |
96 | typedef volume_lod_group_map_t::const_iterator volume_lod_group_map_iter; | 119 | typedef volume_lod_group_map_t::const_iterator volume_lod_group_map_iter; |
97 | volume_lod_group_map_t mVolumeLODGroups; | 120 | volume_lod_group_map_t mVolumeLODGroups; |
98 | 121 | ||
99 | LLMutex* mDataMutex; | 122 | LLMutex* mDataMutex; |
100 | 123 | ||
101 | // S32 mNumVolumes; | 124 | // We need to be able to disable threadsafe checks to prevent |
125 | // some unit_tests from blocking on failure | ||
126 | bool mThreadSafe; | ||
102 | }; | 127 | }; |
103 | 128 | ||
104 | extern LLVolumeMgr* gVolumeMgr; | 129 | //extern LLVolumeMgr* gVolumeMgr; |
105 | 130 | ||
106 | #endif // LL_LLVOLUMEMGR_H | 131 | #endif // LL_LLVOLUMEMGR_H |
diff --git a/linden/indra/llmath/m3math.cpp b/linden/indra/llmath/m3math.cpp index 6741f05..5c3eb08 100644 --- a/linden/indra/llmath/m3math.cpp +++ b/linden/indra/llmath/m3math.cpp | |||
@@ -136,7 +136,7 @@ void LLMatrix3::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const | |||
136 | 136 | ||
137 | // Clear and Assignment Functions | 137 | // Clear and Assignment Functions |
138 | 138 | ||
139 | const LLMatrix3& LLMatrix3::identity() | 139 | const LLMatrix3& LLMatrix3::setIdentity() |
140 | { | 140 | { |
141 | mMatrix[0][0] = 1.f; | 141 | mMatrix[0][0] = 1.f; |
142 | mMatrix[0][1] = 0.f; | 142 | mMatrix[0][1] = 0.f; |
@@ -152,7 +152,23 @@ const LLMatrix3& LLMatrix3::identity() | |||
152 | return (*this); | 152 | return (*this); |
153 | } | 153 | } |
154 | 154 | ||
155 | const LLMatrix3& LLMatrix3::zero() | 155 | const LLMatrix3& LLMatrix3::clear() |
156 | { | ||
157 | mMatrix[0][0] = 0.f; | ||
158 | mMatrix[0][1] = 0.f; | ||
159 | mMatrix[0][2] = 0.f; | ||
160 | |||
161 | mMatrix[1][0] = 0.f; | ||
162 | mMatrix[1][1] = 0.f; | ||
163 | mMatrix[1][2] = 0.f; | ||
164 | |||
165 | mMatrix[2][0] = 0.f; | ||
166 | mMatrix[2][1] = 0.f; | ||
167 | mMatrix[2][2] = 0.f; | ||
168 | return (*this); | ||
169 | } | ||
170 | |||
171 | const LLMatrix3& LLMatrix3::setZero() | ||
156 | { | 172 | { |
157 | mMatrix[0][0] = 0.f; | 173 | mMatrix[0][0] = 0.f; |
158 | mMatrix[0][1] = 0.f; | 174 | mMatrix[0][1] = 0.f; |
@@ -190,15 +206,26 @@ F32 LLMatrix3::determinant() const | |||
190 | mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]); | 206 | mMatrix[0][2] * (mMatrix[1][0] * mMatrix[2][1] - mMatrix[1][1] * mMatrix[2][0]); |
191 | } | 207 | } |
192 | 208 | ||
193 | // This is identical to the transMat3() method because we assume a rotation matrix | 209 | // inverts this matrix |
194 | const LLMatrix3& LLMatrix3::invert() | 210 | void LLMatrix3::invert() |
195 | { | 211 | { |
196 | // transpose the matrix | 212 | // fails silently if determinant is zero too small |
197 | F32 temp; | 213 | F32 det = determinant(); |
198 | temp = mMatrix[VX][VY]; mMatrix[VX][VY] = mMatrix[VY][VX]; mMatrix[VY][VX] = temp; | 214 | const F32 VERY_SMALL_DETERMINANT = 0.000001f; |
199 | temp = mMatrix[VX][VZ]; mMatrix[VX][VZ] = mMatrix[VZ][VX]; mMatrix[VZ][VX] = temp; | 215 | if (fabs(det) > VERY_SMALL_DETERMINANT) |
200 | temp = mMatrix[VY][VZ]; mMatrix[VY][VZ] = mMatrix[VZ][VY]; mMatrix[VZ][VY] = temp; | 216 | { |
201 | return *this; | 217 | // invertiable |
218 | LLMatrix3 t(*this); | ||
219 | mMatrix[VX][VX] = ( t.mMatrix[VY][VY] * t.mMatrix[VZ][VZ] - t.mMatrix[VY][VZ] * t.mMatrix[VZ][VY] ) / det; | ||
220 | mMatrix[VY][VX] = ( t.mMatrix[VY][VZ] * t.mMatrix[VZ][VX] - t.mMatrix[VY][VX] * t.mMatrix[VZ][VZ] ) / det; | ||
221 | mMatrix[VZ][VX] = ( t.mMatrix[VY][VX] * t.mMatrix[VZ][VY] - t.mMatrix[VY][VY] * t.mMatrix[VZ][VX] ) / det; | ||
222 | mMatrix[VX][VY] = ( t.mMatrix[VZ][VY] * t.mMatrix[VX][VZ] - t.mMatrix[VZ][VZ] * t.mMatrix[VX][VY] ) / det; | ||
223 | mMatrix[VY][VY] = ( t.mMatrix[VZ][VZ] * t.mMatrix[VX][VX] - t.mMatrix[VZ][VX] * t.mMatrix[VX][VZ] ) / det; | ||
224 | mMatrix[VZ][VY] = ( t.mMatrix[VZ][VX] * t.mMatrix[VX][VY] - t.mMatrix[VZ][VY] * t.mMatrix[VX][VX] ) / det; | ||
225 | mMatrix[VX][VZ] = ( t.mMatrix[VX][VY] * t.mMatrix[VY][VZ] - t.mMatrix[VX][VZ] * t.mMatrix[VY][VY] ) / det; | ||
226 | mMatrix[VY][VZ] = ( t.mMatrix[VX][VZ] * t.mMatrix[VY][VX] - t.mMatrix[VX][VX] * t.mMatrix[VY][VZ] ) / det; | ||
227 | mMatrix[VZ][VZ] = ( t.mMatrix[VX][VX] * t.mMatrix[VY][VY] - t.mMatrix[VX][VY] * t.mMatrix[VY][VX] ) / det; | ||
228 | } | ||
202 | } | 229 | } |
203 | 230 | ||
204 | // does not assume a rotation matrix, and does not divide by determinant, assuming results will be renormalized | 231 | // does not assume a rotation matrix, and does not divide by determinant, assuming results will be renormalized |
@@ -351,6 +378,27 @@ const LLMatrix3& LLMatrix3::setRows(const LLVector3 &fwd, const LLVector3 &left, | |||
351 | return *this; | 378 | return *this; |
352 | } | 379 | } |
353 | 380 | ||
381 | const LLMatrix3& LLMatrix3::setRow( U32 rowIndex, const LLVector3& row ) | ||
382 | { | ||
383 | llassert( rowIndex >= 0 && rowIndex < NUM_VALUES_IN_MAT3 ); | ||
384 | |||
385 | mMatrix[rowIndex][0] = row[0]; | ||
386 | mMatrix[rowIndex][1] = row[1]; | ||
387 | mMatrix[rowIndex][2] = row[2]; | ||
388 | |||
389 | return *this; | ||
390 | } | ||
391 | |||
392 | const LLMatrix3& LLMatrix3::setCol( U32 colIndex, const LLVector3& col ) | ||
393 | { | ||
394 | llassert( colIndex >= 0 && colIndex < NUM_VALUES_IN_MAT3 ); | ||
395 | |||
396 | mMatrix[0][colIndex] = col[0]; | ||
397 | mMatrix[1][colIndex] = col[1]; | ||
398 | mMatrix[2][colIndex] = col[2]; | ||
399 | |||
400 | return *this; | ||
401 | } | ||
354 | 402 | ||
355 | // Rotate exisitng mMatrix | 403 | // Rotate exisitng mMatrix |
356 | const LLMatrix3& LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z) | 404 | const LLMatrix3& LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z) |
@@ -384,6 +432,16 @@ const LLMatrix3& LLMatrix3::rotate(const LLQuaternion &q) | |||
384 | return *this; | 432 | return *this; |
385 | } | 433 | } |
386 | 434 | ||
435 | void LLMatrix3::add(const LLMatrix3& other_matrix) | ||
436 | { | ||
437 | for (S32 i = 0; i < 3; ++i) | ||
438 | { | ||
439 | for (S32 j = 0; j < 3; ++j) | ||
440 | { | ||
441 | mMatrix[i][j] += other_matrix.mMatrix[i][j]; | ||
442 | } | ||
443 | } | ||
444 | } | ||
387 | 445 | ||
388 | LLVector3 LLMatrix3::getFwdRow() const | 446 | LLVector3 LLMatrix3::getFwdRow() const |
389 | { | 447 | { |
@@ -536,6 +594,19 @@ const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b) | |||
536 | return a; | 594 | return a; |
537 | } | 595 | } |
538 | 596 | ||
597 | const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar ) | ||
598 | { | ||
599 | for( U32 i = 0; i < NUM_VALUES_IN_MAT3; ++i ) | ||
600 | { | ||
601 | for( U32 j = 0; j < NUM_VALUES_IN_MAT3; ++j ) | ||
602 | { | ||
603 | a.mMatrix[i][j] *= scalar; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | return a; | ||
608 | } | ||
609 | |||
539 | std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) | 610 | std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) |
540 | { | 611 | { |
541 | s << "{ " | 612 | s << "{ " |
diff --git a/linden/indra/llmath/m3math.h b/linden/indra/llmath/m3math.h index 8bd94d8..cd22a86 100644 --- a/linden/indra/llmath/m3math.h +++ b/linden/indra/llmath/m3math.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define LL_M3MATH_H | 33 | #define LL_M3MATH_H |
34 | 34 | ||
35 | #include "llerror.h" | 35 | #include "llerror.h" |
36 | #include "stdtypes.h" | ||
36 | 37 | ||
37 | class LLVector4; | 38 | class LLVector4; |
38 | class LLVector3; | 39 | class LLVector3; |
@@ -76,8 +77,9 @@ class LLMatrix3 | |||
76 | // | 77 | // |
77 | 78 | ||
78 | // various useful matrix functions | 79 | // various useful matrix functions |
79 | const LLMatrix3& identity(); // Load identity matrix | 80 | const LLMatrix3& setIdentity(); // Load identity matrix |
80 | const LLMatrix3& zero(); // Clears Matrix to zero | 81 | const LLMatrix3& clear(); // Clears Matrix to zero |
82 | const LLMatrix3& setZero(); // Clears Matrix to zero | ||
81 | 83 | ||
82 | /////////////////////////// | 84 | /////////////////////////// |
83 | // | 85 | // |
@@ -91,6 +93,9 @@ class LLMatrix3 | |||
91 | const LLMatrix3& setRot(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos | 93 | const LLMatrix3& setRot(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos |
92 | 94 | ||
93 | const LLMatrix3& setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis); | 95 | const LLMatrix3& setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis); |
96 | const LLMatrix3& setRow( U32 rowIndex, const LLVector3& row ); | ||
97 | const LLMatrix3& setCol( U32 colIndex, const LLVector3& col ); | ||
98 | |||
94 | 99 | ||
95 | /////////////////////////// | 100 | /////////////////////////// |
96 | // | 101 | // |
@@ -103,29 +108,31 @@ class LLMatrix3 | |||
103 | LLVector3 getFwdRow() const; | 108 | LLVector3 getFwdRow() const; |
104 | LLVector3 getLeftRow() const; | 109 | LLVector3 getLeftRow() const; |
105 | LLVector3 getUpRow() const; | 110 | LLVector3 getUpRow() const; |
106 | F32 determinant() const; // Return determinant | 111 | F32 determinant() const; // Return determinant |
107 | 112 | ||
108 | 113 | ||
109 | /////////////////////////// | 114 | /////////////////////////// |
110 | // | 115 | // |
111 | // Operations on an existing matrix | 116 | // Operations on an existing matrix |
112 | // | 117 | // |
113 | const LLMatrix3& transpose(); // Transpose MAT4 | 118 | const LLMatrix3& transpose(); // Transpose MAT4 |
114 | const LLMatrix3& invert(); // Invert MAT4 | 119 | const LLMatrix3& orthogonalize(); // Orthogonalizes X, then Y, then Z |
115 | const LLMatrix3& orthogonalize(); // Orthogonalizes X, then Y, then Z | 120 | void invert(); // Invert MAT4 |
116 | const LLMatrix3& adjointTranspose(); // returns transpose of matrix adjoint, for multiplying normals | 121 | const LLMatrix3& adjointTranspose();// returns transpose of matrix adjoint, for multiplying normals |
117 | 122 | ||
118 | 123 | ||
119 | // Rotate existing matrix | 124 | // Rotate existing matrix |
120 | // Note: the two lines below are equivalent: | 125 | // Note: the two lines below are equivalent: |
121 | // foo.rotate(bar) | 126 | // foo.rotate(bar) |
122 | // foo = foo * bar | 127 | // foo = foo * bar |
123 | // That is, foo.rotMat3(bar) multiplies foo by bar FROM THE RIGHT | 128 | // That is, foo.rotate(bar) multiplies foo by bar FROM THE RIGHT |
124 | const LLMatrix3& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); // Rotate matrix by rotating angle radians about (x, y, z) | 129 | const LLMatrix3& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); // Rotate matrix by rotating angle radians about (x, y, z) |
125 | const LLMatrix3& rotate(const F32 angle, const LLVector3 &vec); // Rotate matrix by rotating angle radians about vec | 130 | const LLMatrix3& rotate(const F32 angle, const LLVector3 &vec); // Rotate matrix by rotating angle radians about vec |
126 | const LLMatrix3& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by roll (about x), pitch (about y), and yaw (about z) | 131 | const LLMatrix3& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by roll (about x), pitch (about y), and yaw (about z) |
127 | const LLMatrix3& rotate(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos | 132 | const LLMatrix3& rotate(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos |
128 | 133 | ||
134 | void add(const LLMatrix3& other_matrix); // add other_matrix to this one | ||
135 | |||
129 | // This operator is misleading as to operation direction | 136 | // This operator is misleading as to operation direction |
130 | // friend LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b); // Apply rotation a to vector b | 137 | // friend LLVector3 operator*(const LLMatrix3 &a, const LLVector3 &b); // Apply rotation a to vector b |
131 | 138 | ||
@@ -137,6 +144,7 @@ class LLMatrix3 | |||
137 | friend bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b); // Return a != b | 144 | friend bool operator!=(const LLMatrix3 &a, const LLMatrix3 &b); // Return a != b |
138 | 145 | ||
139 | friend const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b); // Return a * b | 146 | friend const LLMatrix3& operator*=(LLMatrix3 &a, const LLMatrix3 &b); // Return a * b |
147 | friend const LLMatrix3& operator*=(LLMatrix3 &a, F32 scalar ); // Return a * scalar | ||
140 | 148 | ||
141 | friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a | 149 | friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a |
142 | }; | 150 | }; |
diff --git a/linden/indra/llmath/m4math.cpp b/linden/indra/llmath/m4math.cpp index 2b51db1..f2db478 100644 --- a/linden/indra/llmath/m4math.cpp +++ b/linden/indra/llmath/m4math.cpp | |||
@@ -163,7 +163,7 @@ LLMatrix4::~LLMatrix4(void) | |||
163 | 163 | ||
164 | // Clear and Assignment Functions | 164 | // Clear and Assignment Functions |
165 | 165 | ||
166 | const LLMatrix4& LLMatrix4::zero() | 166 | const LLMatrix4& LLMatrix4::setZero() |
167 | { | 167 | { |
168 | mMatrix[0][0] = 0.f; | 168 | mMatrix[0][0] = 0.f; |
169 | mMatrix[0][1] = 0.f; | 169 | mMatrix[0][1] = 0.f; |
diff --git a/linden/indra/llmath/m4math.h b/linden/indra/llmath/m4math.h index 7a51eb2..27eb865 100644 --- a/linden/indra/llmath/m4math.h +++ b/linden/indra/llmath/m4math.h | |||
@@ -132,8 +132,8 @@ public: | |||
132 | const LLVector4 &row3); | 132 | const LLVector4 &row3); |
133 | 133 | ||
134 | // various useful matrix functions | 134 | // various useful matrix functions |
135 | const LLMatrix4& identity(); // Load identity matrix | 135 | const LLMatrix4& setIdentity(); // Load identity matrix |
136 | const LLMatrix4& zero(); // Clears matrix to all zeros. | 136 | const LLMatrix4& setZero(); // Clears matrix to all zeros. |
137 | 137 | ||
138 | const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix by rotating angle radians about (x, y, z) | 138 | const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix by rotating angle radians about (x, y, z) |
139 | const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis); // Calculate rotation matrix for rotating angle radians about vec | 139 | const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis); // Calculate rotation matrix for rotating angle radians about vec |
@@ -243,10 +243,10 @@ public: | |||
243 | 243 | ||
244 | inline LLMatrix4::LLMatrix4() | 244 | inline LLMatrix4::LLMatrix4() |
245 | { | 245 | { |
246 | identity(); | 246 | setIdentity(); |
247 | } | 247 | } |
248 | 248 | ||
249 | inline const LLMatrix4& LLMatrix4::identity() | 249 | inline const LLMatrix4& LLMatrix4::setIdentity() |
250 | { | 250 | { |
251 | mMatrix[0][0] = 1.f; | 251 | mMatrix[0][0] = 1.f; |
252 | mMatrix[0][1] = 0.f; | 252 | mMatrix[0][1] = 0.f; |
diff --git a/linden/indra/llmath/v2math.h b/linden/indra/llmath/v2math.h index b951786..5a520d2 100644 --- a/linden/indra/llmath/v2math.h +++ b/linden/indra/llmath/v2math.h | |||
@@ -54,18 +54,26 @@ class LLVector2 | |||
54 | LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) | 54 | LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1]) |
55 | 55 | ||
56 | // Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec. | 56 | // Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec. |
57 | void clearVec(); | 57 | void clear(); |
58 | void setZero(); | ||
59 | void clearVec(); // deprecated | ||
60 | void zeroVec(); // deprecated | ||
58 | 61 | ||
59 | // Zero LLVector2 to (0, 0) | 62 | void set(F32 x, F32 y); // Sets LLVector2 to (x, y) |
60 | void zeroVec(); | 63 | void set(const LLVector2 &vec); // Sets LLVector2 to vec |
64 | void set(const F32 *vec); // Sets LLVector2 to vec | ||
61 | 65 | ||
62 | void setVec(F32 x, F32 y); // Sets LLVector2 to (x, y) | 66 | void setVec(F32 x, F32 y); // deprecated |
63 | void setVec(const LLVector2 &vec); // Sets LLVector2 to vec | 67 | void setVec(const LLVector2 &vec); // deprecated |
64 | void setVec(const F32 *vec); // Sets LLVector2 to vec | 68 | void setVec(const F32 *vec); // deprecated |
65 | 69 | ||
66 | F32 magVec() const; // Returns magnitude of LLVector2 | 70 | F32 length() const; // Returns magnitude of LLVector2 |
67 | F32 magVecSquared() const; // Returns magnitude squared of LLVector2 | 71 | F32 lengthSquared() const; // Returns magnitude squared of LLVector2 |
68 | F32 normVec(); // Normalizes and returns the magnitude of LLVector2 | 72 | F32 normalize(); // Normalizes and returns the magnitude of LLVector2 |
73 | |||
74 | F32 magVec() const; // deprecated | ||
75 | F32 magVecSquared() const; // deprecated | ||
76 | F32 normVec(); // deprecated | ||
69 | 77 | ||
70 | BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed | 78 | BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed |
71 | 79 | ||
@@ -132,30 +140,66 @@ inline LLVector2::LLVector2(const F32 *vec) | |||
132 | 140 | ||
133 | // Clear and Assignment Functions | 141 | // Clear and Assignment Functions |
134 | 142 | ||
143 | inline void LLVector2::clear(void) | ||
144 | { | ||
145 | mV[VX] = 0.f; | ||
146 | mV[VY] = 0.f; | ||
147 | } | ||
148 | |||
149 | inline void LLVector2::setZero(void) | ||
150 | { | ||
151 | mV[VX] = 0.f; | ||
152 | mV[VY] = 0.f; | ||
153 | } | ||
154 | |||
155 | // deprecated | ||
135 | inline void LLVector2::clearVec(void) | 156 | inline void LLVector2::clearVec(void) |
136 | { | 157 | { |
137 | mV[VX] = 0.f; | 158 | mV[VX] = 0.f; |
138 | mV[VY] = 0.f; | 159 | mV[VY] = 0.f; |
139 | } | 160 | } |
140 | 161 | ||
162 | // deprecated | ||
141 | inline void LLVector2::zeroVec(void) | 163 | inline void LLVector2::zeroVec(void) |
142 | { | 164 | { |
143 | mV[VX] = 0.f; | 165 | mV[VX] = 0.f; |
144 | mV[VY] = 0.f; | 166 | mV[VY] = 0.f; |
145 | } | 167 | } |
146 | 168 | ||
169 | inline void LLVector2::set(F32 x, F32 y) | ||
170 | { | ||
171 | mV[VX] = x; | ||
172 | mV[VY] = y; | ||
173 | } | ||
174 | |||
175 | inline void LLVector2::set(const LLVector2 &vec) | ||
176 | { | ||
177 | mV[VX] = vec.mV[VX]; | ||
178 | mV[VY] = vec.mV[VY]; | ||
179 | } | ||
180 | |||
181 | inline void LLVector2::set(const F32 *vec) | ||
182 | { | ||
183 | mV[VX] = vec[VX]; | ||
184 | mV[VY] = vec[VY]; | ||
185 | } | ||
186 | |||
187 | |||
188 | // deprecated | ||
147 | inline void LLVector2::setVec(F32 x, F32 y) | 189 | inline void LLVector2::setVec(F32 x, F32 y) |
148 | { | 190 | { |
149 | mV[VX] = x; | 191 | mV[VX] = x; |
150 | mV[VY] = y; | 192 | mV[VY] = y; |
151 | } | 193 | } |
152 | 194 | ||
195 | // deprecated | ||
153 | inline void LLVector2::setVec(const LLVector2 &vec) | 196 | inline void LLVector2::setVec(const LLVector2 &vec) |
154 | { | 197 | { |
155 | mV[VX] = vec.mV[VX]; | 198 | mV[VX] = vec.mV[VX]; |
156 | mV[VY] = vec.mV[VY]; | 199 | mV[VY] = vec.mV[VY]; |
157 | } | 200 | } |
158 | 201 | ||
202 | // deprecated | ||
159 | inline void LLVector2::setVec(const F32 *vec) | 203 | inline void LLVector2::setVec(const F32 *vec) |
160 | { | 204 | { |
161 | mV[VX] = vec[VX]; | 205 | mV[VX] = vec[VX]; |
@@ -164,16 +208,49 @@ inline void LLVector2::setVec(const F32 *vec) | |||
164 | 208 | ||
165 | // LLVector2 Magnitude and Normalization Functions | 209 | // LLVector2 Magnitude and Normalization Functions |
166 | 210 | ||
211 | inline F32 LLVector2::length(void) const | ||
212 | { | ||
213 | return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); | ||
214 | } | ||
215 | |||
216 | inline F32 LLVector2::lengthSquared(void) const | ||
217 | { | ||
218 | return mV[0]*mV[0] + mV[1]*mV[1]; | ||
219 | } | ||
220 | |||
221 | inline F32 LLVector2::normalize(void) | ||
222 | { | ||
223 | F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); | ||
224 | F32 oomag; | ||
225 | |||
226 | if (mag > FP_MAG_THRESHOLD) | ||
227 | { | ||
228 | oomag = 1.f/mag; | ||
229 | mV[0] *= oomag; | ||
230 | mV[1] *= oomag; | ||
231 | } | ||
232 | else | ||
233 | { | ||
234 | mV[0] = 0.f; | ||
235 | mV[1] = 0.f; | ||
236 | mag = 0; | ||
237 | } | ||
238 | return (mag); | ||
239 | } | ||
240 | |||
241 | // deprecated | ||
167 | inline F32 LLVector2::magVec(void) const | 242 | inline F32 LLVector2::magVec(void) const |
168 | { | 243 | { |
169 | return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); | 244 | return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); |
170 | } | 245 | } |
171 | 246 | ||
247 | // deprecated | ||
172 | inline F32 LLVector2::magVecSquared(void) const | 248 | inline F32 LLVector2::magVecSquared(void) const |
173 | { | 249 | { |
174 | return mV[0]*mV[0] + mV[1]*mV[1]; | 250 | return mV[0]*mV[0] + mV[1]*mV[1]; |
175 | } | 251 | } |
176 | 252 | ||
253 | // deprecated | ||
177 | inline F32 LLVector2::normVec(void) | 254 | inline F32 LLVector2::normVec(void) |
178 | { | 255 | { |
179 | F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); | 256 | F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); |
diff --git a/linden/indra/llmath/v3dmath.h b/linden/indra/llmath/v3dmath.h index 60757ba..9bd80b8 100644 --- a/linden/indra/llmath/v3dmath.h +++ b/linden/indra/llmath/v3dmath.h | |||
@@ -83,8 +83,9 @@ class LLVector3d | |||
83 | BOOL clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns TRUE if data changed | 83 | BOOL clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns TRUE if data changed |
84 | BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed | 84 | BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed |
85 | 85 | ||
86 | inline const LLVector3d& clearVec(); // Clears LLVector3d to (0, 0, 0, 1) | 86 | inline const LLVector3d& clearVec(); // Clears LLVector3d to (0, 0, 0, 1) |
87 | inline const LLVector3d& zeroVec(); // Zero LLVector3d to (0, 0, 0, 0) | 87 | inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0) |
88 | inline const LLVector3d& zeroVec(); // deprecated | ||
88 | inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1) | 89 | inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1) |
89 | inline const LLVector3d& setVec(const LLVector3d &vec); // Sets LLVector3d to vec | 90 | inline const LLVector3d& setVec(const LLVector3d &vec); // Sets LLVector3d to vec |
90 | inline const LLVector3d& setVec(const F64 *vec); // Sets LLVector3d to vec | 91 | inline const LLVector3d& setVec(const F64 *vec); // Sets LLVector3d to vec |
@@ -198,6 +199,14 @@ inline const LLVector3d& LLVector3d::clearVec(void) | |||
198 | return (*this); | 199 | return (*this); |
199 | } | 200 | } |
200 | 201 | ||
202 | inline const LLVector3d& LLVector3d::setZero(void) | ||
203 | { | ||
204 | mdV[0] = 0.f; | ||
205 | mdV[1] = 0.f; | ||
206 | mdV[2] = 0.f; | ||
207 | return (*this); | ||
208 | } | ||
209 | |||
201 | inline const LLVector3d& LLVector3d::zeroVec(void) | 210 | inline const LLVector3d& LLVector3d::zeroVec(void) |
202 | { | 211 | { |
203 | mdV[0] = 0.f; | 212 | mdV[0] = 0.f; |
diff --git a/linden/indra/llmath/v3math.cpp b/linden/indra/llmath/v3math.cpp index 34cce06..bbe460f 100644 --- a/linden/indra/llmath/v3math.cpp +++ b/linden/indra/llmath/v3math.cpp | |||
@@ -172,6 +172,22 @@ LLVector3 LLVector3::scaledVec(const LLVector3& vec) const | |||
172 | return ret; | 172 | return ret; |
173 | } | 173 | } |
174 | 174 | ||
175 | const LLVector3& LLVector3::set(const LLVector3d &vec) | ||
176 | { | ||
177 | mV[0] = (F32)vec.mdV[0]; | ||
178 | mV[1] = (F32)vec.mdV[1]; | ||
179 | mV[2] = (F32)vec.mdV[2]; | ||
180 | return (*this); | ||
181 | } | ||
182 | |||
183 | const LLVector3& LLVector3::set(const LLVector4 &vec) | ||
184 | { | ||
185 | mV[0] = vec.mV[0]; | ||
186 | mV[1] = vec.mV[1]; | ||
187 | mV[2] = vec.mV[2]; | ||
188 | return (*this); | ||
189 | } | ||
190 | |||
175 | const LLVector3& LLVector3::setVec(const LLVector3d &vec) | 191 | const LLVector3& LLVector3::setVec(const LLVector3d &vec) |
176 | { | 192 | { |
177 | mV[0] = (F32)vec.mdV[0]; | 193 | mV[0] = (F32)vec.mdV[0]; |
diff --git a/linden/indra/llmath/v3math.h b/linden/indra/llmath/v3math.h index f1c1b39..ddb5e1f 100644 --- a/linden/indra/llmath/v3math.h +++ b/linden/indra/llmath/v3math.h | |||
@@ -81,18 +81,33 @@ class LLVector3 | |||
81 | 81 | ||
82 | BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed | 82 | BOOL abs(); // sets all values to absolute value of original value (first octant), returns TRUE if changed |
83 | 83 | ||
84 | inline void clearVec(); // Clears LLVector3 to (0, 0, 0, 1) | 84 | inline void clear(); // Clears LLVector3 to (0, 0, 0) |
85 | inline void zeroVec(); // Zero LLVector3 to (0, 0, 0, 0) | 85 | inline void setZero(); // Clears LLVector3 to (0, 0, 0) |
86 | inline void setVec(F32 x, F32 y, F32 z); // Sets LLVector3 to (x, y, z, 1) | 86 | inline void clearVec(); // deprecated |
87 | inline void setVec(const LLVector3 &vec); // Sets LLVector3 to vec | 87 | inline void zeroVec(); // deprecated |
88 | inline void setVec(const F32 *vec); // Sets LLVector3 to vec | ||
89 | 88 | ||
90 | const LLVector3& setVec(const LLVector4 &vec); | 89 | inline void set(F32 x, F32 y, F32 z); // Sets LLVector3 to (x, y, z, 1) |
91 | const LLVector3& setVec(const LLVector3d &vec); // Sets LLVector3 to vec | 90 | inline void set(const LLVector3 &vec); // Sets LLVector3 to vec |
91 | inline void set(const F32 *vec); // Sets LLVector3 to vec | ||
92 | const LLVector3& set(const LLVector4 &vec); | ||
93 | const LLVector3& set(const LLVector3d &vec);// Sets LLVector3 to vec | ||
92 | 94 | ||
93 | F32 magVec() const; // Returns magnitude of LLVector3 | 95 | inline void setVec(F32 x, F32 y, F32 z); // deprecated |
94 | F32 magVecSquared() const; // Returns magnitude squared of LLVector3 | 96 | inline void setVec(const LLVector3 &vec); // deprecated |
95 | inline F32 normVec(); // Normalizes and returns the magnitude of LLVector3 | 97 | inline void setVec(const F32 *vec); // deprecated |
98 | |||
99 | const LLVector3& setVec(const LLVector4 &vec); // deprecated | ||
100 | const LLVector3& setVec(const LLVector3d &vec); // deprecated | ||
101 | |||
102 | F32 length() const; // Returns magnitude of LLVector3 | ||
103 | F32 lengthSquared() const; // Returns magnitude squared of LLVector3 | ||
104 | F32 magVec() const; // deprecated | ||
105 | F32 magVecSquared() const; // deprecated | ||
106 | |||
107 | inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3 | ||
108 | inline F32 normVec(); // deprecated | ||
109 | |||
110 | inline BOOL inRange( F32 min, F32 max ) const; // Returns true if all values of the vector are between min and max | ||
96 | 111 | ||
97 | const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians | 112 | const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians |
98 | const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians | 113 | const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians |
@@ -188,6 +203,20 @@ inline BOOL LLVector3::isFinite() const | |||
188 | 203 | ||
189 | // Clear and Assignment Functions | 204 | // Clear and Assignment Functions |
190 | 205 | ||
206 | inline void LLVector3::clear(void) | ||
207 | { | ||
208 | mV[0] = 0.f; | ||
209 | mV[1] = 0.f; | ||
210 | mV[2] = 0.f; | ||
211 | } | ||
212 | |||
213 | inline void LLVector3::setZero(void) | ||
214 | { | ||
215 | mV[0] = 0.f; | ||
216 | mV[1] = 0.f; | ||
217 | mV[2] = 0.f; | ||
218 | } | ||
219 | |||
191 | inline void LLVector3::clearVec(void) | 220 | inline void LLVector3::clearVec(void) |
192 | { | 221 | { |
193 | mV[0] = 0.f; | 222 | mV[0] = 0.f; |
@@ -202,6 +231,28 @@ inline void LLVector3::zeroVec(void) | |||
202 | mV[2] = 0.f; | 231 | mV[2] = 0.f; |
203 | } | 232 | } |
204 | 233 | ||
234 | inline void LLVector3::set(F32 x, F32 y, F32 z) | ||
235 | { | ||
236 | mV[VX] = x; | ||
237 | mV[VY] = y; | ||
238 | mV[VZ] = z; | ||
239 | } | ||
240 | |||
241 | inline void LLVector3::set(const LLVector3 &vec) | ||
242 | { | ||
243 | mV[0] = vec.mV[0]; | ||
244 | mV[1] = vec.mV[1]; | ||
245 | mV[2] = vec.mV[2]; | ||
246 | } | ||
247 | |||
248 | inline void LLVector3::set(const F32 *vec) | ||
249 | { | ||
250 | mV[0] = vec[0]; | ||
251 | mV[1] = vec[1]; | ||
252 | mV[2] = vec[2]; | ||
253 | } | ||
254 | |||
255 | // deprecated | ||
205 | inline void LLVector3::setVec(F32 x, F32 y, F32 z) | 256 | inline void LLVector3::setVec(F32 x, F32 y, F32 z) |
206 | { | 257 | { |
207 | mV[VX] = x; | 258 | mV[VX] = x; |
@@ -209,6 +260,7 @@ inline void LLVector3::setVec(F32 x, F32 y, F32 z) | |||
209 | mV[VZ] = z; | 260 | mV[VZ] = z; |
210 | } | 261 | } |
211 | 262 | ||
263 | // deprecated | ||
212 | inline void LLVector3::setVec(const LLVector3 &vec) | 264 | inline void LLVector3::setVec(const LLVector3 &vec) |
213 | { | 265 | { |
214 | mV[0] = vec.mV[0]; | 266 | mV[0] = vec.mV[0]; |
@@ -216,6 +268,7 @@ inline void LLVector3::setVec(const LLVector3 &vec) | |||
216 | mV[2] = vec.mV[2]; | 268 | mV[2] = vec.mV[2]; |
217 | } | 269 | } |
218 | 270 | ||
271 | // deprecated | ||
219 | inline void LLVector3::setVec(const F32 *vec) | 272 | inline void LLVector3::setVec(const F32 *vec) |
220 | { | 273 | { |
221 | mV[0] = vec[0]; | 274 | mV[0] = vec[0]; |
@@ -223,6 +276,29 @@ inline void LLVector3::setVec(const F32 *vec) | |||
223 | mV[2] = vec[2]; | 276 | mV[2] = vec[2]; |
224 | } | 277 | } |
225 | 278 | ||
279 | inline F32 LLVector3::normalize(void) | ||
280 | { | ||
281 | F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); | ||
282 | F32 oomag; | ||
283 | |||
284 | if (mag > FP_MAG_THRESHOLD) | ||
285 | { | ||
286 | oomag = 1.f/mag; | ||
287 | mV[0] *= oomag; | ||
288 | mV[1] *= oomag; | ||
289 | mV[2] *= oomag; | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | mV[0] = 0.f; | ||
294 | mV[1] = 0.f; | ||
295 | mV[2] = 0.f; | ||
296 | mag = 0; | ||
297 | } | ||
298 | return (mag); | ||
299 | } | ||
300 | |||
301 | // deprecated | ||
226 | inline F32 LLVector3::normVec(void) | 302 | inline F32 LLVector3::normVec(void) |
227 | { | 303 | { |
228 | F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); | 304 | F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); |
@@ -247,6 +323,16 @@ inline F32 LLVector3::normVec(void) | |||
247 | 323 | ||
248 | // LLVector3 Magnitude and Normalization Functions | 324 | // LLVector3 Magnitude and Normalization Functions |
249 | 325 | ||
326 | inline F32 LLVector3::length(void) const | ||
327 | { | ||
328 | return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); | ||
329 | } | ||
330 | |||
331 | inline F32 LLVector3::lengthSquared(void) const | ||
332 | { | ||
333 | return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; | ||
334 | } | ||
335 | |||
250 | inline F32 LLVector3::magVec(void) const | 336 | inline F32 LLVector3::magVec(void) const |
251 | { | 337 | { |
252 | return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); | 338 | return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); |
@@ -257,6 +343,13 @@ inline F32 LLVector3::magVecSquared(void) const | |||
257 | return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; | 343 | return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]; |
258 | } | 344 | } |
259 | 345 | ||
346 | inline BOOL LLVector3::inRange( F32 min, F32 max ) const | ||
347 | { | ||
348 | return mV[0] >= min && mV[0] <= max && | ||
349 | mV[1] >= min && mV[1] <= max && | ||
350 | mV[2] >= min && mV[2] <= max; | ||
351 | } | ||
352 | |||
260 | inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b) | 353 | inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b) |
261 | { | 354 | { |
262 | LLVector3 c(a); | 355 | LLVector3 c(a); |
@@ -397,7 +490,7 @@ inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b) | |||
397 | inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b) | 490 | inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b) |
398 | { | 491 | { |
399 | LLVector3 project_axis = b; | 492 | LLVector3 project_axis = b; |
400 | project_axis.normVec(); | 493 | project_axis.normalize(); |
401 | return project_axis * (a * project_axis); | 494 | return project_axis * (a * project_axis); |
402 | } | 495 | } |
403 | 496 | ||
@@ -438,8 +531,8 @@ inline F32 angle_between(const LLVector3& a, const LLVector3& b) | |||
438 | { | 531 | { |
439 | LLVector3 an = a; | 532 | LLVector3 an = a; |
440 | LLVector3 bn = b; | 533 | LLVector3 bn = b; |
441 | an.normVec(); | 534 | an.normalize(); |
442 | bn.normVec(); | 535 | bn.normalize(); |
443 | F32 cosine = an * bn; | 536 | F32 cosine = an * bn; |
444 | F32 angle = (cosine >= 1.0f) ? 0.0f : | 537 | F32 angle = (cosine >= 1.0f) ? 0.0f : |
445 | (cosine <= -1.0f) ? F_PI : | 538 | (cosine <= -1.0f) ? F_PI : |
@@ -451,8 +544,8 @@ inline BOOL are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon) | |||
451 | { | 544 | { |
452 | LLVector3 an = a; | 545 | LLVector3 an = a; |
453 | LLVector3 bn = b; | 546 | LLVector3 bn = b; |
454 | an.normVec(); | 547 | an.normalize(); |
455 | bn.normVec(); | 548 | bn.normalize(); |
456 | F32 dot = an * bn; | 549 | F32 dot = an * bn; |
457 | if ( (1.0f - fabs(dot)) < epsilon) | 550 | if ( (1.0f - fabs(dot)) < epsilon) |
458 | { | 551 | { |
diff --git a/linden/indra/llmath/v4math.cpp b/linden/indra/llmath/v4math.cpp index 26a47ff..34b8f07 100644 --- a/linden/indra/llmath/v4math.cpp +++ b/linden/indra/llmath/v4math.cpp | |||
@@ -113,8 +113,8 @@ F32 angle_between( const LLVector4& a, const LLVector4& b ) | |||
113 | { | 113 | { |
114 | LLVector4 an = a; | 114 | LLVector4 an = a; |
115 | LLVector4 bn = b; | 115 | LLVector4 bn = b; |
116 | an.normVec(); | 116 | an.normalize(); |
117 | bn.normVec(); | 117 | bn.normalize(); |
118 | F32 cosine = an * bn; | 118 | F32 cosine = an * bn; |
119 | F32 angle = (cosine >= 1.0f) ? 0.0f : | 119 | F32 angle = (cosine >= 1.0f) ? 0.0f : |
120 | (cosine <= -1.0f) ? F_PI : | 120 | (cosine <= -1.0f) ? F_PI : |
@@ -126,8 +126,8 @@ BOOL are_parallel(const LLVector4 &a, const LLVector4 &b, F32 epsilon) | |||
126 | { | 126 | { |
127 | LLVector4 an = a; | 127 | LLVector4 an = a; |
128 | LLVector4 bn = b; | 128 | LLVector4 bn = b; |
129 | an.normVec(); | 129 | an.normalize(); |
130 | bn.normVec(); | 130 | bn.normalize(); |
131 | F32 dot = an * bn; | 131 | F32 dot = an * bn; |
132 | if ( (1.0f - fabs(dot)) < epsilon) | 132 | if ( (1.0f - fabs(dot)) < epsilon) |
133 | return TRUE; | 133 | return TRUE; |
diff --git a/linden/indra/llmath/v4math.h b/linden/indra/llmath/v4math.h index 60e30e3..4ef2d32 100644 --- a/linden/indra/llmath/v4math.h +++ b/linden/indra/llmath/v4math.h | |||
@@ -68,17 +68,29 @@ class LLVector4 | |||
68 | 68 | ||
69 | inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite | 69 | inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite |
70 | 70 | ||
71 | inline void clearVec(); // Clears LLVector4 to (0, 0, 0, 1) | 71 | inline void clear(); // Clears LLVector4 to (0, 0, 0, 1) |
72 | inline void zeroVec(); // zero LLVector4 to (0, 0, 0, 0) | 72 | inline void clearVec(); // deprecated |
73 | inline void setVec(F32 x, F32 y, F32 z); // Sets LLVector4 to (x, y, z, 1) | 73 | inline void zeroVec(); // deprecated |
74 | inline void setVec(F32 x, F32 y, F32 z, F32 w); // Sets LLVector4 to (x, y, z, w) | 74 | |
75 | inline void setVec(const LLVector4 &vec); // Sets LLVector4 to vec | 75 | inline void set(F32 x, F32 y, F32 z); // Sets LLVector4 to (x, y, z, 1) |
76 | inline void setVec(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec | 76 | inline void set(F32 x, F32 y, F32 z, F32 w); // Sets LLVector4 to (x, y, z, w) |
77 | inline void setVec(const F32 *vec); // Sets LLVector4 to vec | 77 | inline void set(const LLVector4 &vec); // Sets LLVector4 to vec |
78 | 78 | inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec | |
79 | F32 magVec() const; // Returns magnitude of LLVector4 | 79 | inline void set(const F32 *vec); // Sets LLVector4 to vec |
80 | F32 magVecSquared() const; // Returns magnitude squared of LLVector4 | 80 | |
81 | F32 normVec(); // Normalizes and returns the magnitude of LLVector4 | 81 | inline void setVec(F32 x, F32 y, F32 z); // deprecated |
82 | inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated | ||
83 | inline void setVec(const LLVector4 &vec); // deprecated | ||
84 | inline void setVec(const LLVector3 &vec, F32 w = 1.f); // deprecated | ||
85 | inline void setVec(const F32 *vec); // deprecated | ||
86 | |||
87 | F32 length() const; // Returns magnitude of LLVector4 | ||
88 | F32 lengthSquared() const; // Returns magnitude squared of LLVector4 | ||
89 | F32 normalize(); // Normalizes and returns the magnitude of LLVector4 | ||
90 | |||
91 | F32 magVec() const; // deprecated | ||
92 | F32 magVecSquared() const; // deprecated | ||
93 | F32 normVec(); // deprecated | ||
82 | 94 | ||
83 | // Sets all values to absolute value of their original values | 95 | // Sets all values to absolute value of their original values |
84 | // Returns TRUE if data changed | 96 | // Returns TRUE if data changed |
@@ -192,6 +204,15 @@ inline BOOL LLVector4::isFinite() const | |||
192 | 204 | ||
193 | // Clear and Assignment Functions | 205 | // Clear and Assignment Functions |
194 | 206 | ||
207 | inline void LLVector4::clear(void) | ||
208 | { | ||
209 | mV[VX] = 0.f; | ||
210 | mV[VY] = 0.f; | ||
211 | mV[VZ] = 0.f; | ||
212 | mV[VW] = 1.f; | ||
213 | } | ||
214 | |||
215 | // deprecated | ||
195 | inline void LLVector4::clearVec(void) | 216 | inline void LLVector4::clearVec(void) |
196 | { | 217 | { |
197 | mV[VX] = 0.f; | 218 | mV[VX] = 0.f; |
@@ -200,6 +221,7 @@ inline void LLVector4::clearVec(void) | |||
200 | mV[VW] = 1.f; | 221 | mV[VW] = 1.f; |
201 | } | 222 | } |
202 | 223 | ||
224 | // deprecated | ||
203 | inline void LLVector4::zeroVec(void) | 225 | inline void LLVector4::zeroVec(void) |
204 | { | 226 | { |
205 | mV[VX] = 0.f; | 227 | mV[VX] = 0.f; |
@@ -208,6 +230,48 @@ inline void LLVector4::zeroVec(void) | |||
208 | mV[VW] = 0.f; | 230 | mV[VW] = 0.f; |
209 | } | 231 | } |
210 | 232 | ||
233 | inline void LLVector4::set(F32 x, F32 y, F32 z) | ||
234 | { | ||
235 | mV[VX] = x; | ||
236 | mV[VY] = y; | ||
237 | mV[VZ] = z; | ||
238 | mV[VW] = 1.f; | ||
239 | } | ||
240 | |||
241 | inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w) | ||
242 | { | ||
243 | mV[VX] = x; | ||
244 | mV[VY] = y; | ||
245 | mV[VZ] = z; | ||
246 | mV[VW] = w; | ||
247 | } | ||
248 | |||
249 | inline void LLVector4::set(const LLVector4 &vec) | ||
250 | { | ||
251 | mV[VX] = vec.mV[VX]; | ||
252 | mV[VY] = vec.mV[VY]; | ||
253 | mV[VZ] = vec.mV[VZ]; | ||
254 | mV[VW] = vec.mV[VW]; | ||
255 | } | ||
256 | |||
257 | inline void LLVector4::set(const LLVector3 &vec, F32 w) | ||
258 | { | ||
259 | mV[VX] = vec.mV[VX]; | ||
260 | mV[VY] = vec.mV[VY]; | ||
261 | mV[VZ] = vec.mV[VZ]; | ||
262 | mV[VW] = w; | ||
263 | } | ||
264 | |||
265 | inline void LLVector4::set(const F32 *vec) | ||
266 | { | ||
267 | mV[VX] = vec[VX]; | ||
268 | mV[VY] = vec[VY]; | ||
269 | mV[VZ] = vec[VZ]; | ||
270 | mV[VW] = vec[VW]; | ||
271 | } | ||
272 | |||
273 | |||
274 | // deprecated | ||
211 | inline void LLVector4::setVec(F32 x, F32 y, F32 z) | 275 | inline void LLVector4::setVec(F32 x, F32 y, F32 z) |
212 | { | 276 | { |
213 | mV[VX] = x; | 277 | mV[VX] = x; |
@@ -216,6 +280,7 @@ inline void LLVector4::setVec(F32 x, F32 y, F32 z) | |||
216 | mV[VW] = 1.f; | 280 | mV[VW] = 1.f; |
217 | } | 281 | } |
218 | 282 | ||
283 | // deprecated | ||
219 | inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) | 284 | inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) |
220 | { | 285 | { |
221 | mV[VX] = x; | 286 | mV[VX] = x; |
@@ -224,6 +289,7 @@ inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) | |||
224 | mV[VW] = w; | 289 | mV[VW] = w; |
225 | } | 290 | } |
226 | 291 | ||
292 | // deprecated | ||
227 | inline void LLVector4::setVec(const LLVector4 &vec) | 293 | inline void LLVector4::setVec(const LLVector4 &vec) |
228 | { | 294 | { |
229 | mV[VX] = vec.mV[VX]; | 295 | mV[VX] = vec.mV[VX]; |
@@ -232,6 +298,7 @@ inline void LLVector4::setVec(const LLVector4 &vec) | |||
232 | mV[VW] = vec.mV[VW]; | 298 | mV[VW] = vec.mV[VW]; |
233 | } | 299 | } |
234 | 300 | ||
301 | // deprecated | ||
235 | inline void LLVector4::setVec(const LLVector3 &vec, F32 w) | 302 | inline void LLVector4::setVec(const LLVector3 &vec, F32 w) |
236 | { | 303 | { |
237 | mV[VX] = vec.mV[VX]; | 304 | mV[VX] = vec.mV[VX]; |
@@ -240,6 +307,7 @@ inline void LLVector4::setVec(const LLVector3 &vec, F32 w) | |||
240 | mV[VW] = w; | 307 | mV[VW] = w; |
241 | } | 308 | } |
242 | 309 | ||
310 | // deprecated | ||
243 | inline void LLVector4::setVec(const F32 *vec) | 311 | inline void LLVector4::setVec(const F32 *vec) |
244 | { | 312 | { |
245 | mV[VX] = vec[VX]; | 313 | mV[VX] = vec[VX]; |
@@ -250,6 +318,16 @@ inline void LLVector4::setVec(const F32 *vec) | |||
250 | 318 | ||
251 | // LLVector4 Magnitude and Normalization Functions | 319 | // LLVector4 Magnitude and Normalization Functions |
252 | 320 | ||
321 | inline F32 LLVector4::length(void) const | ||
322 | { | ||
323 | return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); | ||
324 | } | ||
325 | |||
326 | inline F32 LLVector4::lengthSquared(void) const | ||
327 | { | ||
328 | return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; | ||
329 | } | ||
330 | |||
253 | inline F32 LLVector4::magVec(void) const | 331 | inline F32 LLVector4::magVec(void) const |
254 | { | 332 | { |
255 | return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); | 333 | return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); |
@@ -364,13 +442,13 @@ inline LLVector4 operator-(const LLVector4 &a) | |||
364 | inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) | 442 | inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) |
365 | { | 443 | { |
366 | LLVector4 vec = a - b; | 444 | LLVector4 vec = a - b; |
367 | return (vec.magVec()); | 445 | return (vec.length()); |
368 | } | 446 | } |
369 | 447 | ||
370 | inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b) | 448 | inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b) |
371 | { | 449 | { |
372 | LLVector4 vec = a - b; | 450 | LLVector4 vec = a - b; |
373 | return (vec.magVecSquared()); | 451 | return (vec.lengthSquared()); |
374 | } | 452 | } |
375 | 453 | ||
376 | inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) | 454 | inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) |
@@ -382,6 +460,29 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) | |||
382 | a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); | 460 | a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); |
383 | } | 461 | } |
384 | 462 | ||
463 | inline F32 LLVector4::normalize(void) | ||
464 | { | ||
465 | F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); | ||
466 | F32 oomag; | ||
467 | |||
468 | if (mag > FP_MAG_THRESHOLD) | ||
469 | { | ||
470 | oomag = 1.f/mag; | ||
471 | mV[VX] *= oomag; | ||
472 | mV[VY] *= oomag; | ||
473 | mV[VZ] *= oomag; | ||
474 | } | ||
475 | else | ||
476 | { | ||
477 | mV[0] = 0.f; | ||
478 | mV[1] = 0.f; | ||
479 | mV[2] = 0.f; | ||
480 | mag = 0; | ||
481 | } | ||
482 | return (mag); | ||
483 | } | ||
484 | |||
485 | // deprecated | ||
385 | inline F32 LLVector4::normVec(void) | 486 | inline F32 LLVector4::normVec(void) |
386 | { | 487 | { |
387 | F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); | 488 | F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); |
diff --git a/linden/indra/llmath/xform.h b/linden/indra/llmath/xform.h index 8fd1e9e..ad2a944 100644 --- a/linden/indra/llmath/xform.h +++ b/linden/indra/llmath/xform.h | |||
@@ -35,10 +35,12 @@ | |||
35 | #include "m4math.h" | 35 | #include "m4math.h" |
36 | #include "llquaternion.h" | 36 | #include "llquaternion.h" |
37 | 37 | ||
38 | const F32 MAX_OBJECT_Z = 768.f; | 38 | const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f |
39 | const F32 MIN_OBJECT_Z = -256.f; | 39 | const F32 MIN_OBJECT_Z = -256.f; |
40 | const F32 MIN_OBJECT_SCALE = 0.01f; | 40 | const F32 DEFAULT_MAX_PRIM_SCALE = 10.f; |
41 | const F32 MAX_OBJECT_SCALE = 10.f; | 41 | const F32 MIN_PRIM_SCALE = 0.01f; |
42 | const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX | ||
43 | |||
42 | 44 | ||
43 | class LLXform | 45 | class LLXform |
44 | { | 46 | { |
@@ -138,7 +140,7 @@ public: | |||
138 | 140 | ||
139 | void init() | 141 | void init() |
140 | { | 142 | { |
141 | mWorldMatrix.identity(); | 143 | mWorldMatrix.setIdentity(); |
142 | mMin.clearVec(); | 144 | mMin.clearVec(); |
143 | mMax.clearVec(); | 145 | mMax.clearVec(); |
144 | 146 | ||