aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmath
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llmath/files.lst2
-rw-r--r--linden/indra/llmath/llline.cpp189
-rw-r--r--linden/indra/llmath/llline.h75
-rw-r--r--linden/indra/llmath/llmath.h33
-rw-r--r--linden/indra/llmath/llmath.vcproj12
-rw-r--r--linden/indra/llmath/llquaternion.cpp186
-rw-r--r--linden/indra/llmath/llquaternion.h164
-rw-r--r--linden/indra/llmath/llrect.h5
-rw-r--r--linden/indra/llmath/llsphere.cpp364
-rw-r--r--linden/indra/llmath/llsphere.h72
-rw-r--r--linden/indra/llmath/lluuid.cpp5
-rw-r--r--linden/indra/llmath/lluuid.h1
-rw-r--r--linden/indra/llmath/llvolume.cpp269
-rw-r--r--linden/indra/llmath/llvolume.h35
-rw-r--r--linden/indra/llmath/llvolumemgr.cpp182
-rw-r--r--linden/indra/llmath/llvolumemgr.h47
-rw-r--r--linden/indra/llmath/m3math.cpp91
-rw-r--r--linden/indra/llmath/m3math.h24
-rw-r--r--linden/indra/llmath/m4math.cpp2
-rw-r--r--linden/indra/llmath/m4math.h8
-rw-r--r--linden/indra/llmath/v2math.h95
-rw-r--r--linden/indra/llmath/v3dmath.h13
-rw-r--r--linden/indra/llmath/v3math.cpp16
-rw-r--r--linden/indra/llmath/v3math.h123
-rw-r--r--linden/indra/llmath/v4math.cpp8
-rw-r--r--linden/indra/llmath/v4math.h127
-rw-r--r--linden/indra/llmath/xform.h10
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
2llmath/llcamera.cpp 2llmath/llcamera.cpp
3llmath/llcoordframe.cpp 3llmath/llcoordframe.cpp
4llmath/llcrc.cpp 4llmath/llcrc.cpp
5llmath/llline.cpp
5llmath/llmd5.cpp 6llmath/llmd5.cpp
6llmath/llperlin.cpp 7llmath/llperlin.cpp
7llmath/llquaternion.cpp 8llmath/llquaternion.cpp
8llmath/llrand.cpp 9llmath/llrand.cpp
9llmath/llrect.cpp 10llmath/llrect.cpp
11llmath/llsphere.cpp
10llmath/lluuid.cpp 12llmath/lluuid.cpp
11llmath/llvolume.cpp 13llmath/llvolume.cpp
12llmath/llvolumemgr.cpp 14llmath/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
26const F32 SOME_SMALL_NUMBER = 1.0e-5f;
27const F32 SOME_VERY_SMALL_NUMBER = 1.0e-8f;
28
29LLLine::LLLine()
30: mPoint(0.f, 0.f, 0.f),
31 mDirection(1.f, 0.f, 0.f)
32{ }
33
34LLLine::LLLine( const LLVector3& first_point, const LLVector3& second_point )
35{
36 setPoints(first_point, second_point);
37}
38
39void 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
46void LLLine::setPointDirection( const LLVector3& first_point, const LLVector3& second_point )
47{
48 setPoints(first_point, first_point + second_point);
49}
50
51bool 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
60LLVector3 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
70LLVector3 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
107std::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
114F32 ALMOST_PARALLEL = 0.99f;
115F32 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'
119bool 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
149bool 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
31const F32 DEFAULT_INTERSECTION_ERROR = 0.000001f;
32
33class LLLine
34{
35public:
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
67protected:
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
108inline 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
102inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) 114inline 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
135inline 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
123inline S32 llabs(const S32 a) 156inline 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;
51LLQuaternion::LLQuaternion(const LLMatrix4 &mat) 51LLQuaternion::LLQuaternion(const LLMatrix4 &mat)
52{ 52{
53 *this = mat.quaternion(); 53 *this = mat.quaternion();
54 normQuat(); 54 normalize();
55} 55}
56 56
57LLQuaternion::LLQuaternion(const LLMatrix3 &mat) 57LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
58{ 58{
59 *this = mat.quaternion(); 59 *this = mat.quaternion();
60 normQuat(); 60 normalize();
61} 61}
62 62
63LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) 63LLQuaternion::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
79LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) 79LLQuaternion::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
95LLQuaternion::LLQuaternion(const LLVector3 &x_axis, 95LLQuaternion::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
141const 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
160const 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
179const 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
197const 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
208const LLQuaternion& LLQuaternion::set(const LLMatrix3 &mat)
209{
210 *this = mat.quaternion();
211 normalize();
212 return (*this);
213}
214
215// deprecated
216const LLQuaternion& LLQuaternion::set(const LLMatrix4 &mat)
217{
218 *this = mat.quaternion();
219 normalize();
220 return (*this);
221}
222
223// deprecated
141const LLQuaternion& LLQuaternion::setQuat(F32 angle, F32 x, F32 y, F32 z) 224const 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
160const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector3 &vec) 244const 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
179const LLQuaternion& LLQuaternion::setQuat(F32 angle, const LLVector4 &vec) 263const 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
291const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat)
292{
293 *this = mat.quaternion();
294 normalize();
295 return (*this);
296}
297
298const 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
745const LLQuaternion& LLQuaternion::setQuat(const LLMatrix3 &mat)
746{
747 *this = mat.quaternion();
748 normQuat();
749 return (*this);
750}
751
752const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
753{
754 *this = mat.quaternion();
755 normQuat();
756 return (*this);
757}
758
759void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const 843void 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
244inline 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
254inline 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
264inline 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
227inline const LLQuaternion& LLQuaternion::setQuatInit(F32 x, F32 y, F32 z, F32 w) 276inline 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
237inline const LLQuaternion& LLQuaternion::setQuat(const LLQuaternion &quat) 287inline 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
247inline const LLQuaternion& LLQuaternion::setQuat(const F32 *q) 298inline 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
348inline 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
279inline const LLQuaternion& LLQuaternion::conjQuat() 356inline const LLQuaternion& LLQuaternion::conjQuat()
@@ -285,12 +362,21 @@ inline const LLQuaternion& LLQuaternion::conjQuat()
285} 362}
286 363
287// Transpose 364// Transpose
365inline 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
288inline const LLQuaternion& LLQuaternion::transQuat() 374inline 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
471inline 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
385inline F32 LLQuaternion::normQuat() 495inline 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
25LLSphere::LLSphere()
26: mCenter(0.f, 0.f, 0.f),
27 mRadius(0.f)
28{ }
29
30LLSphere::LLSphere( const LLVector3& center, F32 radius)
31{
32 set(center, radius);
33}
34
35void LLSphere::set( const LLVector3& center, F32 radius )
36{
37 mCenter = center;
38 setRadius(radius);
39}
40
41void LLSphere::setCenter( const LLVector3& center)
42{
43 mCenter = center;
44}
45
46void LLSphere::setRadius( F32 radius)
47{
48 if (radius < 0.f)
49 {
50 radius = -radius;
51 }
52 mRadius = radius;
53}
54
55const LLVector3& LLSphere::getCenter() const
56{
57 return mCenter;
58}
59
60F32 LLSphere::getRadius() const
61{
62 return mRadius;
63}
64
65// returns 'TRUE' if this sphere completely contains other_sphere
66BOOL 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
73BOOL 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
81F32 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
87bool 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
94std::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
102void 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
141LLSphere 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
174LLSphere 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
32class LLSphere
33{
34public:
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
66protected:
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
870void 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
871U32 LLUUID::getRandomSeed() 876U32 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
2517S32 *LLVolume::getTriangleIndices(U32 &num_indices) const 2513S32 *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;
3149noindices: 3131 return index;
3150 if (!indices) 3132}
3133
3134S32 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
3487BOOL equalTriangle(const S32 *a, const S32 *b) 3517BOOL 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
3900const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity
3901const 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
3851BOOL LLVolumeParams::isConvex() const 3905BOOL 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
3972void 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
3897LLFaceID LLVolume::generateFaceMask() 3992LLFaceID 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;
72const F32 REV_QUANTA = 0.015f; 72const F32 REV_QUANTA = 0.015f;
73const F32 HOLLOW_QUANTA = 0.00002f; 73const F32 HOLLOW_QUANTA = 0.00002f;
74 74
75const S32 MAX_VOLUME_TRIANGLE_INDICES = 10000;
76
75//============================================================================ 77//============================================================================
76 78
77// useful masks 79// useful masks
@@ -187,10 +189,10 @@ class LLProfileParams
187public: 189public:
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
307public: 309public:
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
630protected: 635protected:
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
39LLVolumeMgr* gVolumeMgr = 0; 39//LLVolumeMgr* gVolumeMgr = 0;
40 40
41const F32 BASE_THRESHOLD = 0.03f; 41const F32 BASE_THRESHOLD = 0.03f;
42 42
@@ -49,37 +49,23 @@ F32 LLVolumeLODGroup::mDetailThresholds[NUM_LODS] = {BASE_THRESHOLD,
49//static 49//static
50F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f}; 50F32 LLVolumeLODGroup::mDetailScales[NUM_LODS] = {1.f, 1.5f, 2.5f, 4.f};
51 51
52//============================================================================
53//static
54void LLVolumeMgr::initClass()
55{
56 gVolumeMgr = new LLVolumeMgr();
57}
58
59//static
60BOOL 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
73LLVolumeMgr::LLVolumeMgr() 55LLVolumeMgr::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
79LLVolumeMgr::~LLVolumeMgr() 63LLVolumeMgr::~LLVolumeMgr()
80{ 64{
81 cleanup(); 65 cleanup();
66
82 delete mDataMutex; 67 delete mDataMutex;
68 mDataMutex = NULL;
83} 69}
84 70
85BOOL LLVolumeMgr::cleanup() 71BOOL 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>.
113LLVolume *LLVolumeMgr::getVolume(const LLVolumeParams &volume_params, const S32 detail) 108LLVolume *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
138LLVolumeLODGroup* 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
140void LLVolumeMgr::cleanupVolume(LLVolume *volumep) 158void 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
205S32 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
217S32 LLVolumeMgr::getGroupCount() const
218{
219 return mVolumeLODGroups.size();
220}
221#endif
222
223// protected
224LLVolumeLODGroup* 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
178void LLVolumeMgr::dump() 234void 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
257void LLVolumeMgr::useMutex()
258{
259 if (!mDataMutex)
260 {
261 mDataMutex = new LLMutex(gAPRPoolp);
262 }
263}
264
195std::ostream& operator<<(std::ostream& s, const LLVolumeMgr& volume_mgr) 265std::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 &params)
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
308S32 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
230LLVolumeLODGroup::~LLVolumeLODGroup() 320LLVolumeLODGroup::~LLVolumeLODGroup()
231{ 321{
322 destroy();
232} 323}
233 324
325// protected
326void 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
235LLVolume * LLVolumeLODGroup::getLOD(const S32 detail) 335LLVolume * 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
248BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) 348BOOL 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
44class LLVolumeLODGroup : public LLThreadSafeRefCount 44class LLVolumeLODGroup : public LLThreadSafeRefCount
45{ 45{
46protected:
47 ~LLVolumeLODGroup();
48
49public: 46public:
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
69protected:
70 virtual ~LLVolumeLODGroup();
71 void destroy();
72
68protected: 73protected:
69 LLVolumeParams mParams; 74 LLVolumeParams mParams;
70 75
@@ -77,30 +82,50 @@ protected:
77 82
78class LLVolumeMgr 83class LLVolumeMgr
79{ 84{
80public: 85//public:
81 static void initClass(); 86// static void initClass();
82 static BOOL cleanupClass(); 87// static BOOL cleanupClass();
83 88
84public: 89public:
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
94protected: 114protected:
115 virtual LLVolumeLODGroup* createNewGroup(const LLVolumeParams& volume_params);
116
117protected:
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
104extern 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
139const LLMatrix3& LLMatrix3::identity() 139const 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
155const LLMatrix3& LLMatrix3::zero() 155const 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
171const 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
194const LLMatrix3& LLMatrix3::invert() 210void 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
381const 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
392const 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
356const LLMatrix3& LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z) 404const 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
435void 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
388LLVector3 LLMatrix3::getFwdRow() const 446LLVector3 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
597const 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
539std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a) 610std::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
37class LLVector4; 38class LLVector4;
38class LLVector3; 39class 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
166const LLMatrix4& LLMatrix4::zero() 166const 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
244inline LLMatrix4::LLMatrix4() 244inline LLMatrix4::LLMatrix4()
245{ 245{
246 identity(); 246 setIdentity();
247} 247}
248 248
249inline const LLMatrix4& LLMatrix4::identity() 249inline 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
143inline void LLVector2::clear(void)
144{
145 mV[VX] = 0.f;
146 mV[VY] = 0.f;
147}
148
149inline void LLVector2::setZero(void)
150{
151 mV[VX] = 0.f;
152 mV[VY] = 0.f;
153}
154
155// deprecated
135inline void LLVector2::clearVec(void) 156inline 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
141inline void LLVector2::zeroVec(void) 163inline 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
169inline void LLVector2::set(F32 x, F32 y)
170{
171 mV[VX] = x;
172 mV[VY] = y;
173}
174
175inline void LLVector2::set(const LLVector2 &vec)
176{
177 mV[VX] = vec.mV[VX];
178 mV[VY] = vec.mV[VY];
179}
180
181inline void LLVector2::set(const F32 *vec)
182{
183 mV[VX] = vec[VX];
184 mV[VY] = vec[VY];
185}
186
187
188// deprecated
147inline void LLVector2::setVec(F32 x, F32 y) 189inline 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
153inline void LLVector2::setVec(const LLVector2 &vec) 196inline 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
159inline void LLVector2::setVec(const F32 *vec) 203inline 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
211inline F32 LLVector2::length(void) const
212{
213 return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]);
214}
215
216inline F32 LLVector2::lengthSquared(void) const
217{
218 return mV[0]*mV[0] + mV[1]*mV[1];
219}
220
221inline 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
167inline F32 LLVector2::magVec(void) const 242inline 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
172inline F32 LLVector2::magVecSquared(void) const 248inline 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
177inline F32 LLVector2::normVec(void) 254inline 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
202inline 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
201inline const LLVector3d& LLVector3d::zeroVec(void) 210inline 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
175const 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
183const 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
175const LLVector3& LLVector3::setVec(const LLVector3d &vec) 191const 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
206inline void LLVector3::clear(void)
207{
208 mV[0] = 0.f;
209 mV[1] = 0.f;
210 mV[2] = 0.f;
211}
212
213inline void LLVector3::setZero(void)
214{
215 mV[0] = 0.f;
216 mV[1] = 0.f;
217 mV[2] = 0.f;
218}
219
191inline void LLVector3::clearVec(void) 220inline 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
234inline void LLVector3::set(F32 x, F32 y, F32 z)
235{
236 mV[VX] = x;
237 mV[VY] = y;
238 mV[VZ] = z;
239}
240
241inline 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
248inline 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
205inline void LLVector3::setVec(F32 x, F32 y, F32 z) 256inline 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
212inline void LLVector3::setVec(const LLVector3 &vec) 264inline 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
219inline void LLVector3::setVec(const F32 *vec) 272inline 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
279inline 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
226inline F32 LLVector3::normVec(void) 302inline 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
326inline F32 LLVector3::length(void) const
327{
328 return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
329}
330
331inline F32 LLVector3::lengthSquared(void) const
332{
333 return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
334}
335
250inline F32 LLVector3::magVec(void) const 336inline 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
346inline 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
260inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b) 353inline 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)
397inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b) 490inline 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
207inline 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
195inline void LLVector4::clearVec(void) 216inline 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
203inline void LLVector4::zeroVec(void) 225inline 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
233inline 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
241inline 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
249inline 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
257inline 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
265inline 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
211inline void LLVector4::setVec(F32 x, F32 y, F32 z) 275inline 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
219inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) 284inline 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
227inline void LLVector4::setVec(const LLVector4 &vec) 293inline 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
235inline void LLVector4::setVec(const LLVector3 &vec, F32 w) 302inline 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
243inline void LLVector4::setVec(const F32 *vec) 311inline 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
321inline F32 LLVector4::length(void) const
322{
323 return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
324}
325
326inline F32 LLVector4::lengthSquared(void) const
327{
328 return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
329}
330
253inline F32 LLVector4::magVec(void) const 331inline 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)
364inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) 442inline 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
370inline F32 dist_vec_squared(const LLVector4 &a, const LLVector4 &b) 448inline 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
376inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) 454inline 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
463inline 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
385inline F32 LLVector4::normVec(void) 486inline 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
38const F32 MAX_OBJECT_Z = 768.f; 38const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
39const F32 MIN_OBJECT_Z = -256.f; 39const F32 MIN_OBJECT_Z = -256.f;
40const F32 MIN_OBJECT_SCALE = 0.01f; 40const F32 DEFAULT_MAX_PRIM_SCALE = 10.f;
41const F32 MAX_OBJECT_SCALE = 10.f; 41const F32 MIN_PRIM_SCALE = 0.01f;
42const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX
43
42 44
43class LLXform 45class 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