PageRenderTime 69ms CodeModel.GetById 2ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmath/v3math.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 371 lines | 274 code | 55 blank | 42 comment | 32 complexity | 71d918abae4c1362b3061570daa6b3fd MD5 | raw file
  1/** 
  2 * @file v3math.cpp
  3 * @brief LLVector3 class implementation.
  4 *
  5 * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "v3math.h"
 30
 31//#include "vmath.h"
 32#include "v2math.h"
 33#include "v4math.h"
 34#include "m4math.h"
 35#include "m3math.h"
 36#include "llquaternion.h"
 37#include "llquantize.h"
 38#include "v3dmath.h"
 39
 40// LLVector3
 41// WARNING: Don't use these for global const definitions!
 42// For example: 
 43//		const LLQuaternion(0.5f * F_PI, LLVector3::zero);
 44// at the top of a *.cpp file might not give you what you think.
 45const LLVector3 LLVector3::zero(0,0,0);
 46const LLVector3 LLVector3::x_axis(1.f, 0, 0);
 47const LLVector3 LLVector3::y_axis(0, 1.f, 0);
 48const LLVector3 LLVector3::z_axis(0, 0, 1.f);
 49const LLVector3 LLVector3::x_axis_neg(-1.f, 0, 0);
 50const LLVector3 LLVector3::y_axis_neg(0, -1.f, 0);
 51const LLVector3 LLVector3::z_axis_neg(0, 0, -1.f);
 52const LLVector3 LLVector3::all_one(1.f,1.f,1.f);
 53
 54
 55// Clamps each values to range (min,max).
 56// Returns TRUE if data changed.
 57BOOL LLVector3::clamp(F32 min, F32 max)
 58{
 59	BOOL ret = FALSE;
 60
 61	if (mV[0] < min) { mV[0] = min; ret = TRUE; }
 62	if (mV[1] < min) { mV[1] = min; ret = TRUE; }
 63	if (mV[2] < min) { mV[2] = min; ret = TRUE; }
 64
 65	if (mV[0] > max) { mV[0] = max; ret = TRUE; }
 66	if (mV[1] > max) { mV[1] = max; ret = TRUE; }
 67	if (mV[2] > max) { mV[2] = max; ret = TRUE; }
 68
 69	return ret;
 70}
 71
 72// Clamps length to an upper limit.  
 73// Returns TRUE if the data changed
 74BOOL LLVector3::clampLength( F32 length_limit )
 75{
 76	BOOL changed = FALSE;
 77
 78	F32 len = length();
 79	if (llfinite(len))
 80	{
 81		if ( len > length_limit)
 82		{
 83			normalize();
 84			if (length_limit < 0.f)
 85			{
 86				length_limit = 0.f;
 87			}
 88			mV[0] *= length_limit;
 89			mV[1] *= length_limit;
 90			mV[2] *= length_limit;
 91			changed = TRUE;
 92		}
 93	}
 94	else
 95	{	// this vector may still be salvagable
 96		F32 max_abs_component = 0.f;
 97		for (S32 i = 0; i < 3; ++i)
 98		{
 99			F32 abs_component = fabs(mV[i]);
100			if (llfinite(abs_component))
101			{
102				if (abs_component > max_abs_component)
103				{
104					max_abs_component = abs_component;
105				}
106			}
107			else
108			{
109				// no it can't be salvaged --> clear it
110				clear();
111				changed = TRUE;
112				break;
113			}
114		}
115		if (!changed)
116		{
117			// yes it can be salvaged -->
118			// bring the components down before we normalize
119			mV[0] /= max_abs_component;
120			mV[1] /= max_abs_component;
121			mV[2] /= max_abs_component;
122			normalize();
123
124			if (length_limit < 0.f)
125			{
126				length_limit = 0.f;
127			}
128			mV[0] *= length_limit;
129			mV[1] *= length_limit;
130			mV[2] *= length_limit;
131		}
132	}
133
134	return changed;
135}
136
137BOOL LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec)
138{
139	BOOL ret = FALSE;
140
141	if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = TRUE; }
142	if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = TRUE; }
143	if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = TRUE; }
144
145	if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = TRUE; }
146	if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = TRUE; }
147	if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = TRUE; }
148
149	return ret;
150}
151
152
153// Sets all values to absolute value of their original values
154// Returns TRUE if data changed
155BOOL LLVector3::abs()
156{
157	BOOL ret = FALSE;
158
159	if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = TRUE; }
160	if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = TRUE; }
161	if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = TRUE; }
162
163	return ret;
164}
165
166// Quatizations
167void	LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
168{
169	F32 x = mV[VX];
170	F32 y = mV[VY];
171	F32 z = mV[VZ];
172
173	x = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy);
174	y = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy);
175	z = U16_to_F32(F32_to_U16(z, lowerz,  upperz),  lowerz,  upperz);
176
177	mV[VX] = x;
178	mV[VY] = y;
179	mV[VZ] = z;
180}
181
182void	LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
183{
184	mV[VX] = U8_to_F32(F32_to_U8(mV[VX], lowerxy, upperxy), lowerxy, upperxy);;
185	mV[VY] = U8_to_F32(F32_to_U8(mV[VY], lowerxy, upperxy), lowerxy, upperxy);
186	mV[VZ] = U8_to_F32(F32_to_U8(mV[VZ], lowerz, upperz), lowerz, upperz);
187}
188
189
190void 	LLVector3::snap(S32 sig_digits)
191{
192	mV[VX] = snap_to_sig_figs(mV[VX], sig_digits);
193	mV[VY] = snap_to_sig_figs(mV[VY], sig_digits);
194	mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
195}
196
197const LLVector3&	LLVector3::rotVec(const LLMatrix3 &mat)
198{
199	*this = *this * mat;
200	return *this;
201}
202
203const LLVector3&	LLVector3::rotVec(const LLQuaternion &q)
204{
205	*this = *this * q;
206	return *this;
207}
208
209const LLVector3& LLVector3::transVec(const LLMatrix4& mat)
210{
211	setVec(
212			mV[VX] * mat.mMatrix[VX][VX] + 
213			mV[VY] * mat.mMatrix[VX][VY] + 
214			mV[VZ] * mat.mMatrix[VX][VZ] +
215			mat.mMatrix[VX][VW],
216			 
217			mV[VX] * mat.mMatrix[VY][VX] + 
218			mV[VY] * mat.mMatrix[VY][VY] + 
219			mV[VZ] * mat.mMatrix[VY][VZ] +
220			mat.mMatrix[VY][VW],
221
222			mV[VX] * mat.mMatrix[VZ][VX] + 
223			mV[VY] * mat.mMatrix[VZ][VY] + 
224			mV[VZ] * mat.mMatrix[VZ][VZ] +
225			mat.mMatrix[VZ][VW]);
226
227	return *this;
228}
229
230
231const LLVector3&	LLVector3::rotVec(F32 angle, const LLVector3 &vec)
232{
233	if ( !vec.isExactlyZero() && angle )
234	{
235		*this = *this * LLQuaternion(angle, vec);
236	}
237	return *this;
238}
239
240const LLVector3&	LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
241{
242	LLVector3 vec(x, y, z);
243	if ( !vec.isExactlyZero() && angle )
244	{
245		*this = *this * LLQuaternion(angle, vec);
246	}
247	return *this;
248}
249
250const LLVector3&	LLVector3::scaleVec(const LLVector3& vec)
251{
252	mV[VX] *= vec.mV[VX];
253	mV[VY] *= vec.mV[VY];
254	mV[VZ] *= vec.mV[VZ];
255
256	return *this;
257}
258
259LLVector3			LLVector3::scaledVec(const LLVector3& vec) const
260{
261	LLVector3 ret = LLVector3(*this);
262	ret.scaleVec(vec);
263	return ret;
264}
265
266const LLVector3&	LLVector3::set(const LLVector3d &vec)
267{
268	mV[0] = (F32)vec.mdV[0];
269	mV[1] = (F32)vec.mdV[1];
270	mV[2] = (F32)vec.mdV[2];
271	return (*this);
272}
273
274const LLVector3&	LLVector3::set(const LLVector4 &vec)
275{
276	mV[0] = vec.mV[0];
277	mV[1] = vec.mV[1];
278	mV[2] = vec.mV[2];
279	return (*this);
280}
281
282const LLVector3&	LLVector3::setVec(const LLVector3d &vec)
283{
284	mV[0] = (F32)vec.mdV[0];
285	mV[1] = (F32)vec.mdV[1];
286	mV[2] = (F32)vec.mdV[2];
287	return (*this);
288}
289
290const LLVector3&	LLVector3::setVec(const LLVector4 &vec)
291{
292	mV[0] = vec.mV[0];
293	mV[1] = vec.mV[1];
294	mV[2] = vec.mV[2];
295	return (*this);
296}
297
298LLVector3::LLVector3(const LLVector2 &vec)
299{
300	mV[VX] = (F32)vec.mV[VX];
301	mV[VY] = (F32)vec.mV[VY];
302	mV[VZ] = 0;
303}
304
305LLVector3::LLVector3(const LLVector3d &vec)
306{
307	mV[VX] = (F32)vec.mdV[VX];
308	mV[VY] = (F32)vec.mdV[VY];
309	mV[VZ] = (F32)vec.mdV[VZ];
310}
311
312LLVector3::LLVector3(const LLVector4 &vec)
313{
314	mV[VX] = (F32)vec.mV[VX];
315	mV[VY] = (F32)vec.mV[VY];
316	mV[VZ] = (F32)vec.mV[VZ];
317}
318
319LLVector3::LLVector3(const LLSD& sd)
320{
321	setValue(sd);
322}
323
324LLSD LLVector3::getValue() const
325{
326	LLSD ret;
327	ret[0] = mV[0];
328	ret[1] = mV[1];
329	ret[2] = mV[2];
330	return ret;
331}
332
333void LLVector3::setValue(const LLSD& sd)
334{
335	mV[0] = (F32) sd[0].asReal();
336	mV[1] = (F32) sd[1].asReal();
337	mV[2] = (F32) sd[2].asReal();
338}
339
340const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
341{
342    const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
343    const F32 rx =   rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
344    const F32 ry =   rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] - rot.mQ[VX] * a.mV[VZ];
345    const F32 rz =   rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] - rot.mQ[VY] * a.mV[VX];
346	
347    a.mV[VX] = - rw * rot.mQ[VX] +  rx * rot.mQ[VW] - ry * rot.mQ[VZ] + rz * rot.mQ[VY];
348    a.mV[VY] = - rw * rot.mQ[VY] +  ry * rot.mQ[VW] - rz * rot.mQ[VX] + rx * rot.mQ[VZ];
349    a.mV[VZ] = - rw * rot.mQ[VZ] +  rz * rot.mQ[VW] - rx * rot.mQ[VY] + ry * rot.mQ[VX];
350
351	return a;
352}
353
354// static 
355BOOL LLVector3::parseVector3(const std::string& buf, LLVector3* value)
356{
357	if( buf.empty() || value == NULL)
358	{
359		return FALSE;
360	}
361
362	LLVector3 v;
363	S32 count = sscanf( buf.c_str(), "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 );
364	if( 3 == count )
365	{
366		value->setVec( v );
367		return TRUE;
368	}
369
370	return FALSE;
371}