summaryrefslogtreecommitdiff
path: root/indra/llmath
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmath')
-rw-r--r--indra/llmath/CMakeLists.txt33
-rw-r--r--indra/llmath/camera.h35
-rw-r--r--indra/llmath/coordframe.h35
-rw-r--r--indra/llmath/llbbox.cpp156
-rw-r--r--indra/llmath/llbbox.h97
-rw-r--r--indra/llmath/llbboxlocal.cpp35
-rw-r--r--indra/llmath/llbboxlocal.h38
-rw-r--r--indra/llmath/llcamera.cpp218
-rw-r--r--indra/llmath/llcamera.h73
-rw-r--r--indra/llmath/llcoord.h44
-rw-r--r--indra/llmath/llcoordframe.cpp35
-rw-r--r--indra/llmath/llcoordframe.h35
-rw-r--r--indra/llmath/llinterp.h45
-rw-r--r--indra/llmath/llline.cpp24
-rw-r--r--indra/llmath/llline.h22
-rw-r--r--indra/llmath/llmath.h170
-rw-r--r--indra/llmath/llmodularmath.cpp30
-rw-r--r--indra/llmath/llmodularmath.h52
-rw-r--r--indra/llmath/lloctree.h60
-rw-r--r--indra/llmath/llperlin.cpp35
-rw-r--r--indra/llmath/llperlin.h35
-rw-r--r--indra/llmath/llplane.h35
-rw-r--r--indra/llmath/llquantize.h35
-rw-r--r--indra/llmath/llquaternion.cpp47
-rw-r--r--indra/llmath/llquaternion.h71
-rw-r--r--indra/llmath/llrect.cpp37
-rw-r--r--indra/llmath/llrect.h96
-rw-r--r--indra/llmath/llsdutil_math.cpp42
-rw-r--r--indra/llmath/llsdutil_math.h64
-rw-r--r--indra/llmath/llsphere.cpp24
-rw-r--r--indra/llmath/llsphere.h22
-rw-r--r--indra/llmath/lltreenode.h35
-rw-r--r--indra/llmath/llv4math.h35
-rw-r--r--indra/llmath/llv4matrix3.h35
-rw-r--r--indra/llmath/llv4matrix4.h35
-rw-r--r--indra/llmath/llv4vector3.h35
-rw-r--r--indra/llmath/llvolume.cpp887
-rw-r--r--indra/llmath/llvolume.h91
-rw-r--r--indra/llmath/llvolumemgr.cpp42
-rw-r--r--indra/llmath/llvolumemgr.h43
-rw-r--r--indra/llmath/m3math.cpp35
-rw-r--r--indra/llmath/m3math.h35
-rw-r--r--indra/llmath/m4math.cpp61
-rw-r--r--indra/llmath/m4math.h65
-rw-r--r--indra/llmath/raytrace.cpp35
-rw-r--r--indra/llmath/raytrace.h35
-rw-r--r--indra/llmath/tests/llbbox_test.cpp367
-rw-r--r--indra/llmath/tests/llbboxlocal_test.cpp232
-rw-r--r--indra/llmath/tests/llmodularmath_test.cpp76
-rw-r--r--indra/llmath/tests/llquaternion_test.cpp660
-rw-r--r--indra/llmath/tests/llrect_test.cpp526
-rw-r--r--indra/llmath/tests/m3math_test.cpp321
-rw-r--r--indra/llmath/tests/mathmisc_test.cpp723
-rw-r--r--indra/llmath/tests/v2math_test.cpp448
-rw-r--r--indra/llmath/tests/v3color_test.cpp309
-rw-r--r--indra/llmath/tests/v3dmath_test.cpp526
-rw-r--r--indra/llmath/tests/v3math_test.cpp567
-rw-r--r--indra/llmath/tests/v4color_test.cpp359
-rw-r--r--indra/llmath/tests/v4coloru_test.cpp336
-rw-r--r--indra/llmath/tests/v4math_test.cpp382
-rw-r--r--indra/llmath/tests/xform_test.cpp245
-rw-r--r--indra/llmath/v2math.cpp36
-rw-r--r--indra/llmath/v2math.h62
-rw-r--r--indra/llmath/v3color.cpp75
-rw-r--r--indra/llmath/v3color.h121
-rw-r--r--indra/llmath/v3dmath.cpp41
-rw-r--r--indra/llmath/v3dmath.h91
-rw-r--r--indra/llmath/v3math.cpp129
-rw-r--r--indra/llmath/v3math.h58
-rw-r--r--indra/llmath/v4color.cpp299
-rw-r--r--indra/llmath/v4color.h172
-rw-r--r--indra/llmath/v4coloru.cpp45
-rw-r--r--indra/llmath/v4coloru.h140
-rw-r--r--indra/llmath/v4math.cpp35
-rw-r--r--indra/llmath/v4math.h35
-rw-r--r--indra/llmath/xform.cpp40
-rw-r--r--indra/llmath/xform.h65
77 files changed, 9072 insertions, 1733 deletions
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 6a329fabb6..e93fe90650 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -10,10 +10,12 @@ include_directories(
)
set(llmath_SOURCE_FILES
+ llbbox.cpp
llbboxlocal.cpp
llcamera.cpp
llcoordframe.cpp
llline.cpp
+ llmodularmath.cpp
llperlin.cpp
llquaternion.cpp
llrect.cpp
@@ -39,6 +41,7 @@ set(llmath_HEADER_FILES
camera.h
coordframe.h
+ llbbox.h
llbboxlocal.h
llcamera.h
llcoord.h
@@ -46,6 +49,7 @@ set(llmath_HEADER_FILES
llinterp.h
llline.h
llmath.h
+ llmodularmath.h
lloctree.h
llperlin.h
llplane.h
@@ -60,6 +64,7 @@ set(llmath_HEADER_FILES
llv4vector3.h
llvolume.h
llvolumemgr.h
+ llsdutil_math.h
m3math.h
m4math.h
raytrace.h
@@ -79,3 +84,31 @@ set_source_files_properties(${llmath_HEADER_FILES}
list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})
add_library (llmath ${llmath_SOURCE_FILES})
+
+# Add tests
+if (LL_TESTS)
+ include(LLAddBuildTest)
+ # UNIT TESTS
+ SET(llmath_TEST_SOURCE_FILES
+ llbboxlocal.cpp
+ llmodularmath.cpp
+ llrect.cpp
+ v2math.cpp
+ v3color.cpp
+ v4color.cpp
+ v4coloru.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}")
+
+ # INTEGRATION TESTS
+ set(test_libs llmath llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
+ # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
+ LL_ADD_INTEGRATION_TEST(llbbox llbbox.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llquaternion llquaternion.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(mathmisc "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(m3math "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(v3dmath v3dmath.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(v3math v3math.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(v4math v4math.cpp "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(xform xform.cpp "${test_libs}")
+endif (LL_TESTS)
diff --git a/indra/llmath/camera.h b/indra/llmath/camera.h
index d41af4b830..26f3c3d19f 100644
--- a/indra/llmath/camera.h
+++ b/indra/llmath/camera.h
@@ -2,30 +2,25 @@
* @file camera.h
* @brief Legacy wrapper header.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/coordframe.h b/indra/llmath/coordframe.h
index 384167a124..271bcb433c 100644
--- a/indra/llmath/coordframe.h
+++ b/indra/llmath/coordframe.h
@@ -2,30 +2,25 @@
* @file coordframe.h
* @brief Legacy wrapper header.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp
new file mode 100644
index 0000000000..b46a6e03d2
--- /dev/null
+++ b/indra/llmath/llbbox.cpp
@@ -0,0 +1,156 @@
+/**
+ * @file llbbox.cpp
+ * @brief General purpose bounding box class (Not axis aligned)
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// self include
+#include "llbbox.h"
+
+// library includes
+#include "m4math.h"
+
+void LLBBox::addPointLocal(const LLVector3& p)
+{
+ if (mEmpty)
+ {
+ mMinLocal = p;
+ mMaxLocal = p;
+ mEmpty = FALSE;
+ }
+ else
+ {
+ mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] );
+ mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] );
+ mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] );
+ mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] );
+ mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] );
+ mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] );
+ }
+}
+
+void LLBBox::addPointAgent( LLVector3 p)
+{
+ p -= mPosAgent;
+ p.rotVec( ~mRotation );
+ addPointLocal( p );
+}
+
+
+void LLBBox::addBBoxAgent(const LLBBox& b)
+{
+ if (mEmpty)
+ {
+ mPosAgent = b.mPosAgent;
+ mRotation = b.mRotation;
+ mMinLocal.clearVec();
+ mMaxLocal.clearVec();
+ }
+ LLVector3 vertex[8];
+ vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+ vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+ vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+ vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] );
+ vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] );
+
+ LLMatrix4 m( b.mRotation );
+ m.translate( b.mPosAgent );
+ m.translate( -mPosAgent );
+ m.rotate( ~mRotation );
+
+ for( S32 i=0; i<8; i++ )
+ {
+ addPointLocal( vertex[i] * m );
+ }
+}
+
+
+void LLBBox::expand( F32 delta )
+{
+ mMinLocal.mV[VX] -= delta;
+ mMinLocal.mV[VY] -= delta;
+ mMinLocal.mV[VZ] -= delta;
+ mMaxLocal.mV[VX] += delta;
+ mMaxLocal.mV[VY] += delta;
+ mMaxLocal.mV[VZ] += delta;
+}
+
+LLVector3 LLBBox::localToAgent(const LLVector3& v) const
+{
+ LLMatrix4 m( mRotation );
+ m.translate( mPosAgent );
+ return v * m;
+}
+
+LLVector3 LLBBox::agentToLocal(const LLVector3& v) const
+{
+ LLMatrix4 m;
+ m.translate( -mPosAgent );
+ m.rotate( ~mRotation ); // inverse rotation
+ return v * m;
+}
+
+LLVector3 LLBBox::localToAgentBasis(const LLVector3& v) const
+{
+ LLMatrix4 m( mRotation );
+ return v * m;
+}
+
+LLVector3 LLBBox::agentToLocalBasis(const LLVector3& v) const
+{
+ LLMatrix4 m( ~mRotation ); // inverse rotation
+ return v * m;
+}
+
+BOOL LLBBox::containsPointLocal(const LLVector3& p) const
+{
+ if ( (p.mV[VX] < mMinLocal.mV[VX])
+ ||(p.mV[VX] > mMaxLocal.mV[VX])
+ ||(p.mV[VY] < mMinLocal.mV[VY])
+ ||(p.mV[VY] > mMaxLocal.mV[VY])
+ ||(p.mV[VZ] < mMinLocal.mV[VZ])
+ ||(p.mV[VZ] > mMaxLocal.mV[VZ]))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL LLBBox::containsPointAgent(const LLVector3& p) const
+{
+ LLVector3 point_local = agentToLocal(p);
+ return containsPointLocal(point_local);
+}
+
+
+/*
+LLBBox operator*(const LLBBox &a, const LLMatrix4 &b)
+{
+ return LLBBox( a.mMin * b, a.mMax * b );
+}
+*/
diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h
new file mode 100644
index 0000000000..5b911793f0
--- /dev/null
+++ b/indra/llmath/llbbox.h
@@ -0,0 +1,97 @@
+/**
+ * @file llbbox.h
+ * @brief General purpose bounding box class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_BBOX_H
+#define LL_BBOX_H
+
+#include "v3math.h"
+#include "llquaternion.h"
+
+// Note: "local space" for an LLBBox is defined relative to agent space in terms of
+// a translation followed by a rotation. There is no scale term since the LLBBox's min and
+// max are not necessarily symetrical and define their own extents.
+
+class LLBBox
+{
+public:
+ LLBBox() {mEmpty = TRUE;}
+ LLBBox( const LLVector3& pos_agent,
+ const LLQuaternion& rot,
+ const LLVector3& min_local,
+ const LLVector3& max_local )
+ :
+ mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( TRUE )
+ {}
+
+ // Default copy constructor is OK.
+
+ const LLVector3& getPositionAgent() const { return mPosAgent; }
+ const LLQuaternion& getRotation() const { return mRotation; }
+
+ const LLVector3& getMinLocal() const { return mMinLocal; }
+ void setMinLocal( const LLVector3& min ) { mMinLocal = min; }
+
+ const LLVector3& getMaxLocal() const { return mMaxLocal; }
+ void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; }
+
+ LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; }
+ LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); }
+
+ LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; }
+
+ BOOL containsPointLocal(const LLVector3& p) const;
+ BOOL containsPointAgent(const LLVector3& p) const;
+
+ void addPointAgent(LLVector3 p);
+ void addBBoxAgent(const LLBBox& b);
+
+ void addPointLocal(const LLVector3& p);
+ void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); }
+
+ void expand( F32 delta );
+
+ LLVector3 localToAgent( const LLVector3& v ) const;
+ LLVector3 agentToLocal( const LLVector3& v ) const;
+
+ // Changes rotation but not position
+ LLVector3 localToAgentBasis(const LLVector3& v) const;
+ LLVector3 agentToLocalBasis(const LLVector3& v) const;
+
+
+// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b);
+
+private:
+ LLVector3 mMinLocal;
+ LLVector3 mMaxLocal;
+ LLVector3 mPosAgent; // Position relative to Agent's Region
+ LLQuaternion mRotation;
+ BOOL mEmpty; // Nothing has been added to this bbox yet
+};
+
+//LLBBox operator*(const LLBBox &a, const LLMatrix4 &b);
+
+
+#endif // LL_BBOX_H
diff --git a/indra/llmath/llbboxlocal.cpp b/indra/llmath/llbboxlocal.cpp
index 313013e47e..bf0c1a7b93 100644
--- a/indra/llmath/llbboxlocal.cpp
+++ b/indra/llmath/llbboxlocal.cpp
@@ -2,30 +2,25 @@
* @file llbboxlocal.cpp
* @brief General purpose bounding box class (Not axis aligned).
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llbboxlocal.h b/indra/llmath/llbboxlocal.h
index 043f2dfbca..defb899248 100644
--- a/indra/llmath/llbboxlocal.h
+++ b/indra/llmath/llbboxlocal.h
@@ -2,30 +2,25 @@
* @file llbboxlocal.h
* @brief General purpose bounding box class.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -52,9 +47,6 @@ public:
LLVector3 getCenter() const { return (mMax - mMin) * 0.5f + mMin; }
LLVector3 getExtent() const { return mMax - mMin; }
- BOOL containsPoint(const LLVector3& p) const;
- BOOL intersects(const LLBBoxLocal& b) const;
-
void addPoint(const LLVector3& p);
void addBBox(const LLBBoxLocal& b) { addPoint( b.mMin ); addPoint( b.mMax ); }
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index 3b9ba9d0f7..bad4d00fd6 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -2,30 +2,25 @@
* @file llcamera.cpp
* @brief Implementation of the LLCamera class.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,39 +39,46 @@ LLCamera::LLCamera() :
mNearPlane(DEFAULT_NEAR_PLANE),
mFarPlane(DEFAULT_FAR_PLANE),
mFixedDistance(-1.f),
- mPlaneCount(6)
+ mPlaneCount(6),
+ mFrustumCornerDist(0.f)
{
calculateFrustumPlanes();
}
-LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) :
+LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) :
LLCoordFrame(),
- mView(z_field_of_view),
- mAspect(aspect_ratio),
mViewHeightInPixels(view_height_in_pixels),
- mNearPlane(near_plane),
- mFarPlane(far_plane),
mFixedDistance(-1.f),
- mPlaneCount(6)
+ mPlaneCount(6),
+ mFrustumCornerDist(0.f)
{
- if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
- else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
+ mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
+ mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
+ if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE;
+ mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE);
- if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; }
- else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; }
-
- if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; }
- else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; }
+ setView(vertical_fov_rads);
+}
- if (mFarPlane < 0) { mFarPlane = DEFAULT_FAR_PLANE; }
- else if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; }
- else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; }
- calculateFrustumPlanes();
-}
+// ---------------- LLCamera::getFoo() member functions ----------------
+F32 LLCamera::getMinView() const
+{
+ // minimum vertical fov needs to be constrained in narrow windows.
+ return mAspect > 1
+ ? MIN_FIELD_OF_VIEW // wide views
+ : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views
+}
+F32 LLCamera::getMaxView() const
+{
+ // maximum vertical fov needs to be constrained in wide windows.
+ return mAspect > 1
+ ? MAX_FIELD_OF_VIEW / mAspect // clamps maximum width in wide views
+ : MAX_FIELD_OF_VIEW; // narrow views
+}
// ---------------- LLCamera::setFoo() member functions ----------------
@@ -92,11 +94,9 @@ void LLCamera::disableUserClipPlane()
mPlaneCount = 6;
}
-void LLCamera::setView(F32 field_of_view)
+void LLCamera::setView(F32 vertical_fov_rads)
{
- mView = field_of_view;
- if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; }
- else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; }
+ mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW);
calculateFrustumPlanes();
}
@@ -110,27 +110,21 @@ void LLCamera::setViewHeightInPixels(S32 height)
void LLCamera::setAspect(F32 aspect_ratio)
{
- mAspect = aspect_ratio;
- if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; }
- else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; }
+ mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
calculateFrustumPlanes();
}
void LLCamera::setNear(F32 near_plane)
{
- mNearPlane = near_plane;
- if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; }
- else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; }
+ mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
calculateFrustumPlanes();
}
void LLCamera::setFar(F32 far_plane)
{
- mFarPlane = far_plane;
- if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; }
- else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; }
+ mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE);
calculateFrustumPlanes();
}
@@ -180,28 +174,99 @@ S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius)
U8 mask = 0;
S32 result = 2;
- for (U32 i = 0; i < mPlaneCount; i++)
- {
- mask = mAgentPlanes[i].mask;
- LLPlane p = mAgentPlanes[i].p;
- LLVector3 n = LLVector3(p);
- float d = p.mV[3];
- LLVector3 rscale = radius.scaledVec(scaler[mask]);
-
- LLVector3 minp = center - rscale;
- LLVector3 maxp = center + rscale;
+ /*if (mFrustumCornerDist > 0.f && radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
+ { //box is larger than frustum, check frustum quads against box planes
- if (n * minp > -d)
+ static const LLVector3 dir[] =
{
- return 0;
+ LLVector3(1, 0, 0),
+ LLVector3(-1, 0, 0),
+ LLVector3(0, 1, 0),
+ LLVector3(0, -1, 0),
+ LLVector3(0, 0, 1),
+ LLVector3(0, 0, -1)
+ };
+
+ U32 quads[] =
+ {
+ 0, 1, 2, 3,
+ 0, 1, 5, 4,
+ 2, 3, 7, 6,
+ 3, 0, 7, 4,
+ 1, 2, 6, 4,
+ 4, 5, 6, 7
+ };
+
+ result = 0;
+
+ BOOL total_inside = TRUE;
+ for (U32 i = 0; i < 6; i++)
+ {
+ LLVector3 p = center + radius.scaledVec(dir[i]);
+ F32 d = -p*dir[i];
+
+ for (U32 j = 0; j < 6; j++)
+ { //for each quad
+ F32 dist = mAgentFrustum[quads[j*4+0]]*dir[i] + d;
+ if (dist > 0)
+ { //at least one frustum point is outside the AABB
+ total_inside = FALSE;
+ for (U32 k = 1; k < 4; k++)
+ { //for each other point on quad
+ if ( mAgentFrustum[quads[j*4+k]]*dir[i]+d <= 0.f)
+ { //quad is straddling some plane of AABB
+ return 1;
+ }
+ }
+ }
+ else
+ {
+ for (U32 k = 1; k < 4; k++)
+ {
+ if (mAgentFrustum[quads[j*4+k]]*dir[i]+d > 0.f)
+ {
+ return 1;
+ }
+ }
+ }
+ }
}
-
- if (n * maxp > -d)
+
+ if (total_inside)
{
result = 1;
}
}
+ else*/
+ {
+ for (U32 i = 0; i < mPlaneCount; i++)
+ {
+ mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
+ LLPlane p = mAgentPlanes[i].p;
+ LLVector3 n = LLVector3(p);
+ float d = p.mV[3];
+ LLVector3 rscale = radius.scaledVec(scaler[mask]);
+
+ LLVector3 minp = center - rscale;
+ LLVector3 maxp = center + rscale;
+
+ if (n * minp > -d)
+ {
+ return 0;
+ }
+
+ if (n * maxp > -d)
+ {
+ result = 1;
+ }
+ }
+ }
+
return result;
}
@@ -229,6 +294,10 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& r
}
mask = mAgentPlanes[i].mask;
+ if (mask == 0xff)
+ {
+ continue;
+ }
LLPlane p = mAgentPlanes[i].p;
LLVector3 n = LLVector3(p);
float d = p.mV[3];
@@ -372,6 +441,11 @@ int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius)
int res = 2;
for (int i = 0; i < 6; i++)
{
+ if (mAgentPlanes[i].mask == 0xff)
+ {
+ continue;
+ }
+
float d = mAgentPlanes[i].p.dist(sphere_center);
if (d > radius)
@@ -557,9 +631,19 @@ U8 LLCamera::calcPlaneMask(const LLPlane& plane)
return mask;
}
-void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
+void LLCamera::ignoreAgentFrustumPlane(S32 idx)
{
+ if (idx < 0 || idx > (S32) mPlaneCount)
+ {
+ return;
+ }
+
+ mAgentPlanes[idx].mask = 0xff;
+ mAgentPlanes[idx].p.clearVec();
+}
+void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
+{
for (int i = 0; i < 8; i++)
{
mAgentFrustum[i] = frust[i];
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 82c712e5e7..922d6f9fac 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -2,30 +2,25 @@
* @file llcamera.h
* @brief Header file for the LLCamera class.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -42,17 +37,19 @@ const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
const F32 DEFAULT_NEAR_PLANE = 0.25f;
const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions
-const F32 MAX_FIELD_OF_VIEW = F_PI;
const F32 MAX_ASPECT_RATIO = 50.0f;
const F32 MAX_NEAR_PLANE = 10.f;
const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
const F32 MAX_FAR_CLIP = 512.0f;
-const F32 MIN_FIELD_OF_VIEW = 0.1f;
const F32 MIN_ASPECT_RATIO = 0.02f;
const F32 MIN_NEAR_PLANE = 0.1f;
const F32 MIN_FAR_PLANE = 0.2f;
+// Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio.
+static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
+static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
+
static const LLVector3 X_AXIS(1.f,0.f,0.f);
static const LLVector3 Y_AXIS(0.f,1.f,0.f);
static const LLVector3 Z_AXIS(0.f,0.f,1.f);
@@ -90,6 +87,17 @@ public:
PLANE_TOP_MASK = (1<<PLANE_TOP),
PLANE_ALL_MASK = 0xf
};
+
+ enum
+ {
+ AGENT_PLANE_LEFT = 0,
+ AGENT_PLANE_RIGHT,
+ AGENT_PLANE_NEAR,
+ AGENT_PLANE_BOTTOM,
+ AGENT_PLANE_TOP,
+ AGENT_PLANE_FAR,
+ };
+
enum {
HORIZ_PLANE_LEFT = 0,
HORIZ_PLANE_RIGHT = 1,
@@ -101,7 +109,7 @@ public:
HORIZ_PLANE_ALL_MASK = 0x3
};
-protected:
+private:
F32 mView; // angle between top and bottom frustum planes in radians.
F32 mAspect; // width/height
S32 mViewHeightInPixels; // for ViewHeightInPixels() only
@@ -117,27 +125,29 @@ protected:
struct frustum_plane
{
- frustum_plane() : mask(0) {}
+ frustum_plane() : mask(0) {}
LLPlane p;
U8 mask;
};
frustum_plane mAgentPlanes[7]; //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
-
+
U32 mPlaneCount; //defaults to 6, if setUserClipPlane is called, uses user supplied clip plane in
LLVector3 mWorldPlanePos; // Position of World Planes (may be offset from camera)
public:
LLVector3 mAgentFrustum[8]; //8 corners of 6-plane frustum
F32 mFrustumCornerDist; //distance to corner of frustum against far clip plane
-
+ LLPlane getAgentPlane(U32 idx) { return mAgentPlanes[idx].p; }
+
public:
LLCamera();
- LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
+ LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
+ virtual ~LLCamera(){} // no-op virtual destructor
void setUserClipPlane(LLPlane plane);
void disableUserClipPlane();
U8 calcPlaneMask(const LLPlane& plane);
- void setView(F32 new_view);
+ virtual void setView(F32 vertical_fov_rads);
void setViewHeightInPixels(S32 height);
void setAspect(F32 new_aspect);
void setNear(F32 new_near);
@@ -148,6 +158,11 @@ public:
F32 getAspect() const { return mAspect; } // width / height
F32 getNear() const { return mNearPlane; } // meters
F32 getFar() const { return mFarPlane; } // meters
+
+ // The values returned by the min/max view getters depend upon the aspect ratio
+ // at the time they are called and therefore should not be cached.
+ F32 getMinView() const;
+ F32 getMaxView() const;
F32 getYaw() const
{
@@ -170,6 +185,8 @@ public:
// Return number of bytes copied.
size_t readFrustumFromBuffer(const char *buffer);
void calcAgentFrustumPlanes(LLVector3* frust);
+ void ignoreAgentFrustumPlane(S32 idx);
+
// Returns 1 if partly in, 2 if fully in.
// NOTE: 'center' is in absolute frame.
S32 sphereInFrustumOld(const LLVector3 &center, const F32 radius) const;
diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h
index 91fd5070fa..706ad92787 100644
--- a/indra/llmath/llcoord.h
+++ b/indra/llmath/llcoord.h
@@ -1,30 +1,25 @@
/**
* @file llcoord.h
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -58,8 +53,11 @@ public:
{}
LLCoordGL(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordGL& other) const { return !(*this == other); }
};
+//bool operator ==(const LLCoordGL& a, const LLCoordGL& b);
// Window coords include things like window borders,
// menu regions, etc.
@@ -70,6 +68,8 @@ public:
{}
LLCoordWindow(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordWindow& other) const { return !(*this == other); }
};
@@ -81,6 +81,8 @@ public:
{}
LLCoordScreen(S32 x, S32 y) : LLCoord(x, y)
{}
+ bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordScreen& other) const { return !(*this == other); }
};
class LLCoordFont : public LLCoord
@@ -95,6 +97,8 @@ public:
void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; }
void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; }
+ bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; }
+ bool operator!=(const LLCoordFont& other) const { return !(*this == other); }
};
diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp
index f108454731..7dd8e43185 100644
--- a/indra/llmath/llcoordframe.cpp
+++ b/indra/llmath/llcoordframe.cpp
@@ -2,30 +2,25 @@
* @file llcoordframe.cpp
* @brief LLCoordFrame class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llcoordframe.h b/indra/llmath/llcoordframe.h
index 95deba6134..909adf260c 100644
--- a/indra/llmath/llcoordframe.h
+++ b/indra/llmath/llcoordframe.h
@@ -2,30 +2,25 @@
* @file llcoordframe.h
* @brief LLCoordFrame class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llinterp.h b/indra/llmath/llinterp.h
index 0ad91130a1..5187646179 100644
--- a/indra/llmath/llinterp.h
+++ b/indra/llmath/llinterp.h
@@ -1,36 +1,38 @@
/**
* @file llinterp.h
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLINTERP_H
#define LL_LLINTERP_H
+#if defined(LL_WINDOWS)
+// macro definitions for common math constants (e.g. M_PI) are declared under the _USE_MATH_DEFINES
+// on Windows system.
+// So, let's define _USE_MATH_DEFINES before including math.h
+ #define _USE_MATH_DEFINES
+#endif
+
#include "math.h"
// Class from which different types of interpolators can be derived
@@ -46,7 +48,7 @@ template <typename Type>
class LLInterp
{
public:
- LLInterp();
+ LLInterp();
virtual ~LLInterp() {}
virtual void start();
@@ -143,6 +145,7 @@ protected:
template <typename Type>
LLInterp<Type>::LLInterp()
+: mStartVal(Type()), mEndVal(Type()), mCurVal(Type())
{
mStartTime = 0.f;
mEndTime = 1.f;
diff --git a/indra/llmath/llline.cpp b/indra/llmath/llline.cpp
index b62631072b..ef10d1e7fa 100644
--- a/indra/llmath/llline.cpp
+++ b/indra/llmath/llline.cpp
@@ -3,10 +3,30 @@
* @author Andrew Meadows
* @brief Simple line class that can compute nearest approach between two lines
*
- * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
- * $License$
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llline.h"
#include "llrand.h"
diff --git a/indra/llmath/llline.h b/indra/llmath/llline.h
index cdae3fc1fe..e1cbc1323e 100644
--- a/indra/llmath/llline.h
+++ b/indra/llmath/llline.h
@@ -4,8 +4,26 @@
* @author Andrew Meadows
* @brief Simple line for computing nearest approach between two infinite lines
*
- * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
- * $License$
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
*/
#ifndef LL_LINE_H
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index bf98801508..798f1154d0 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -2,30 +2,25 @@
* @file llmath.h
* @brief Useful math constants and macros.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,7 +29,14 @@
#include <cmath>
#include <cstdlib>
+#include <complex>
#include "lldefs.h"
+//#include "llstl.h" // *TODO: Remove when LLString is gone
+//#include "llstring.h" // *TODO: Remove when LLString is gone
+// lltut.h uses is_approx_equal_fraction(). This was moved to its own header
+// file in llcommon so we can use lltut.h for llcommon tests without making
+// llcommon depend on llmath.
+#include "is_approx_equal_fraction.h"
// work around for Windows & older gcc non-standard function names.
#if LL_WINDOWS
@@ -53,11 +55,11 @@
#endif
// Single Precision Floating Point Routines
-#ifndef fsqrtf
-#define fsqrtf(x) ((F32)sqrt((F64)(x)))
-#endif
#ifndef sqrtf
-#define sqrtf(x) ((F32)sqrt((F64)(x)))
+#define sqrtf(x) ((F32)sqrt((F64)(x)))
+#endif
+#ifndef fsqrtf
+#define fsqrtf(x) sqrtf(x)
#endif
#ifndef cosf
@@ -70,11 +72,14 @@
#define tanf(x) ((F32)tan((F64)(x)))
#endif
#ifndef acosf
-#define acosf(x) ((F32)acos((F64)(x)))
+#define acosf(x) ((F32)acos((F64)(x)))
#endif
#ifndef powf
-#define powf(x,y) ((F32)pow((F64)(x),(F64)(y)))
+#define powf(x,y) ((F32)pow((F64)(x),(F64)(y)))
+#endif
+#ifndef expf
+#define expf(x) ((F32)exp((F64)(x)))
#endif
const F32 GRAVITY = -9.8f;
@@ -83,6 +88,8 @@ const F32 GRAVITY = -9.8f;
const F32 F_PI = 3.1415926535897932384626433832795f;
const F32 F_TWO_PI = 6.283185307179586476925286766559f;
const F32 F_PI_BY_TWO = 1.5707963267948966192313216916398f;
+const F32 F_SQRT_TWO_PI = 2.506628274631000502415765284811f;
+const F32 F_E = 2.71828182845904523536f;
const F32 F_SQRT2 = 1.4142135623730950488016887242097f;
const F32 F_SQRT3 = 1.73205080756888288657986402541f;
const F32 OO_SQRT2 = 0.7071067811865475244008443621049f;
@@ -92,12 +99,39 @@ const F32 F_APPROXIMATELY_ZERO = 0.00001f;
const F32 F_LN2 = 0.69314718056f;
const F32 OO_LN2 = 1.4426950408889634073599246810019f;
+const F32 F_ALMOST_ZERO = 0.0001f;
+const F32 F_ALMOST_ONE = 1.0f - F_ALMOST_ZERO;
+
// BUG: Eliminate in favor of F_APPROXIMATELY_ZERO above?
const F32 FP_MAG_THRESHOLD = 0.0000001f;
// TODO: Replace with logic like is_approx_equal
inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
+// These functions work by interpreting sign+exp+mantissa as an unsigned
+// integer.
+// For example:
+// x = <sign>1 <exponent>00000010 <mantissa>00000000000000000000000
+// y = <sign>1 <exponent>00000001 <mantissa>11111111111111111111111
+//
+// interpreted as ints =
+// x = 10000001000000000000000000000000
+// y = 10000000111111111111111111111111
+// which is clearly a different of 1 in the least significant bit
+// Values with the same exponent can be trivially shown to work.
+//
+// WARNING: Denormals of opposite sign do not work
+// x = <sign>1 <exponent>00000000 <mantissa>00000000000000000000001
+// y = <sign>0 <exponent>00000000 <mantissa>00000000000000000000001
+// Although these values differ by 2 in the LSB, the sign bit makes
+// the int comparison fail.
+//
+// WARNING: NaNs can compare equal
+// There is no special treatment of exceptional values like NaNs
+//
+// WARNING: Infinity is comparable with F32_MAX and negative
+// infinity is comparable with F32_MIN
+
inline BOOL is_approx_equal(F32 x, F32 y)
{
const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02;
@@ -110,48 +144,6 @@ inline BOOL is_approx_equal(F64 x, F64 y)
return (std::abs((S32) ((U64&)x - (U64&)y) ) < COMPARE_MANTISSA_UP_TO_BIT);
}
-inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits)
-{
- BOOL ret = TRUE;
- F32 diff = (F32) fabs(x - y);
-
- S32 diffInt = (S32) diff;
- S32 diffFracTolerance = (S32) ((diff - (F32) diffInt) * (1 << frac_bits));
-
- // if integer portion is not equal, not enough bits were used for packing
- // so error out since either the use case is not correct OR there is
- // an issue with pack/unpack. should fail in either case.
- // for decimal portion, make sure that the delta is no more than 1
- // based on the number of bits used for packing decimal portion.
- if (diffInt != 0 || diffFracTolerance > 1)
- {
- ret = FALSE;
- }
-
- return ret;
-}
-
-inline BOOL is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits)
-{
- BOOL ret = TRUE;
- F64 diff = (F64) fabs(x - y);
-
- S32 diffInt = (S32) diff;
- S32 diffFracTolerance = (S32) ((diff - (F64) diffInt) * (1 << frac_bits));
-
- // if integer portion is not equal, not enough bits were used for packing
- // so error out since either the use case is not correct OR there is
- // an issue with pack/unpack. should fail in either case.
- // for decimal portion, make sure that the delta is no more than 1
- // based on the number of bits used for packing decimal portion.
- if (diffInt != 0 || diffFracTolerance > 1)
- {
- ret = FALSE;
- }
-
- return ret;
-}
-
inline S32 llabs(const S32 a)
{
return S32(std::labs(a));
@@ -208,7 +200,7 @@ inline S32 llfloor( F32 f )
}
return result;
#else
- return (S32)floor(f);
+ return (S32)floorf(f);
#endif
}
@@ -472,8 +464,8 @@ inline F32 llsimple_angle(F32 angle)
return angle;
}
-//calculate the nearesr power of two number for val, bounded by max_power_two
-inline U32 get_nearest_power_two(U32 val, U32 max_power_two)
+//SDK - Renamed this to get_lower_power_two, since this is what this actually does.
+inline U32 get_lower_power_two(U32 val, U32 max_power_two)
{
if(!max_power_two)
{
@@ -488,4 +480,40 @@ inline U32 get_nearest_power_two(U32 val, U32 max_power_two)
return max_power_two ;
}
+
+// calculate next highest power of two, limited by max_power_two
+// This is taken from a brilliant little code snipped on http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html
+// Basically we convert the binary to a solid string of 1's with the same
+// number of digits, then add one. We subtract 1 initially to handle
+// the case where the number passed in is actually a power of two.
+// WARNING: this only works with 32 bit ints.
+inline U32 get_next_power_two(U32 val, U32 max_power_two)
+{
+ if(!max_power_two)
+ {
+ max_power_two = 1 << 31 ;
+ }
+
+ if(val >= max_power_two)
+ {
+ return max_power_two;
+ }
+
+ val--;
+ val = (val >> 1) | val;
+ val = (val >> 2) | val;
+ val = (val >> 4) | val;
+ val = (val >> 8) | val;
+ val = (val >> 16) | val;
+ val++;
+
+ return val;
+}
+
+//get the gaussian value given the linear distance from axis x and guassian value o
+inline F32 llgaussian(F32 x, F32 o)
+{
+ return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o));
+}
+
#endif
diff --git a/indra/llmath/llmodularmath.cpp b/indra/llmath/llmodularmath.cpp
new file mode 100644
index 0000000000..cdc20028bf
--- /dev/null
+++ b/indra/llmath/llmodularmath.cpp
@@ -0,0 +1,30 @@
+/**
+ * @file llmodularmath.cpp
+ * @brief LLModularMath class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
+#include "llmodularmath.h"
diff --git a/indra/llmath/llmodularmath.h b/indra/llmath/llmodularmath.h
new file mode 100644
index 0000000000..0d4d28fadc
--- /dev/null
+++ b/indra/llmath/llmodularmath.h
@@ -0,0 +1,52 @@
+/**
+ * @file llmodularmath.h
+ * @brief Useful modular math functions.
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLMODULARMATH_H
+#define LLMODULARMATH_H
+
+namespace LLModularMath
+{
+ // Return difference between lhs and rhs
+ // treating the U32 operands and result
+ // as unsigned values of given width.
+ template<int width>
+ inline U32 subtract(U32 lhs, U32 rhs)
+ {
+ // Generate a bit mask which will truncate
+ // unsigned values to given width at compile time.
+ const U32 mask = (1 << width) - 1;
+
+ // Operands are unsigned, so modular
+ // arithmetic applies. If lhs < rhs,
+ // difference will wrap in to lower
+ // bits of result, which is then masked
+ // to give a value that can be represented
+ // by an unsigned value of width bits.
+ return mask & (lhs - rhs);
+ }
+}
+
+#endif
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index 25b7100eb7..90d4d742c9 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -2,30 +2,25 @@
* @file lloctree.h
* @brief Octree declaration.
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,9 +33,9 @@
#include <set>
#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
-#define OCT_ERRS LL_WARNS("OctreeErrors")
-#else
#define OCT_ERRS LL_ERRS("OctreeErrors")
+#else
+#define OCT_ERRS LL_WARNS("OctreeErrors")
#endif
#define LL_OCTREE_PARANOIA_CHECK 0
@@ -64,11 +59,10 @@ public:
};
template <class T>
-class LLOctreeTraveler : public LLTreeTraveler<T>
+class LLOctreeTraveler
{
public:
- virtual void traverse(const LLTreeNode<T>* node);
- virtual void visit(const LLTreeNode<T>* state) { }
+ virtual void traverse(const LLOctreeNode<T>* node);
virtual void visit(const LLOctreeNode<T>* branch) = 0;
};
@@ -183,7 +177,6 @@ public:
{
mMax.mdV[i] = mCenter.mdV[i] + mSize.mdV[i];
mMin.mdV[i] = mCenter.mdV[i] - mSize.mdV[i];
- mCenter.mdV[i] = mCenter.mdV[i];
}
}
@@ -330,6 +323,16 @@ public:
//push center in direction of data
LLOctreeNode<T>::pushCenter(center, size, data);
+ // handle case where floating point number gets too small
+ if( llabs(center.mdV[0] - getCenter().mdV[0]) < F_APPROXIMATELY_ZERO &&
+ llabs(center.mdV[1] - getCenter().mdV[1]) < F_APPROXIMATELY_ZERO &&
+ llabs(center.mdV[2] - getCenter().mdV[2]) < F_APPROXIMATELY_ZERO)
+ {
+ mData.insert(data);
+ BaseType::insert(data);
+ return true;
+ }
+
#if LL_OCTREE_PARANOIA_CHECK
if (getChildCount() == 8)
{
@@ -689,19 +692,16 @@ public:
}
};
-
//========================
// LLOctreeTraveler
//========================
template <class T>
-void LLOctreeTraveler<T>::traverse(const LLTreeNode<T>* tree_node)
+void LLOctreeTraveler<T>::traverse(const LLOctreeNode<T>* node)
{
- const LLOctreeNode<T>* node = (const LLOctreeNode<T>*) tree_node;
node->accept(this);
for (U32 i = 0; i < node->getChildCount(); i++)
{
traverse(node->getChild(i));
}
}
-
#endif
diff --git a/indra/llmath/llperlin.cpp b/indra/llmath/llperlin.cpp
index 4dcc7abc1a..e1da2bf92b 100644
--- a/indra/llmath/llperlin.cpp
+++ b/indra/llmath/llperlin.cpp
@@ -1,30 +1,25 @@
/**
* @file llperlin.cpp
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llperlin.h b/indra/llmath/llperlin.h
index 63daaa6d5c..40cf19d1ec 100644
--- a/indra/llmath/llperlin.h
+++ b/indra/llmath/llperlin.h
@@ -1,30 +1,25 @@
/**
* @file llperlin.h
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h
index c1fb7d885a..443f3f46b9 100644
--- a/indra/llmath/llplane.h
+++ b/indra/llmath/llplane.h
@@ -1,30 +1,25 @@
/**
* @file llplane.h
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llquantize.h b/indra/llmath/llquantize.h
index 817c4c356c..7f56ff3448 100644
--- a/indra/llmath/llquantize.h
+++ b/indra/llmath/llquantize.h
@@ -3,30 +3,25 @@
* @brief useful routines for quantizing floats to various length ints
* and back out again
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index 7711d0881d..a51f11072c 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -2,30 +2,25 @@
* @file llquaternion.cpp
* @brief LLQuaternion class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -120,7 +115,7 @@ void LLQuaternion::quantize16(F32 lower, F32 upper)
mQ[VZ] = z;
mQ[VS] = s;
- normQuat();
+ normalize();
}
void LLQuaternion::quantize8(F32 lower, F32 upper)
@@ -130,7 +125,7 @@ void LLQuaternion::quantize8(F32 lower, F32 upper)
mQ[VZ] = U8_to_F32(F32_to_U8_ROUND(mQ[VZ], lower, upper), lower, upper);
mQ[VS] = U8_to_F32(F32_to_U8_ROUND(mQ[VS], lower, upper), lower, upper);
- normQuat();
+ normalize();
}
// LLVector3 Magnitude and Normalization Functions
@@ -345,7 +340,7 @@ const LLQuaternion& LLQuaternion::setQuat(const LLMatrix4 &mat)
// mQ[VZ] = (F32)(cosX*cosY*sinZ - sinX*sinY*cosZ);
//#endif
//
-// normQuat();
+// normalize();
// return (*this);
}
@@ -937,15 +932,15 @@ void LLQuaternion::unpackFromVector3( const LLVector3& vec )
}
}
-BOOL LLQuaternion::parseQuat(const char* buf, LLQuaternion* value)
+BOOL LLQuaternion::parseQuat(const std::string& buf, LLQuaternion* value)
{
- if( buf == NULL || buf[0] == '\0' || value == NULL)
+ if( buf.empty() || value == NULL)
{
return FALSE;
}
LLQuaternion quat;
- S32 count = sscanf( buf, "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 );
+ S32 count = sscanf( buf.c_str(), "%f %f %f %f", quat.mQ + 0, quat.mQ + 1, quat.mQ + 2, quat.mQ + 3 );
if( 4 == count )
{
value->set( quat );
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index a088d70674..26da14ae20 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -2,30 +2,25 @@
* @file llquaternion.h
* @brief LLQuaternion class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -158,7 +153,7 @@ public:
friend const char *OrderToString( const Order order );
friend Order StringToOrder( const char *str );
- static BOOL parseQuat(const char* buf, LLQuaternion* value);
+ static BOOL parseQuat(const std::string& buf, LLQuaternion* value);
// For debugging, only
//static U32 mMultCount;
@@ -468,20 +463,30 @@ inline const LLQuaternion& operator*=(LLQuaternion &a, const LLQuaternion &b)
return a;
}
+const F32 ONE_PART_IN_A_MILLION = 0.000001f;
+
inline F32 LLQuaternion::normalize()
{
F32 mag = sqrtf(mQ[VX]*mQ[VX] + mQ[VY]*mQ[VY] + mQ[VZ]*mQ[VZ] + mQ[VS]*mQ[VS]);
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ // Floating point error can prevent some quaternions from achieving
+ // exact unity length. When trying to renormalize such quaternions we
+ // can oscillate between multiple quantized states. To prevent such
+ // drifts we only renomalize if the length is far enough from unity.
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
+ // we were given a very bad quaternion so we set it to identity
mQ[VX] = 0.f;
mQ[VY] = 0.f;
mQ[VZ] = 0.f;
@@ -498,11 +503,15 @@ inline F32 LLQuaternion::normQuat()
if (mag > FP_MAG_THRESHOLD)
{
- F32 oomag = 1.f/mag;
- mQ[VX] *= oomag;
- mQ[VY] *= oomag;
- mQ[VZ] *= oomag;
- mQ[VS] *= oomag;
+ if (fabs(1.f - mag) > ONE_PART_IN_A_MILLION)
+ {
+ // only renormalize if length not close enough to 1.0 already
+ F32 oomag = 1.f/mag;
+ mQ[VX] *= oomag;
+ mQ[VY] *= oomag;
+ mQ[VZ] *= oomag;
+ mQ[VS] *= oomag;
+ }
}
else
{
diff --git a/indra/llmath/llrect.cpp b/indra/llmath/llrect.cpp
index f7825fa0d6..4083c99768 100644
--- a/indra/llmath/llrect.cpp
+++ b/indra/llmath/llrect.cpp
@@ -1,33 +1,30 @@
/**
* @file llrect.cpp
+ * @brief LLRect class implementation
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
+// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
#include "llrect.h"
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index 17fa981c7c..c51e0e0ae6 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -2,30 +2,25 @@
* @file llrect.h
* @brief A rectangle in GL coordinates, with bottom,left = 0,0
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,6 +36,7 @@
template <class Type> class LLRectBase
{
public:
+ typedef Type tCoordType;
Type mLeft;
Type mTop;
Type mRight;
@@ -63,23 +59,17 @@ public:
mLeft(left), mTop(top), mRight(right), mBottom(bottom)
{}
- LLRectBase(const LLSD& sd)
+ explicit LLRectBase(const LLSD& sd)
{
setValue(sd);
}
- const LLRectBase& operator=(const LLSD& sd)
- {
- setValue(sd);
- return *this;
- }
-
void setValue(const LLSD& sd)
{
- mLeft = sd[0].asInteger();
- mTop = sd[1].asInteger();
- mRight = sd[2].asInteger();
- mBottom = sd[3].asInteger();
+ mLeft = (Type)sd[0].asInteger();
+ mTop = (Type)sd[1].asInteger();
+ mRight = (Type)sd[2].asInteger();
+ mBottom = (Type)sd[3].asInteger();
}
LLSD getValue() const
@@ -146,10 +136,20 @@ public:
// Note: Does NOT follow GL_QUAD conventions: the top and right edges ARE considered part of the rect
// returns TRUE if any part of rect is is inside this LLRect
- BOOL rectInRect(const LLRectBase* rect) const
+ BOOL overlaps(const LLRectBase& rect) const
+ {
+ return !(mLeft > rect.mRight
+ || mRight < rect.mLeft
+ || mBottom > rect.mTop
+ || mTop < rect.mBottom);
+ }
+
+ BOOL contains(const LLRectBase& rect) const
{
- return mLeft <= rect->mRight && rect->mLeft <= mRight &&
- mBottom <= rect->mTop && rect->mBottom <= mTop ;
+ return mLeft <= rect.mLeft
+ && mRight >= rect.mRight
+ && mBottom <= rect.mBottom
+ && mTop >= rect.mTop;
}
LLRectBase& set(Type left, Type top, Type right, Type bottom)
@@ -183,10 +183,11 @@ public:
LLRectBase& setCenterAndSize(Type x, Type y, Type width, Type height)
{
+ // width and height could be odd, so favor top, right with extra pixel
mLeft = x - width/2;
- mTop = y + height/2;
- mRight = x + width/2;
mBottom = y - height/2;
+ mTop = mBottom + height;
+ mRight = mLeft + width;
return *this;
}
@@ -222,26 +223,30 @@ public:
return *this;
}
- bool isNull() const
+ bool isValid() const
+ {
+ return mLeft <= mRight && mBottom <= mTop;
+ }
+
+ bool isEmpty() const
{
return mLeft == mRight || mBottom == mTop;
}
- bool notNull() const
+ bool notEmpty() const
{
- return !isNull();
+ return !isEmpty();
}
- LLRectBase& unionWith(const LLRectBase &other)
+ void unionWith(const LLRectBase &other)
{
mLeft = llmin(mLeft, other.mLeft);
mRight = llmax(mRight, other.mRight);
mBottom = llmin(mBottom, other.mBottom);
mTop = llmax(mTop, other.mTop);
- return *this;
}
- LLRectBase& intersectWith(const LLRectBase &other)
+ void intersectWith(const LLRectBase &other)
{
mLeft = llmax(mLeft, other.mLeft);
mRight = llmin(mRight, other.mRight);
@@ -255,7 +260,6 @@ public:
{
mBottom = mTop;
}
- return *this;
}
friend std::ostream &operator<<(std::ostream &s, const LLRectBase &rect)
@@ -264,8 +268,8 @@ public:
<< " W " << rect.getWidth() << " H " << rect.getHeight() << " }";
return s;
}
-
- bool operator==(const LLRectBase &b)
+
+ bool operator==(const LLRectBase &b) const
{
return ((mLeft == b.mLeft) &&
(mTop == b.mTop) &&
@@ -273,7 +277,7 @@ public:
(mBottom == b.mBottom));
}
- bool operator!=(const LLRectBase &b)
+ bool operator!=(const LLRectBase &b) const
{
return ((mLeft != b.mLeft) ||
(mTop != b.mTop) ||
diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp
index 04b9d892e7..591f7fde36 100644
--- a/indra/llmath/llsdutil_math.cpp
+++ b/indra/llmath/llsdutil_math.cpp
@@ -4,36 +4,31 @@
* @date 2006-05-24
* @brief Implementation of classes, functions, etc, for using structured data.
*
- * $LicenseInfo:firstyear=2006&license=viewergpl$
- *
- * Copyright (c) 2006-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "v3math.h"
#include "v4math.h"
@@ -164,9 +159,6 @@ LLSD ll_sd_from_color4(const LLColor4& c)
LLColor4 ll_color4_from_sd(const LLSD& sd)
{
LLColor4 c;
- c.mV[0] = (F32)sd[0].asReal();
- c.mV[1] = (F32)sd[1].asReal();
- c.mV[2] = (F32)sd[2].asReal();
- c.mV[3] = (F32)sd[3].asReal();
+ c.setValue(sd);
return c;
}
diff --git a/indra/llmath/llsdutil_math.h b/indra/llmath/llsdutil_math.h
new file mode 100644
index 0000000000..0ea78cd231
--- /dev/null
+++ b/indra/llmath/llsdutil_math.h
@@ -0,0 +1,64 @@
+/**
+ * @file llsdutil_math.h
+ * @author Brad
+ * @date 2009-05-19
+ * @brief Utility classes, functions, etc, for using structured data with math classes.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDUTIL_MATH_H
+#define LL_LLSDUTIL_MATH_H
+
+class LL_COMMON_API LLSD;
+
+// vector3
+class LLVector3;
+LLSD ll_sd_from_vector3(const LLVector3& vec);
+LLVector3 ll_vector3_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector4
+class LLVector4;
+LLSD ll_sd_from_vector4(const LLVector4& vec);
+LLVector4 ll_vector4_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector3d (double)
+class LLVector3d;
+LLSD ll_sd_from_vector3d(const LLVector3d& vec);
+LLVector3d ll_vector3d_from_sd(const LLSD& sd, S32 start_index = 0);
+
+// vector2
+class LLVector2;
+LLSD ll_sd_from_vector2(const LLVector2& vec);
+LLVector2 ll_vector2_from_sd(const LLSD& sd);
+
+// Quaternion
+class LLQuaternion;
+LLSD ll_sd_from_quaternion(const LLQuaternion& quat);
+LLQuaternion ll_quaternion_from_sd(const LLSD& sd);
+
+// color4
+class LLColor4;
+LLSD ll_sd_from_color4(const LLColor4& c);
+LLColor4 ll_color4_from_sd(const LLSD& sd);
+
+#endif // LL_LLSDUTIL_MATH_H
diff --git a/indra/llmath/llsphere.cpp b/indra/llmath/llsphere.cpp
index 3428dc1487..740047b93a 100644
--- a/indra/llmath/llsphere.cpp
+++ b/indra/llmath/llsphere.cpp
@@ -3,10 +3,30 @@
* @author Andrew Meadows
* @brief Simple line class that can compute nearest approach between two lines
*
- * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
- * $License$
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llsphere.h"
LLSphere::LLSphere()
diff --git a/indra/llmath/llsphere.h b/indra/llmath/llsphere.h
index 709406eb5e..7c60a11406 100644
--- a/indra/llmath/llsphere.h
+++ b/indra/llmath/llsphere.h
@@ -4,8 +4,26 @@
* @author Andrew Meadows
* @brief Simple sphere implementation for basic geometric operations
*
- * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
- * $License$
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
*/
#ifndef LL_SPHERE_H
diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h
index 6685915bcf..a462d1659e 100644
--- a/indra/llmath/lltreenode.h
+++ b/indra/llmath/lltreenode.h
@@ -1,30 +1,25 @@
/**
* @file lltreenode.h
*
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llv4math.h b/indra/llmath/llv4math.h
index 9ad689b577..5f403ba526 100644
--- a/indra/llmath/llv4math.h
+++ b/indra/llmath/llv4math.h
@@ -2,30 +2,25 @@
* @file llv4math.h
* @brief LLV4* class header file - vector processor enabled math
*
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llv4matrix3.h b/indra/llmath/llv4matrix3.h
index bed09d0793..270f5d7dae 100644
--- a/indra/llmath/llv4matrix3.h
+++ b/indra/llmath/llv4matrix3.h
@@ -2,30 +2,25 @@
* @file llviewerjointmesh.cpp
* @brief LLV4* class header file - vector processor enabled math
*
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llv4matrix4.h b/indra/llmath/llv4matrix4.h
index 8ffb9d31f2..2eb49d9294 100644
--- a/indra/llmath/llv4matrix4.h
+++ b/indra/llmath/llv4matrix4.h
@@ -2,30 +2,25 @@
* @file llviewerjointmesh.cpp
* @brief LLV4* class header file - vector processor enabled math
*
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llv4vector3.h b/indra/llmath/llv4vector3.h
index e1769087a3..a340d53f5a 100644
--- a/indra/llmath/llv4vector3.h
+++ b/indra/llmath/llv4vector3.h
@@ -2,30 +2,25 @@
* @file llviewerjointmesh.cpp
* @brief LLV4* class header file - vector processor enabled math
*
- * $LicenseInfo:firstyear=2007&license=viewergpl$
- *
- * Copyright (c) 2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index ecc4b09d10..14e1ca8d43 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1,30 +1,25 @@
/**
* @file llvolume.cpp
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -82,12 +77,10 @@ const F32 TAPER_MAX = 1.f;
const F32 SKEW_MIN = -0.95f;
const F32 SKEW_MAX = 0.95f;
-const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square
-const S32 SCULPT_REZ_2 = 8;
-const S32 SCULPT_REZ_3 = 16;
-const S32 SCULPT_REZ_4 = 32;
-
const F32 SCULPT_MIN_AREA = 0.002f;
+const S32 SCULPT_MIN_AREA_DETAIL = 1;
+
+#define GEN_TRI_STRIP 0
BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)
{
@@ -104,46 +97,128 @@ BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLV
}
}
-// intersect test between triangle pt1,pt2,pt3 and line from linept to linept+vect
-//returns TRUE if intersecting and moves linept to the point of intersection
-BOOL LLTriangleLineSegmentIntersect( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, LLVector3& linept, const LLVector3& vect)
+BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
+{
+ float fAWdU[3];
+ LLVector3 dir;
+ LLVector3 diff;
+
+ for (U32 i = 0; i < 3; i++)
+ {
+ dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]);
+ diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i];
+ fAWdU[i] = fabsf(dir.mV[i]);
+ if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false;
+ }
+
+ float f;
+ f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false;
+ f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false;
+ f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false;
+
+ return true;
+}
+
+
+// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir.
+// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b,
+// and returns the intersection point along dir in intersection_t.
+
+// Moller-Trumbore algorithm
+BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
+ F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided)
{
- LLVector3 V1 = pt2-pt1;
- LLVector3 V2 = pt3-pt2;
+ F32 u, v, t;
- LLVector3 norm = V1 % V2;
+ /* find vectors for two edges sharing vert0 */
+ LLVector3 edge1 = vert1 - vert0;
+
+ LLVector3 edge2 = vert2 - vert0;;
+
+ /* begin calculating determinant - also used to calculate U parameter */
+ LLVector3 pvec = dir % edge2;
- F32 dotprod = norm * vect;
+ /* if determinant is near zero, ray lies in plane of triangle */
+ F32 det = edge1 * pvec;
- if(dotprod < 0)
+ if (!two_sided)
{
- //Find point of intersect to triangle plane.
- //find t to intersect point
- F32 t = -(norm * (linept-pt1))/dotprod;
+ if (det < F_APPROXIMATELY_ZERO)
+ {
+ return FALSE;
+ }
- // if ds is neg line started past triangle so can't hit triangle.
- if (t > 0)
+ /* calculate distance from vert0 to ray origin */
+ LLVector3 tvec = orig - vert0;
+
+ /* calculate U parameter and test bounds */
+ u = tvec * pvec;
+
+ if (u < 0.f || u > det)
{
return FALSE;
}
- LLVector3 pt_int = linept + (vect*t);
+ /* prepare to test V parameter */
+ LLVector3 qvec = tvec % edge1;
- if(check_same_clock_dir(pt1, pt2, pt_int, norm))
+ /* calculate V parameter and test bounds */
+ v = dir * qvec;
+ if (v < 0.f || u + v > det)
{
- if(check_same_clock_dir(pt2, pt3, pt_int, norm))
+ return FALSE;
+ }
+
+ /* calculate t, scale parameters, ray intersects triangle */
+ t = edge2 * qvec;
+ F32 inv_det = 1.0 / det;
+ t *= inv_det;
+ u *= inv_det;
+ v *= inv_det;
+ }
+
+ else // two sided
{
- if(check_same_clock_dir(pt3, pt1, pt_int, norm))
+ if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO)
{
- // answer in pt_int is insde triangle
- linept.setVec(pt_int);
- return TRUE;
+ return FALSE;
}
+ F32 inv_det = 1.0 / det;
+
+ /* calculate distance from vert0 to ray origin */
+ LLVector3 tvec = orig - vert0;
+
+ /* calculate U parameter and test bounds */
+ u = (tvec * pvec) * inv_det;
+ if (u < 0.f || u > 1.f)
+ {
+ return FALSE;
}
+
+ /* prepare to test V parameter */
+ LLVector3 qvec = tvec - edge1;
+
+ /* calculate V parameter and test bounds */
+ v = (dir * qvec) * inv_det;
+
+ if (v < 0.f || u + v > 1.f)
+ {
+ return FALSE;
}
+
+ /* calculate t, ray intersects triangle */
+ t = (edge2 * qvec) * inv_det;
}
- return FALSE;
+ if (intersection_a != NULL)
+ *intersection_a = u;
+ if (intersection_b != NULL)
+ *intersection_b = v;
+ if (intersection_t != NULL)
+ *intersection_t = t;
+
+
+ return TRUE;
}
@@ -198,9 +273,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3
F32 t, t_step, t_first, t_fraction, ang, ang_step;
LLVector3 pt1,pt2;
- mMaxX = 0.f;
- mMinX = 0.f;
-
F32 begin = params.getBegin();
F32 end = params.getEnd();
@@ -236,15 +308,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3
if (t_fraction < 0.9999f)
{
LLVector3 new_pt = lerp(pt1, pt2, t_fraction);
- F32 pt_x = new_pt.mV[VX];
- if (pt_x < mMinX)
- {
- mMinX = pt_x;
- }
- else if (pt_x > mMaxX)
- {
- mMaxX = pt_x;
- }
mProfile.push_back(new_pt);
}
@@ -254,16 +317,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3
// Iterate through all the integer steps of t.
pt1.setVec(cos(ang)*scale,sin(ang)*scale,t);
- F32 pt_x = pt1.mV[VX];
- if (pt_x < mMinX)
- {
- mMinX = pt_x;
- }
- else if (pt_x > mMaxX)
- {
- mMaxX = pt_x;
- }
-
if (mProfile.size() > 0) {
LLVector3 p = mProfile[mProfile.size()-1];
for (S32 i = 0; i < split && mProfile.size() > 0; i++) {
@@ -287,15 +340,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3
if (t_fraction > 0.0001f)
{
LLVector3 new_pt = lerp(pt1, pt2, t_fraction);
- F32 pt_x = new_pt.mV[VX];
- if (pt_x < mMinX)
- {
- mMinX = pt_x;
- }
- else if (pt_x > mMaxX)
- {
- mMaxX = pt_x;
- }
if (mProfile.size() > 0) {
LLVector3 p = mProfile[mProfile.size()-1];
@@ -472,31 +516,9 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3
}
-S32 sculpt_sides(F32 detail)
-{
-
- // detail is usually one of: 1, 1.5, 2.5, 4.0.
-
- if (detail <= 1.0)
- {
- return SCULPT_REZ_1;
- }
- if (detail <= 2.0)
- {
- return SCULPT_REZ_2;
- }
- if (detail <= 3.0)
- {
- return SCULPT_REZ_3;
- }
- else
- {
- return SCULPT_REZ_4;
- }
-}
-
-BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, BOOL is_sculpted)
+BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
+ BOOL is_sculpted, S32 sculpt_size)
{
LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -640,7 +662,7 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai
S32 sides = (S32)circle_detail;
if (is_sculpted)
- sides = sculpt_sides(detail);
+ sides = sculpt_size;
genNGon(params, sides);
@@ -1131,7 +1153,8 @@ const LLVector2 LLPathParams::getEndScale() const
return end_scale;
}
-BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted)
+BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
+ BOOL is_sculpted, S32 sculpt_size)
{
LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -1194,7 +1217,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is
S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
if (is_sculpted)
- sides = sculpt_sides(detail);
+ sides = sculpt_size;
genNGon(params, sides);
}
@@ -1259,7 +1282,8 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is
return TRUE;
}
-BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted)
+BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split,
+ BOOL is_sculpted, S32 sculpt_size)
{
LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -1624,9 +1648,13 @@ void LLPathParams::copyParams(const LLPathParams &params)
setSkew(params.getSkew());
}
+S32 profile_delete_lock = 1 ;
LLProfile::~LLProfile()
{
-
+ if(profile_delete_lock)
+ {
+ llerrs << "LLProfile should not be deleted here!" << llendl ;
+ }
}
@@ -1656,7 +1684,7 @@ LLVolume::LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL ge
mGenerateSingleFace = generate_single_face;
generate();
- if (mParams.getSculptID().isNull())
+ if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE)
{
createVolumeFaces();
}
@@ -1683,7 +1711,11 @@ LLVolume::~LLVolume()
{
sNumMeshPoints -= mMesh.size();
delete mPathp;
+
+ profile_delete_lock = 0 ;
delete mProfilep;
+ profile_delete_lock = 1 ;
+
mPathp = NULL;
mProfilep = NULL;
mVolumeFaces.clear();
@@ -1728,18 +1760,47 @@ BOOL LLVolume::generate()
mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
}
+ //********************************************************************
+ //debug info, to be removed
+ if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20))
+ {
+ llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ;
+ llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ;
+ llinfos << mParams << llendl ;
+ llinfos << "more info to check if mProfilep is deleted or not." << llendl ;
+ llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ;
+
+ llerrs << "LLVolume corrupted!" << llendl ;
+ }
+ //********************************************************************
+
BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
if (regenPath || regenProf )
{
- sNumMeshPoints -= mMesh.size();
- mMesh.resize(mProfilep->mProfile.size() * mPathp->mPath.size());
- sNumMeshPoints += mMesh.size();
-
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
+ //********************************************************************
+ //debug info, to be removed
+ if((U32)(sizeS * sizeT) > (1u << 20))
+ {
+ llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ;
+ llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ;
+ llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ;
+ llinfos << mParams << llendl ;
+ llinfos << "more info to check if mProfilep is deleted or not." << llendl ;
+ llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ;
+
+ llerrs << "LLVolume corrupted!" << llendl ;
+ }
+ //********************************************************************
+
+ sNumMeshPoints -= mMesh.size();
+ mMesh.resize(sizeT * sizeS);
+ sNumMeshPoints += mMesh.size();
+
//generate vertex positions
// Run along the path.
@@ -1799,6 +1860,11 @@ void LLVolume::createVolumeFaces()
LLProfile::Face& face = mProfilep->mFaces[i];
vf.mBeginS = face.mIndex;
vf.mNumS = face.mCount;
+ if (vf.mNumS < 0)
+ {
+ llerrs << "Volume face corruption detected." << llendl;
+ }
+
vf.mBeginT = 0;
vf.mNumT= getPath().mPath.size();
vf.mID = i;
@@ -1842,6 +1908,10 @@ void LLVolume::createVolumeFaces()
if (face.mFlat && vf.mNumS > 2)
{ //flat inner faces have to copy vert normals
vf.mNumS = vf.mNumS*2;
+ if (vf.mNumS < 0)
+ {
+ llerrs << "Volume face corruption detected." << llendl;
+ }
}
}
else
@@ -1909,34 +1979,29 @@ inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_
}
-F32 LLVolume::sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
+F32 LLVolume::sculptGetSurfaceArea()
{
// test to see if image has enough variation to create non-degenerate geometry
+ F32 area = 0;
+
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
-
- F32 area = 0;
-
- if ((sculpt_width != 0) &&
- (sculpt_height != 0) &&
- (sculpt_components != 0) &&
- (sculpt_data != NULL))
+
+ for (S32 s = 0; s < sizeS-1; s++)
{
- for (S32 s = 0; s < sizeS - 1; s++)
+ for (S32 t = 0; t < sizeT-1; t++)
{
- for (S32 t = 0; t < sizeT - 1; t++)
- {
- // convert image data to vectors
- LLVector3 p1 = sculpt_st_to_vector(s, t, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
- LLVector3 p2 = sculpt_st_to_vector(s+1, t, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
- LLVector3 p3 = sculpt_st_to_vector(s, t+1, sizeS, sizeT, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
-
- // compute the area of the parallelogram by taking the length of the cross product:
- // (parallegram is an approximation of two triangles)
- LLVector3 cross = (p1 - p2) % (p1 - p3);
- area += cross.magVec();
- }
+ // get four corners of quad
+ LLVector3 p1 = mMesh[(s )*sizeT + (t )].mPos;
+ LLVector3 p2 = mMesh[(s+1)*sizeT + (t )].mPos;
+ LLVector3 p3 = mMesh[(s )*sizeT + (t+1)].mPos;
+ LLVector3 p4 = mMesh[(s+1)*sizeT + (t+1)].mPos;
+
+ // compute the area of the quad by taking the length of the cross product of the two triangles
+ LLVector3 cross1 = (p1 - p2) % (p1 - p3);
+ LLVector3 cross2 = (p4 - p2) % (p4 - p3);
+ area += (cross1.magVec() + cross2.magVec()) / 2.0;
}
}
@@ -1979,6 +2044,12 @@ void LLVolume::sculptGeneratePlaceholder()
// create the vertices from the map
void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type)
{
+ U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
+ BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
+ BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
+ BOOL reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR
+
+
LLMemType m1(LLMemType::MTYPE_VOLUME);
S32 sizeS = mPathp->mPath.size();
@@ -1993,13 +2064,21 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8
S32 i = t + line;
Point& pt = mMesh[i];
- U32 x = (U32) ((F32)t/(sizeT-1) * (F32) sculpt_width);
+ S32 reversed_t = t;
+
+ if (reverse_horizontal)
+ {
+ reversed_t = sizeT - t - 1;
+ }
+
+ U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width);
U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height);
+
if (y == 0) // top row stitching
{
// pinch?
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
+ if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE)
{
x = sculpt_width / 2;
}
@@ -2008,7 +2087,7 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8
if (y == sculpt_height) // bottom row stitching
{
// wrap?
- if (sculpt_type == LL_SCULPT_TYPE_TORUS)
+ if (sculpt_stitching == LL_SCULPT_TYPE_TORUS)
{
y = 0;
}
@@ -2018,7 +2097,7 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8
}
// pinch?
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
+ if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE)
{
x = sculpt_width / 2;
}
@@ -2027,9 +2106,9 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8
if (x == sculpt_width) // side stitching
{
// wrap?
- if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) ||
- (sculpt_type == LL_SCULPT_TYPE_TORUS) ||
- (sculpt_type == LL_SCULPT_TYPE_CYLINDER))
+ if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) ||
+ (sculpt_stitching == LL_SCULPT_TYPE_TORUS) ||
+ (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER))
{
x = 0;
}
@@ -2041,12 +2120,83 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8
}
pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
+
+ if (sculpt_mirror)
+ {
+ pt.mPos.mV[VX] *= -1.f;
+ }
}
+
line += sizeT;
}
}
+const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square
+const S32 SCULPT_REZ_2 = 8;
+const S32 SCULPT_REZ_3 = 16;
+const S32 SCULPT_REZ_4 = 32;
+
+S32 sculpt_sides(F32 detail)
+{
+
+ // detail is usually one of: 1, 1.5, 2.5, 4.0.
+
+ if (detail <= 1.0)
+ {
+ return SCULPT_REZ_1;
+ }
+ if (detail <= 2.0)
+ {
+ return SCULPT_REZ_2;
+ }
+ if (detail <= 3.0)
+ {
+ return SCULPT_REZ_3;
+ }
+ else
+ {
+ return SCULPT_REZ_4;
+ }
+}
+
+
+
+// determine the number of vertices in both s and t direction for this sculpt
+void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t)
+{
+ // this code has the following properties:
+ // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map
+ // while still using all available verts
+ // 2) the mesh cannot have more verts than is allowed by LOD
+ // 3) the mesh cannot have more verts than is allowed by the map
+
+ S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0);
+ S32 max_vertices_map = width * height / 4;
+
+ S32 vertices;
+ if (max_vertices_map > 0)
+ vertices = llmin(max_vertices_lod, max_vertices_map);
+ else
+ vertices = max_vertices_lod;
+
+
+ F32 ratio;
+ if ((width == 0) || (height == 0))
+ ratio = 1.f;
+ else
+ ratio = (F32) width / (F32) height;
+
+
+ s = (S32)fsqrtf(((F32)vertices / ratio));
+
+ s = llmax(s, 4); // no degenerate sizes, please
+ t = vertices / s;
+
+ t = llmax(t, 4); // no degenerate sizes, please
+ s = vertices / t;
+}
+
// sculpt replaces generate() for sculpted surfaces
void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
{
@@ -2061,11 +2211,16 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
data_is_empty = TRUE;
}
- mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE);
- mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE);
+ S32 requested_sizeS = 0;
+ S32 requested_sizeT = 0;
- S32 sizeS = mPathp->mPath.size();
- S32 sizeT = mProfilep->mProfile.size();
+ sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT);
+
+ mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS);
+ mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT);
+
+ S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got
+ S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got
// weird crash bug - DEV-11158 - trying to collect more data:
if ((sizeS == 0) || (sizeT == 0))
@@ -2076,20 +2231,29 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
sNumMeshPoints -= mMesh.size();
mMesh.resize(sizeS * sizeT);
sNumMeshPoints += mMesh.size();
-
- if (!data_is_empty && sculptGetSurfaceArea(sculpt_width, sculpt_height, sculpt_components, sculpt_data) < SCULPT_MIN_AREA)
- data_is_empty = TRUE;
//generate vertex positions
- if (data_is_empty) // if empty, make a placeholder mesh
- {
- sculptGeneratePlaceholder();
- }
- else
+ if (!data_is_empty)
{
sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type);
+
+ // don't test lowest LOD to support legacy content DEV-33670
+ if (mDetail > SCULPT_MIN_AREA_DETAIL)
+ {
+ if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
+ {
+ data_is_empty = TRUE;
+ }
+ }
+ }
+
+ if (data_is_empty)
+ {
+ sculptGeneratePlaceholder();
}
+
+
for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++)
{
mFaceMask |= mProfilep->mFaces[i].mFaceID;
@@ -3216,7 +3380,8 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
std::vector<S32> &segments,
const LLVector3& obj_cam_vec,
const LLMatrix4& mat,
- const LLMatrix3& norm_mat)
+ const LLMatrix3& norm_mat,
+ S32 face_mask)
{
LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -3224,12 +3389,17 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
normals.clear();
segments.clear();
+ S32 cur_index = 0;
//for each face
for (face_list_t::iterator iter = mVolumeFaces.begin();
iter != mVolumeFaces.end(); ++iter)
{
const LLVolumeFace& face = *iter;
+ if (!(face_mask & (0x1 << cur_index++)))
+ {
+ continue;
+ }
if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
}
@@ -3405,47 +3575,99 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
}
}
-S32 LLVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
+S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
+ S32 face,
+ LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
{
- S32 ret = -1;
+ S32 hit_face = -1;
+
+ S32 start_face;
+ S32 end_face;
- LLVector3 vec = end - start;
+ if (face == -1) // ALL_SIDES
+ {
+ start_face = 0;
+ end_face = getNumVolumeFaces() - 1;
+ }
+ else
+ {
+ start_face = face;
+ end_face = face;
+ }
+
+ LLVector3 dir = end - start;
+
+ F32 closest_t = 2.f; // must be larger than 1
- for (S32 i = 0; i < getNumFaces(); i++)
+ for (S32 i = start_face; i <= end_face; i++)
{
- const LLVolumeFace& face = getVolumeFace(i);
+ const LLVolumeFace &face = getVolumeFace((U32)i);
+
+ LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f;
+ LLVector3 box_size = face.mExtents[1] - face.mExtents[0];
+
+ if (LLLineSegmentBoxIntersect(start, end, box_center, box_size))
+ {
+ if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them
+ {
+ genBinormals(i);
+ }
+
+ for (U32 tri = 0; tri < face.mIndices.size()/3; tri++)
+ {
+ S32 index1 = face.mIndices[tri*3+0];
+ S32 index2 = face.mIndices[tri*3+1];
+ S32 index3 = face.mIndices[tri*3+2];
- for (U32 j = 0; j < face.mIndices.size()/3; j++)
+ F32 a, b, t;
+
+ if (LLTriangleRayIntersect(face.mVertices[index1].mPosition,
+ face.mVertices[index2].mPosition,
+ face.mVertices[index3].mPosition,
+ start, dir, &a, &b, &t, FALSE))
+ {
+ if ((t >= 0.f) && // if hit is after start
+ (t <= 1.f) && // and before end
+ (t < closest_t)) // and this hit is closer
{
- //approximate normal
- S32 v1 = face.mIndices[j*3+0];
- S32 v2 = face.mIndices[j*3+1];
- S32 v3 = face.mIndices[j*3+2];
+ closest_t = t;
+ hit_face = i;
- LLVector3 norm = (face.mVertices[v2].mPosition - face.mVertices[v1].mPosition) %
- (face.mVertices[v3].mPosition - face.mVertices[v2].mPosition);
+ if (intersection != NULL)
+ {
+ *intersection = start + dir * closest_t;
+ }
- if (norm.magVecSquared() >= 0.00000001f)
+ if (tex_coord != NULL)
{
- //get view vector
- //LLVector3 view = (start-face.mVertices[v1].mPosition);
- //if (view * norm < 0.0f)
+ *tex_coord = ((1.f - a - b) * face.mVertices[index1].mTexCoord +
+ a * face.mVertices[index2].mTexCoord +
+ b * face.mVertices[index3].mTexCoord);
+
+ }
+
+ if (normal != NULL)
{
- if (LLTriangleLineSegmentIntersect( face.mVertices[v1].mPosition,
- face.mVertices[v2].mPosition,
- face.mVertices[v3].mPosition,
- end,
- vec))
+ *normal = ((1.f - a - b) * face.mVertices[index1].mNormal +
+ a * face.mVertices[index2].mNormal +
+ b * face.mVertices[index3].mNormal);
+ }
+
+ if (bi_normal != NULL)
{
- vec = end-start;
- ret = (S32) i;
+ *bi_normal = ((1.f - a - b) * face.mVertices[index1].mBinormal +
+ a * face.mVertices[index2].mBinormal +
+ b * face.mVertices[index3].mBinormal);
+ }
+
}
}
}
}
}
- return ret;
+
+ return hit_face;
}
class LLVertexIndexPair
@@ -3605,6 +3827,7 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices,
// Generate the vertex mapping and the list of vertices without
// duplicates. This will crash if there are no vertices.
+ llassert(num_input_vertices > 0); // check for no vertices!
S32 *vertex_mapping = new S32[num_input_vertices];
LLVector3 *new_vertices = new LLVector3[num_input_vertices];
LLVertexIndexPair *prev_pairp = NULL;
@@ -4056,7 +4279,7 @@ LLFaceID LLVolume::generateFaceMask()
}
break;
default:
- llerrs << "Unknown profile!" << llendl
+ llerrs << "Unknown profile!" << llendl;
break;
}
@@ -4303,16 +4526,74 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
if (!partial_build)
{
- int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
- for(int gx = 0;gx<grid_size;gx++){
- for(int gy = 0;gy<grid_size;gy++){
- if (mTypeMask & TOP_MASK){
- for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
- }else{
- for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+#if GEN_TRI_STRIP
+ mTriStrip.clear();
+#endif
+ S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
+ for(S32 gx = 0;gx<grid_size;gx++)
+ {
+
+ for(S32 gy = 0;gy<grid_size;gy++)
+ {
+ if (mTypeMask & TOP_MASK)
+ {
+ for(S32 i=5;i>=0;i--)
+ {
+ mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+ }
+
+#if GEN_TRI_STRIP
+ if (gy == 0)
+ {
+ mTriStrip.push_back((gx+1)*(grid_size+1));
+ mTriStrip.push_back((gx+1)*(grid_size+1));
+ mTriStrip.push_back(gx*(grid_size+1));
+ }
+
+ mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1));
+ mTriStrip.push_back(gy+1+gx*(grid_size+1));
+
+
+ if (gy == grid_size-1)
+ {
+ mTriStrip.push_back(gy+1+gx*(grid_size+1));
+ }
+#endif
+ }
+ else
+ {
+ for(S32 i=0;i<6;i++)
+ {
+ mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
+ }
+
+#if GEN_TRI_STRIP
+ if (gy == 0)
+ {
+ mTriStrip.push_back(gx*(grid_size+1));
+ mTriStrip.push_back(gx*(grid_size+1));
+ mTriStrip.push_back((gx+1)*(grid_size+1));
+ }
+
+ mTriStrip.push_back(gy+1+gx*(grid_size+1));
+ mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1));
+
+ if (gy == grid_size-1)
+ {
+ mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1));
+ }
+#endif
}
}
+
+ }
+
+#if GEN_TRI_STRIP
+ if (mTriStrip.size()%2 == 1)
+ {
+ mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
}
+#endif
}
return TRUE;
@@ -4553,6 +4834,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
pt2--;
}
}
+
+ makeTriStrip();
}
else
{
@@ -4657,67 +4940,112 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
pt2--;
}
}
+
+ makeTriStrip();
}
}
else
{
// Not hollow, generate the triangle fan.
+ U16 v1 = 2;
+ U16 v2 = 1;
+
if (mTypeMask & TOP_MASK)
{
- if (mTypeMask & OPEN_MASK)
- {
- // SOLID OPEN TOP
- // Generate indices
- // This is a tri-fan, so we reuse the same first point for all triangles.
- for (S32 i = 0; i < (num_vertices - 2); i++)
- {
- mIndices[3*i] = num_vertices - 1;
- mIndices[3*i+1] = i;
- mIndices[3*i+2] = i + 1;
- }
- }
- else
- {
- // SOLID CLOSED TOP
- for (S32 i = 0; i < (num_vertices - 2); i++)
- {
- //MSMSM fix these caps but only for the un-cut case
- mIndices[3*i] = num_vertices - 1;
- mIndices[3*i+1] = i;
- mIndices[3*i+2] = i + 1;
- }
- }
+ v1 = 1;
+ v2 = 2;
+ }
+
+ for (S32 i = 0; i < (num_vertices - 2); i++)
+ {
+ mIndices[3*i] = num_vertices - 1;
+ mIndices[3*i+v1] = i;
+ mIndices[3*i+v2] = i + 1;
+ }
+
+#if GEN_TRI_STRIP
+ //make tri strip
+ if (mTypeMask & OPEN_MASK)
+ {
+ makeTriStrip();
}
else
{
- if (mTypeMask & OPEN_MASK)
+ S32 j = num_vertices-2;
+ if (mTypeMask & TOP_MASK)
{
- // SOLID OPEN BOTTOM
- // Generate indices
- // This is a tri-fan, so we reuse the same first point for all triangles.
- for (S32 i = 0; i < (num_vertices - 2); i++)
+ mTriStrip.push_back(0);
+ for (S32 i = 0; i <= j; ++i)
{
- mIndices[3*i] = num_vertices - 1;
- mIndices[3*i+1] = i + 1;
- mIndices[3*i+2] = i;
+ mTriStrip.push_back(i);
+ if (i != j)
+ {
+ mTriStrip.push_back(j);
+ }
+ --j;
}
}
else
{
- // SOLID CLOSED BOTTOM
- for (S32 i = 0; i < (num_vertices - 2); i++)
+ mTriStrip.push_back(j);
+ for (S32 i = 0; i <= j; ++i)
{
- //MSMSM fix these caps but only for the un-cut case
- mIndices[3*i] = num_vertices - 1;
- mIndices[3*i+1] = i + 1;
- mIndices[3*i+2] = i;
+ if (i != j)
+ {
+ mTriStrip.push_back(j);
+ }
+ mTriStrip.push_back(i);
+ --j;
}
}
+
+ mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
+
+ if (mTriStrip.size()%2 == 1)
+ {
+ mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
+ }
}
+#endif
}
+
return TRUE;
}
+void LLVolumeFace::makeTriStrip()
+{
+#if GEN_TRI_STRIP
+ for (U32 i = 0; i < mIndices.size(); i+=3)
+ {
+ U16 i0 = mIndices[i];
+ U16 i1 = mIndices[i+1];
+ U16 i2 = mIndices[i+2];
+
+ if ((i/3)%2 == 1)
+ {
+ mTriStrip.push_back(i0);
+ mTriStrip.push_back(i0);
+ mTriStrip.push_back(i1);
+ mTriStrip.push_back(i2);
+ mTriStrip.push_back(i2);
+ }
+ else
+ {
+ mTriStrip.push_back(i2);
+ mTriStrip.push_back(i2);
+ mTriStrip.push_back(i1);
+ mTriStrip.push_back(i0);
+ mTriStrip.push_back(i0);
+ }
+ }
+
+ if (mTriStrip.size()%2 == 1)
+ {
+ mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
+ }
+#endif
+}
+
void LLVolumeFace::createBinormals()
{
LLMemType m1(LLMemType::MTYPE_VOLUME);
@@ -4768,6 +5096,13 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
LLMemType m1(LLMemType::MTYPE_VOLUME);
BOOL flat = mTypeMask & FLAT_MASK;
+
+ U8 sculpt_type = volume->getParams().getSculptType();
+ U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
+ BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
+ BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
+ BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR
+
S32 num_vertices, num_indices;
const std::vector<LLVolume::Point>& mesh = volume->getMesh();
@@ -4789,11 +5124,10 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
mIndices.resize(num_indices);
mEdge.resize(num_indices);
}
-
- LLVector3& face_min = mExtents[0];
- LLVector3& face_max = mExtents[1];
-
- mCenter.clearVec();
+ else
+ {
+ mHasBinormals = FALSE;
+ }
S32 begin_stex = llfloor( profile[mBeginS].mV[2] );
S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS;
@@ -4829,6 +5163,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
}
}
+ if (sculpt_reverse_horizontal)
+ {
+ ss = 1.f - ss;
+ }
+
// Check to see if this triangle wraps around the array.
if (mBeginS + s >= max_s)
{
@@ -4845,15 +5184,6 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
-
- if (cur_vertex == 0)
- {
- face_min = face_max = mesh[i].mPos;
- }
- else
- {
- update_min_max(face_min, face_max, mesh[i].mPos);
- }
cur_vertex++;
@@ -4887,12 +5217,22 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
- update_min_max(face_min,face_max,mesh[i].mPos);
-
cur_vertex++;
}
}
+
+ //get bounding box for this side
+ LLVector3& face_min = mExtents[0];
+ LLVector3& face_max = mExtents[1];
+ mCenter.clearVec();
+
+ face_min = face_max = mVertices[0].mPosition;
+ for (U32 i = 1; i < mVertices.size(); ++i)
+ {
+ update_min_max(face_min, face_max, mVertices[i].mPosition);
+ }
+
mCenter = (face_min + face_max) * 0.5f;
S32 cur_index = 0;
@@ -4901,9 +5241,18 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
if (!partial_build)
{
+#if GEN_TRI_STRIP
+ mTriStrip.clear();
+#endif
+
// Now we generate the indices.
for (t = 0; t < (mNumT-1); t++)
{
+#if GEN_TRI_STRIP
+ //prepend terminating index to strip
+ mTriStrip.push_back(mNumS*t);
+#endif
+
for (s = 0; s < (mNumS-1); s++)
{
mIndices[cur_index++] = s + mNumS*t; //bottom left
@@ -4913,6 +5262,16 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
mIndices[cur_index++] = s+1 + mNumS*t; //bottom right
mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
+#if GEN_TRI_STRIP
+ if (s == 0)
+ {
+ mTriStrip.push_back(s+mNumS*t);
+ mTriStrip.push_back(s+mNumS*(t+1));
+ }
+ mTriStrip.push_back(s+1+mNumS*t);
+ mTriStrip.push_back(s+1+mNumS*(t+1));
+#endif
+
mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face
if (t < mNumT-2) { //top right/top left neighbor face
mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
@@ -4953,46 +5312,44 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
}
mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face
}
+#if GEN_TRI_STRIP
+ //append terminating vertex to strip
+ mTriStrip.push_back(mNumS-1+mNumS*(t+1));
+#endif
+ }
+
+#if GEN_TRI_STRIP
+ if (mTriStrip.size()%2 == 1)
+ {
+ mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]);
}
+#endif
}
//generate normals
for (U32 i = 0; i < mIndices.size()/3; i++) //for each triangle
{
- const S32 i0 = mIndices[i*3+0];
- const S32 i1 = mIndices[i*3+1];
- const S32 i2 = mIndices[i*3+2];
- const VertexData& v0 = mVertices[i0];
- const VertexData& v1 = mVertices[i1];
- const VertexData& v2 = mVertices[i2];
+ const U16* idx = &(mIndices[i*3]);
+
+ VertexData* v[] =
+ { &mVertices[idx[0]], &mVertices[idx[1]], &mVertices[idx[2]] };
//calculate triangle normal
- LLVector3 norm = (v0.mPosition-v1.mPosition) % (v0.mPosition-v2.mPosition);
+ LLVector3 norm = (v[0]->mPosition-v[1]->mPosition) % (v[0]->mPosition-v[2]->mPosition);
- for (U32 j = 0; j < 3; j++)
- { //add triangle normal to vertices
- const S32 idx = mIndices[i*3+j];
- mVertices[idx].mNormal += norm; // * (weight_sum - d[j])/weight_sum;
- }
+ v[0]->mNormal += norm;
+ v[1]->mNormal += norm;
+ v[2]->mNormal += norm;
//even out quad contributions
- if ((i & 1) == 0)
- {
- mVertices[i2].mNormal += norm;
- }
- else
- {
- mVertices[i1].mNormal += norm;
- }
+ v[i%2+1]->mNormal += norm;
}
// adjust normals based on wrapping and stitching
BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f);
BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f);
- U8 sculpt_type = volume->getParams().getSculptType();
-
- if (sculpt_type == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes
+ if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes
{
if (volume->getPath().isOpen() == FALSE)
{ //wrap normals on T
@@ -5041,15 +5398,15 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
BOOL wrap_s = FALSE;
BOOL wrap_t = FALSE;
- if (sculpt_type == LL_SCULPT_TYPE_SPHERE)
+ if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE)
average_poles = TRUE;
- if ((sculpt_type == LL_SCULPT_TYPE_SPHERE) ||
- (sculpt_type == LL_SCULPT_TYPE_TORUS) ||
- (sculpt_type == LL_SCULPT_TYPE_CYLINDER))
+ if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) ||
+ (sculpt_stitching == LL_SCULPT_TYPE_TORUS) ||
+ (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER))
wrap_s = TRUE;
- if (sculpt_type == LL_SCULPT_TYPE_TORUS)
+ if (sculpt_stitching == LL_SCULPT_TYPE_TORUS)
wrap_t = TRUE;
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index c395ed7378..d48a79ee46 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -2,30 +2,25 @@
* @file llvolume.h
* @brief LLVolume base class.
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -51,7 +46,7 @@ class LLVolume;
#include "llquaternion.h"
#include "llstrider.h"
#include "v4coloru.h"
-#include "llmemory.h"
+#include "llrefcount.h"
#include "llfile.h"
//============================================================================
@@ -175,7 +170,7 @@ const LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8;
//============================================================================
-// sculpt types
+// sculpt types + flags
const U8 LL_SCULPT_TYPE_NONE = 0;
const U8 LL_SCULPT_TYPE_SPHERE = 1;
@@ -183,6 +178,10 @@ const U8 LL_SCULPT_TYPE_TORUS = 2;
const U8 LL_SCULPT_TYPE_PLANE = 3;
const U8 LL_SCULPT_TYPE_CYLINDER = 4;
+const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER;
+
+const U8 LL_SCULPT_FLAG_INVERT = 64;
+const U8 LL_SCULPT_FLAG_MIRROR = 128;
class LLProfileParams
@@ -667,9 +666,7 @@ public:
mConcave(FALSE),
mDirty(TRUE),
mTotalOut(0),
- mTotal(2),
- mMinX(0.f),
- mMaxX(0.f)
+ mTotal(2)
{
}
@@ -680,7 +677,8 @@ public:
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
BOOL isOpen() const { return mOpen; }
void setDirty() { mDirty = TRUE; }
- BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
+ BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
+ BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL isConcave() const { return mConcave; }
public:
struct Face
@@ -716,9 +714,6 @@ protected:
S32 mTotalOut;
S32 mTotal;
-
- F32 mMaxX;
- F32 mMinX;
};
//-------------------------------------------------------------------
@@ -749,7 +744,8 @@ public:
virtual ~LLPath();
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
- virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
+ virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
+ BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL isOpen() const { return mOpen; }
F32 getStep() const { return mStep; }
@@ -775,7 +771,8 @@ class LLDynamicPath : public LLPath
{
public:
LLDynamicPath() : LLPath() { }
- /*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE);
+ /*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
+ BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
};
// Yet another "face" class - caches volume-specific, but not instance-specific data for faces)
@@ -795,7 +792,8 @@ public:
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
void createBinormals();
-
+ void makeTriStrip();
+
class VertexData
{
public:
@@ -836,6 +834,7 @@ public:
std::vector<VertexData> mVertices;
std::vector<U16> mIndices;
+ std::vector<U16> mTriStrip;
std::vector<S32> mEdge;
private:
@@ -899,14 +898,24 @@ public:
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
- void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec,
- const LLMatrix4& mat,
- const LLMatrix3& norm_mat);
+ void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
+ std::vector<LLVector3> &normals,
+ std::vector<S32> &segments,
+ const LLVector3& view_vec,
+ const LLMatrix4& mat,
+ const LLMatrix3& norm_mat,
+ S32 face_index);
//get the face index of the face that intersects with the given line segment at the point
//closest to start. Moves end to the point of intersection. Returns -1 if no intersection.
//Line segment must be in volume space.
- S32 lineSegmentIntersect(const LLVector3& start, LLVector3& end) const;
+ S32 lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
+ S32 face = -1, // which face to check, -1 = ALL_SIDES
+ LLVector3* intersection = NULL, // return the intersection point
+ LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
+ LLVector3* normal = NULL, // return the surface normal at the intersection point
+ LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point
+ );
// The following cleans up vertices and triangles,
// getting rid of degenerate triangles and duplicate vertices,
@@ -934,9 +943,11 @@ public:
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
private:
- F32 sculptGetSurfaceArea(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data);
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
+ F32 sculptGetSurfaceArea();
void sculptGeneratePlaceholder();
+ void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t);
+
protected:
BOOL generate();
@@ -967,4 +978,10 @@ LLVector3 calc_binormal_from_triangle(
const LLVector3& pos2,
const LLVector2& tex2);
+BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
+BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
+ F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided);
+
+
+
#endif
diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp
index 23ed0183b8..88c195936c 100644
--- a/indra/llmath/llvolumemgr.cpp
+++ b/indra/llmath/llvolumemgr.cpp
@@ -1,30 +1,25 @@
/**
* @file llvolumemgr.cpp
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -115,7 +110,7 @@ LLVolume* LLVolumeMgr::refVolume(const LLVolumeParams &volume_params, const S32
{
mDataMutex->unlock();
}
- return volgroupp->getLODVolume(detail);
+ return volgroupp->refLOD(detail);
}
// virtual
@@ -294,7 +289,7 @@ bool LLVolumeLODGroup::cleanupRefs()
return res;
}
-LLVolume* LLVolumeLODGroup::getLODVolume(const S32 detail)
+LLVolume* LLVolumeLODGroup::refLOD(const S32 detail)
{
llassert(detail >=0 && detail < NUM_LODS);
mAccessCount[detail]++;
@@ -376,7 +371,6 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
F32 LLVolumeLODGroup::dump()
{
- char dump_str[255]; /* Flawfinder: ignore */
F32 usage = 0.f;
for (S32 i = 0; i < NUM_LODS; i++)
{
@@ -387,7 +381,7 @@ F32 LLVolumeLODGroup::dump()
}
usage = usage / (F32)NUM_LODS;
- snprintf(dump_str, sizeof(dump_str), "%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]); /* Flawfinder: ignore */
+ std::string dump_str = llformat("%.3f %d %d %d %d", usage, mAccessCount[0], mAccessCount[1], mAccessCount[2], mAccessCount[3]);
llinfos << dump_str << llendl;
return usage;
diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h
index fac194165b..5257da2693 100644
--- a/indra/llmath/llvolumemgr.h
+++ b/indra/llmath/llvolumemgr.h
@@ -2,30 +2,25 @@
* @file llvolumemgr.h
* @brief LLVolumeMgr class.
*
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,7 +30,7 @@
#include <map>
#include "llvolume.h"
-#include "llmemory.h"
+#include "llpointer.h"
#include "llthread.h"
class LLVolumeParams;
@@ -59,7 +54,7 @@ public:
static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher);
static F32 getVolumeScaleFromDetail(const S32 detail);
- LLVolume* getLODVolume(const S32 detail);
+ LLVolume* refLOD(const S32 detail);
BOOL derefLOD(LLVolume *volumep);
S32 getNumRefs() const { return mRefs; }
@@ -91,8 +86,8 @@ public:
// whatever calls getVolume() never owns the LLVolume* and
// cannot keep references for long since it may be deleted
// later. For best results hold it in an LLPointer<LLVolume>.
- LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
- void unrefVolume(LLVolume *volumep);
+ virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
+ virtual void unrefVolume(LLVolume *volumep);
void dump();
diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp
index 184b87c000..802ddb9e57 100644
--- a/indra/llmath/m3math.cpp
+++ b/indra/llmath/m3math.cpp
@@ -2,30 +2,25 @@
* @file m3math.cpp
* @brief LLMatrix3 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h
index 5f37456f51..2be5452f8d 100644
--- a/indra/llmath/m3math.h
+++ b/indra/llmath/m3math.h
@@ -2,30 +2,25 @@
* @file m3math.h
* @brief LLMatrix3 class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index 836b3178d5..946b1553fe 100644
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -2,30 +2,25 @@
* @file m4math.cpp
* @brief LLMatrix4 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -677,32 +672,6 @@ LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b)
}
*/
-// Operates "to the left" on row-vector a
-//
-// This used to be in the header file but was not actually inlined in practice.
-// When avatar vertex programs are off, this function is a hot spot in profiles
-// due to software skinning in LLViewerJointMesh::updateGeometry(). JC
-LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
-{
- // This is better than making a temporary LLVector3. This eliminates an
- // unnecessary LLVector3() constructor and also helps the compiler to
- // realize that the output floats do not alias the input floats, hence
- // eliminating redundant loads of a.mV[0], etc. JC
- return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
- a.mV[VY] * b.mMatrix[VY][VX] +
- a.mV[VZ] * b.mMatrix[VZ][VX] +
- b.mMatrix[VW][VX],
-
- a.mV[VX] * b.mMatrix[VX][VY] +
- a.mV[VY] * b.mMatrix[VY][VY] +
- a.mV[VZ] * b.mMatrix[VZ][VY] +
- b.mMatrix[VW][VY],
-
- a.mV[VX] * b.mMatrix[VX][VZ] +
- a.mV[VY] * b.mMatrix[VY][VZ] +
- a.mV[VZ] * b.mMatrix[VZ][VZ] +
- b.mMatrix[VW][VZ]);
-}
LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b)
{
diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h
index 790e77abc6..6ec9958491 100644
--- a/indra/llmath/m4math.h
+++ b/indra/llmath/m4math.h
@@ -2,30 +2,25 @@
* @file m4math.h
* @brief LLMatrix4 class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -229,7 +224,7 @@ public:
// friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b
- friend LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
+ friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate
friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b); // Rotates a but does not translate
@@ -352,7 +347,31 @@ inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b)
return a;
}
-#endif
-
+// Operates "to the left" on row-vector a
+//
+// When avatar vertex programs are off, this function is a hot spot in profiles
+// due to software skinning in LLViewerJointMesh::updateGeometry(). JC
+inline const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
+{
+ // This is better than making a temporary LLVector3. This eliminates an
+ // unnecessary LLVector3() constructor and also helps the compiler to
+ // realize that the output floats do not alias the input floats, hence
+ // eliminating redundant loads of a.mV[0], etc. JC
+ return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] +
+ a.mV[VY] * b.mMatrix[VY][VX] +
+ a.mV[VZ] * b.mMatrix[VZ][VX] +
+ b.mMatrix[VW][VX],
+
+ a.mV[VX] * b.mMatrix[VX][VY] +
+ a.mV[VY] * b.mMatrix[VY][VY] +
+ a.mV[VZ] * b.mMatrix[VZ][VY] +
+ b.mMatrix[VW][VY],
+
+ a.mV[VX] * b.mMatrix[VX][VZ] +
+ a.mV[VY] * b.mMatrix[VY][VZ] +
+ a.mV[VZ] * b.mMatrix[VZ][VZ] +
+ b.mMatrix[VW][VZ]);
+}
+#endif
diff --git a/indra/llmath/raytrace.cpp b/indra/llmath/raytrace.cpp
index fbdc6cf38b..f38fe49bcb 100644
--- a/indra/llmath/raytrace.cpp
+++ b/indra/llmath/raytrace.cpp
@@ -2,30 +2,25 @@
* @file raytrace.cpp
* @brief Functions called by box object scripts.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/raytrace.h b/indra/llmath/raytrace.h
index 0735b87de1..2d32af0c86 100644
--- a/indra/llmath/raytrace.h
+++ b/indra/llmath/raytrace.h
@@ -2,30 +2,25 @@
* @file raytrace.h
* @brief Ray intersection tests for primitives.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp
new file mode 100644
index 0000000000..8064ab217d
--- /dev/null
+++ b/indra/llmath/tests/llbbox_test.cpp
@@ -0,0 +1,367 @@
+/**
+ * @file llbbox_test.cpp
+ * @author Martin Reddy
+ * @date 2009-06-25
+ * @brief Test for llbbox.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../test/lltut.h"
+
+#include "../llbbox.h"
+
+
+#define ANGLE (3.14159265f / 2.0f)
+#define APPROX_EQUAL(a, b) dist_vec((a),(b)) < 1e-5
+
+namespace tut
+{
+ struct LLBBoxData
+ {
+ };
+
+ typedef test_group<LLBBoxData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory llbbox_test_factory("LLBBox");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the default constructor
+ //
+
+ LLBBox bbox1;
+
+ ensure_equals("Default bbox min", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox max", bbox1.getMaxLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox pos agent", bbox1.getPositionAgent(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox rotation", bbox1.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the non-default constructor
+ //
+
+ LLBBox bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 3.0f, 4.0f), LLVector3(4.0f, 5.0f, 6.0f));
+
+ ensure_equals("Custom bbox min", bbox2.getMinLocal(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Custom bbox max", bbox2.getMaxLocal(), LLVector3(4.0f, 5.0f, 6.0f));
+ ensure_equals("Custom bbox pos agent", bbox2.getPositionAgent(), LLVector3(1.0f, 2.0f, 3.0f));
+ ensure_equals("Custom bbox rotation", bbox2.getRotation(), LLQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the setMinLocal() method
+ //
+ LLBBox bbox2;
+ bbox2.setMinLocal(LLVector3(3.0f, 3.0f, 3.0f));
+ ensure_equals("Custom bbox min (2)", bbox2.getMinLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the setMaxLocal() method
+ //
+ LLBBox bbox2;
+ bbox2.setMaxLocal(LLVector3(5.0f, 5.0f, 5.0f));
+ ensure_equals("Custom bbox max (2)", bbox2.getMaxLocal(), LLVector3(5.0f, 5.0f, 5.0f));
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the getCenterLocal() method
+ //
+
+ ensure_equals("Default bbox local center", LLBBox().getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
+
+ ensure_equals("Custom bbox center local", bbox1.getCenterLocal(), LLVector3(3.0f, 5.0f, 7.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ ensure_equals("Custom bbox center local with rot", bbox2.getCenterLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test the getCenterAgent()
+ //
+
+ ensure_equals("Default bbox agent center", LLBBox().getCenterAgent(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
+
+ ensure_equals("Custom bbox center agent", bbox1.getCenterAgent(), LLVector3(4.0f, 7.0f, 10.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ ensure("Custom bbox center agent with rot", APPROX_EQUAL(bbox2.getCenterAgent(), LLVector3(-2.0f, 4.0f, 4.0f)));
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the getExtentLocal() method
+ //
+
+ ensure_equals("Default bbox local extent", LLBBox().getExtentLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox1(LLVector3(1.0f, 2.0f, 3.0f), LLQuaternion(),
+ LLVector3(2.0f, 4.0f, 6.0f), LLVector3(4.0f, 6.0f, 8.0f));
+
+ ensure_equals("Custom bbox extent local", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(0.0f, 0.0f, 1.0f)),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ ensure_equals("Custom bbox extent local with rot", bbox1.getExtentLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the addPointLocal() method
+ //
+
+ LLBBox bbox1;
+ bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointLocal(LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("addPointLocal center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("addPointLocal center agent (1)", bbox1.getCenterAgent(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("addPointLocal min (1)", bbox1.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("addPointLocal max (1)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox1.addPointLocal(LLVector3(0.0f, 0.0f, 0.0f));
+ bbox1.addPointLocal(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointLocal(LLVector3(2.0f, 2.0f, 2.0f));
+
+ ensure_equals("addPointLocal center local (2)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f));
+ ensure_equals("addPointLocal min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("addPointLocal max (2)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the addBBoxLocal() method
+ //
+
+ LLBBox bbox1;
+ bbox1.addBBoxLocal(LLBBox(LLVector3(), LLQuaternion(),
+ LLVector3(0.0f, 0.0f, 0.0f), LLVector3(3.0f, 3.0f, 3.0f)));
+
+ ensure_equals("addPointLocal center local (3)", bbox1.getCenterLocal(), LLVector3(1.5f, 1.5f, 1.5f));
+ ensure_equals("addPointLocal min (3)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("addPointLocal max (3)", bbox1.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f)));
+
+ ensure_equals("addPointLocal center local (4)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 5.0f));
+ ensure_equals("addPointLocal center agent (4)", bbox1.getCenterAgent(), LLVector3(5.0f, 5.0f, 5.0f));
+ ensure_equals("addPointLocal min (4)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("addPointLocal max (4)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f));
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ //
+ // test the addPointAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("addPointAgent center local (1)", bbox1.getCenterLocal(), LLVector3(2.0f, 2.0f, -2.0f));
+ ensure_equals("addPointAgent center agent (1)", bbox1.getCenterAgent(), LLVector3(3.0f, 3.0f, 7.0f));
+ ensure_equals("addPointAgent min (1)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f));
+ ensure_equals("addPointAgent max (1)", bbox1.getMaxLocal(), LLVector3(4.0f, 4.0f, 0.0f));
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ //
+ // test the addBBoxAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(1.0, 0.0, 0.0, 1.0),
+ LLVector3(2.0f, 2.0f, 2.0f), LLVector3(4.0f, 4.0f, 4.0f));
+
+ bbox1.addPointAgent(LLVector3(1.0f, 1.0f, 1.0f));
+ bbox1.addPointAgent(LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox1.addBBoxLocal(LLBBox(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(5.0f, 5.0f, 5.0f), LLVector3(10.0f, 10.0f, 10.0f)));
+
+ ensure_equals("addPointAgent center local (2)", bbox1.getCenterLocal(), LLVector3(5.0f, 5.0f, 3.0f));
+ ensure_equals("addPointAgent center agent (2)", bbox1.getCenterAgent(), LLVector3(6.0f, -10.0f, 8.0f));
+ ensure_equals("addPointAgent min (2)", bbox1.getMinLocal(), LLVector3(0.0f, 0.0f, -4.0f));
+ ensure_equals("addPointAgent max (2)", bbox1.getMaxLocal(), LLVector3(10.0f, 10.0f, 10.0f));
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ //
+ // test the expand() method
+ //
+
+ LLBBox bbox1;
+ bbox1.expand(0.0);
+
+ ensure_equals("Zero-expanded Default BBox center", bbox1.getCenterLocal(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+ bbox2.expand(0.0);
+
+ ensure_equals("Zero-expanded center local", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Zero-expanded center agent", bbox2.getCenterAgent(), LLVector3(3.0f, 3.0f, 3.0f));
+ ensure_equals("Zero-expanded min", bbox2.getMinLocal(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Zero-expanded max", bbox2.getMaxLocal(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox2.expand(0.5);
+
+ ensure_equals("Positive-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Positive-expanded min", bbox2.getMinLocal(), LLVector3(0.5f, 0.5f, 0.5f));
+ ensure_equals("Positive-expanded max", bbox2.getMaxLocal(), LLVector3(3.5f, 3.5f, 3.5f));
+
+ bbox2.expand(-1.0);
+
+ ensure_equals("Negative-expanded center", bbox2.getCenterLocal(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Negative-expanded min", bbox2.getMinLocal(), LLVector3(1.5f, 1.5f, 1.5f));
+ ensure_equals("Negative-expanded max", bbox2.getMaxLocal(), LLVector3(2.5f, 2.5f, 2.5f));
+ }
+
+ template<> template<>
+ void object::test<13>()
+ {
+ //
+ // test the localToAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("localToAgent(1,2,3)", bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, 3.0f, 4.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure("localToAgent(1,2,3) rot", APPROX_EQUAL(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(2.0f, -2.0f, 3.0f)));
+ }
+
+ template<> template<>
+ void object::test<14>()
+ {
+ //
+ // test the agentToLocal() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure_equals("agentToLocal(1,2,3)", bbox1.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 1.0f, 2.0f));
+ ensure_equals("agentToLocal(localToAgent)", bbox1.agentToLocal(bbox1.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))),
+ LLVector3(1.0f, 2.0f, 3.0f));
+
+ LLBBox bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(ANGLE, LLVector3(1.0f, 0.0f, 0.0f)),
+ LLVector3(1.0f, 1.0f, 1.0f), LLVector3(3.0f, 3.0f, 3.0f));
+
+ ensure("agentToLocal(1,2,3) rot", APPROX_EQUAL(bbox2.agentToLocal(LLVector3(1.0f, 2.0f, 3.0f)), LLVector3(0.0f, 2.0f, -1.0f)));
+ ensure("agentToLocal(localToAgent) rot", APPROX_EQUAL(bbox2.agentToLocal(bbox2.localToAgent(LLVector3(1.0f, 2.0f, 3.0f))),
+ LLVector3(1.0f, 2.0f, 3.0f)));
+ }
+
+ template<> template<>
+ void object::test<15>()
+ {
+ //
+ // test the containsPointLocal() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
+
+ ensure("containsPointLocal(0,0,0)", bbox1.containsPointLocal(LLVector3(0.0f, 0.0f, 0.0f)) == FALSE);
+ ensure("containsPointLocal(1,2,3)", bbox1.containsPointLocal(LLVector3(1.0f, 2.0f, 3.0f)) == TRUE);
+ ensure("containsPointLocal(0.999,2,3)", bbox1.containsPointLocal(LLVector3(0.999f, 2.0f, 3.0f)) == FALSE);
+ ensure("containsPointLocal(3,4,5)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.0f)) == TRUE);
+ ensure("containsPointLocal(3,4,5.001)", bbox1.containsPointLocal(LLVector3(3.0f, 4.0f, 5.001f)) == FALSE);
+ }
+
+ template<> template<>
+ void object::test<16>()
+ {
+ //
+ // test the containsPointAgent() method
+ //
+
+ LLBBox bbox1(LLVector3(1.0f, 1.0f, 1.0f), LLQuaternion(),
+ LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
+
+ ensure("containsPointAgent(0,0,0)", bbox1.containsPointAgent(LLVector3(0.0f, 0.0f, 0.0f)) == FALSE);
+ ensure("containsPointAgent(2,3,4)", bbox1.containsPointAgent(LLVector3(2.0f, 3.0f, 4.0f)) == TRUE);
+ ensure("containsPointAgent(2,2.999,4)", bbox1.containsPointAgent(LLVector3(2.0f, 2.999f, 4.0f)) == FALSE);
+ ensure("containsPointAgent(4,5,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.0f, 6.0f)) == TRUE);
+ ensure("containsPointAgent(4,5.001,6)", bbox1.containsPointAgent(LLVector3(4.0f, 5.001f, 6.0f)) == FALSE);
+ }
+}
+
diff --git a/indra/llmath/tests/llbboxlocal_test.cpp b/indra/llmath/tests/llbboxlocal_test.cpp
new file mode 100644
index 0000000000..f31e4126c4
--- /dev/null
+++ b/indra/llmath/tests/llbboxlocal_test.cpp
@@ -0,0 +1,232 @@
+/**
+ * @file llbboxlocal_test.cpp
+ * @author Martin Reddy
+ * @date 2009-06-25
+ * @brief Test for llbboxlocal.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "../llbboxlocal.h"
+
+namespace tut
+{
+ struct LLBBoxLocalData
+ {
+ };
+
+ typedef test_group<LLBBoxLocalData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory llbboxlocal_test_factory("LLBBoxLocal");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the default constructor
+ //
+
+ LLBBoxLocal bbox1;
+
+ ensure_equals("Default bbox min", bbox1.getMin(), LLVector3(0.0f, 0.0f, 0.0f));
+ ensure_equals("Default bbox max", bbox1.getMax(), LLVector3(0.0f, 0.0f, 0.0f));
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the non-default constructor
+ //
+
+ LLBBoxLocal bbox2(LLVector3(-1.0f, -2.0f, 0.0f), LLVector3(1.0f, 2.0f, 3.0f));
+
+ ensure_equals("Custom bbox min", bbox2.getMin(), LLVector3(-1.0f, -2.0f, 0.0f));
+ ensure_equals("Custom bbox max", bbox2.getMax(), LLVector3(1.0f, 2.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the setMin()
+ //
+ // N.B. no validation is currently performed to ensure that the min
+ // and max vectors are actually the min/max values.
+ //
+
+ LLBBoxLocal bbox2;
+ bbox2.setMin(LLVector3(1.0f, 2.0f, 3.0f));
+
+ ensure_equals("Custom bbox min (2)", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the setMax()
+ //
+ // N.B. no validation is currently performed to ensure that the min
+ // and max vectors are actually the min/max values.
+ //
+
+ LLBBoxLocal bbox2;
+ bbox2.setMax(LLVector3(10.0f, 20.0f, 30.0f));
+
+ ensure_equals("Custom bbox max (2)", bbox2.getMax(), LLVector3(10.0f, 20.0f, 30.0f));
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the getCenter() method
+ //
+
+ ensure_equals("Default bbox center", LLBBoxLocal().getCenter(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBoxLocal bbox1(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f));
+
+ ensure_equals("Custom bbox center", bbox1.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f));
+
+ LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f));
+
+ ensure_equals("Invalid bbox center", bbox2.getCenter(), LLVector3(-0.5f, -0.5f, -0.5f));
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test the getExtent() method
+ //
+
+ LLBBoxLocal bbox2(LLVector3(0.0f, 0.0f, 0.0f), LLVector3(-1.0f, -1.0f, -1.0f));
+
+ ensure_equals("Default bbox extent", LLBBoxLocal().getExtent(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBoxLocal bbox3(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(1.0f, 2.0f, 0.0f));
+
+ ensure_equals("Custom bbox extent", bbox3.getExtent(), LLVector3(2.0f, 3.0f, 1.0f));
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the addPoint() method
+ //
+ // N.B. if you create an empty bbox and then add points,
+ // the vector (0, 0, 0) will always be part of the bbox.
+ // (Fixing this would require adding a bool to the class size).
+ //
+
+ LLBBoxLocal bbox1;
+ bbox1.addPoint(LLVector3(-1.0f, -2.0f, -3.0f));
+ bbox1.addPoint(LLVector3(3.0f, 4.0f, 5.0f));
+
+ ensure_equals("Custom BBox center (1)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox min (1)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
+ ensure_equals("Custom BBox max (1)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
+
+ bbox1.addPoint(LLVector3(0.0f, 0.0f, 0.0f));
+ bbox1.addPoint(LLVector3(1.0f, 2.0f, 3.0f));
+ bbox1.addPoint(LLVector3(2.0f, 2.0f, 2.0f));
+
+ ensure_equals("Custom BBox center (2)", bbox1.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox min (2)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
+ ensure_equals("Custom BBox max (2)", bbox1.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
+
+ bbox1.addPoint(LLVector3(5.0f, 5.0f, 5.0f));
+
+ ensure_equals("Custom BBox center (3)", bbox1.getCenter(), LLVector3(2.0f, 1.5f, 1.0f));
+ ensure_equals("Custom BBox min (3)", bbox1.getMin(), LLVector3(-1.0f, -2.0f, -3.0f));
+ ensure_equals("Custom BBox max (3)", bbox1.getMax(), LLVector3(5.0f, 5.0f, 5.0f));
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the addBBox() methods
+ //
+ // N.B. if you create an empty bbox and then add points,
+ // the vector (0, 0, 0) will always be part of the bbox.
+ // (Fixing this would require adding a bool to the class size).
+ //
+
+ LLBBoxLocal bbox2(LLVector3(1.0f, 1.0f, 1.0f), LLVector3(2.0f, 2.0f, 2.0f));
+ bbox2.addBBox(LLBBoxLocal(LLVector3(1.5f, 1.5f, 1.5f), LLVector3(3.0f, 3.0f, 3.0f)));
+
+ ensure_equals("Custom BBox center (4)", bbox2.getCenter(), LLVector3(2.0f, 2.0f, 2.0f));
+ ensure_equals("Custom BBox min (4)", bbox2.getMin(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox max (4)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f));
+
+ bbox2.addBBox(LLBBoxLocal(LLVector3(-1.0f, -1.0f, -1.0f), LLVector3(0.0f, 0.0f, 0.0f)));
+
+ ensure_equals("Custom BBox center (5)", bbox2.getCenter(), LLVector3(1.0f, 1.0f, 1.0f));
+ ensure_equals("Custom BBox min (5)", bbox2.getMin(), LLVector3(-1.0f, -1.0f, -1.0f));
+ ensure_equals("Custom BBox max (5)", bbox2.getMax(), LLVector3(3.0f, 3.0f, 3.0f));
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the expand() method
+ //
+
+ LLBBoxLocal bbox1;
+ bbox1.expand(0.0f);
+
+ ensure_equals("Zero-expanded Default BBox center", bbox1.getCenter(), LLVector3(0.0f, 0.0f, 0.0f));
+
+ LLBBoxLocal bbox2(LLVector3(1.0f, 2.0f, 3.0f), LLVector3(3.0f, 4.0f, 5.0f));
+ bbox2.expand(0.0f);
+
+ ensure_equals("Zero-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Zero-expanded BBox min", bbox2.getMin(), LLVector3(1.0f, 2.0f, 3.0f));
+ ensure_equals("Zero-expanded BBox max", bbox2.getMax(), LLVector3(3.0f, 4.0f, 5.0f));
+
+ bbox2.expand(0.5f);
+
+ ensure_equals("Positive-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Positive-expanded BBox min", bbox2.getMin(), LLVector3(0.5f, 1.5f, 2.5f));
+ ensure_equals("Positive-expanded BBox max", bbox2.getMax(), LLVector3(3.5f, 4.5f, 5.5f));
+
+ bbox2.expand(-1.0f);
+
+ ensure_equals("Negative-expanded BBox center", bbox2.getCenter(), LLVector3(2.0f, 3.0f, 4.0f));
+ ensure_equals("Negative-expanded BBox min", bbox2.getMin(), LLVector3(1.5f, 2.5f, 3.5f));
+ ensure_equals("Negative-expanded BBox max", bbox2.getMax(), LLVector3(2.5f, 3.5f, 4.5f));
+ }
+}
diff --git a/indra/llmath/tests/llmodularmath_test.cpp b/indra/llmath/tests/llmodularmath_test.cpp
new file mode 100644
index 0000000000..063d3ef79f
--- /dev/null
+++ b/indra/llmath/tests/llmodularmath_test.cpp
@@ -0,0 +1,76 @@
+/**
+ * @file modularmath_test.cpp
+ * @author babbage
+ * @date 2008-09
+ * @brief llmodularmath tests
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llmodularmath.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct modularmath_data
+ {
+ };
+ typedef test_group<modularmath_data> modularmath_test;
+ typedef modularmath_test::object modularmath_object;
+ tut::modularmath_test modularmath_testcase("LLModularMath");
+
+ template<> template<>
+ void modularmath_object::test<1>()
+ {
+ // lhs < rhs
+ const U32 lhs = 0x000001;
+ const U32 rhs = 0xFFFFFF;
+ const U32 width = 24;
+ U32 result = LLModularMath::subtract<width>(lhs, rhs);
+ ensure_equals("diff(0x000001, 0xFFFFFF, 24)", result, 2);
+ }
+
+ template<> template<>
+ void modularmath_object::test<2>()
+ {
+ // lhs > rhs
+ const U32 lhs = 0x000002;
+ const U32 rhs = 0x000001;
+ const U32 width = 24;
+ U32 result = LLModularMath::subtract<width>(lhs, rhs);
+ ensure_equals("diff(0x000002, 0x000001, 24)", result, 1);
+ }
+
+ template<> template<>
+ void modularmath_object::test<3>()
+ {
+ // lhs == rhs
+ const U32 lhs = 0xABCDEF;
+ const U32 rhs = 0xABCDEF;
+ const U32 width = 24;
+ U32 result = LLModularMath::subtract<width>(lhs, rhs);
+ ensure_equals("diff(0xABCDEF, 0xABCDEF, 24)", result, 0);
+ }
+}
diff --git a/indra/llmath/tests/llquaternion_test.cpp b/indra/llmath/tests/llquaternion_test.cpp
new file mode 100644
index 0000000000..9e79b299ff
--- /dev/null
+++ b/indra/llmath/tests/llquaternion_test.cpp
@@ -0,0 +1,660 @@
+/**
+ * @file llquaternion_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief Test cases of llquaternion.h
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../llquaternion.h"
+#include "../v4math.h"
+#include "../v3math.h"
+#include "../v3dmath.h"
+#include "../m4math.h"
+#include "../m3math.h"
+
+namespace tut
+{
+ struct llquat_test
+ {
+ };
+ typedef test_group<llquat_test> llquat_test_t;
+ typedef llquat_test_t::object llquat_test_object_t;
+ tut::llquat_test_t tut_llquat_test("LLQuaternion");
+
+ //test case for LLQuaternion::LLQuaternion(void) fn.
+ template<> template<>
+ void llquat_test_object_t::test<1>()
+ {
+ LLQuaternion llquat;
+ ensure("LLQuaternion::LLQuaternion() failed", 0.f == llquat.mQ[0] &&
+ 0.f == llquat.mQ[1] &&
+ 0.f == llquat.mQ[2] &&
+ 1.f == llquat.mQ[3]);
+ }
+
+ //test case for explicit LLQuaternion(const LLMatrix4 &mat) fn.
+ template<> template<>
+ void llquat_test_object_t::test<2>()
+ {
+ LLMatrix4 llmat;
+ LLVector4 vector1(2.0f, 1.0f, 3.0f, 6.0f);
+ LLVector4 vector2(5.0f, 6.0f, 0.0f, 1.0f);
+ LLVector4 vector3(2.0f, 1.0f, 2.0f, 9.0f);
+ LLVector4 vector4(3.0f, 8.0f, 1.0f, 5.0f);
+
+ llmat.initRows(vector1, vector2, vector3, vector4);
+ ensure("explicit LLQuaternion(const LLMatrix4 &mat) failed", 2.0f == llmat.mMatrix[0][0] &&
+ 1.0f == llmat.mMatrix[0][1] &&
+ 3.0f == llmat.mMatrix[0][2] &&
+ 6.0f == llmat.mMatrix[0][3] &&
+ 5.0f == llmat.mMatrix[1][0] &&
+ 6.0f == llmat.mMatrix[1][1] &&
+ 0.0f == llmat.mMatrix[1][2] &&
+ 1.0f == llmat.mMatrix[1][3] &&
+ 2.0f == llmat.mMatrix[2][0] &&
+ 1.0f == llmat.mMatrix[2][1] &&
+ 2.0f == llmat.mMatrix[2][2] &&
+ 9.0f == llmat.mMatrix[2][3] &&
+ 3.0f == llmat.mMatrix[3][0] &&
+ 8.0f == llmat.mMatrix[3][1] &&
+ 1.0f == llmat.mMatrix[3][2] &&
+ 5.0f == llmat.mMatrix[3][3]);
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<3>()
+ {
+ LLMatrix3 llmat;
+
+ LLVector3 vect1(3.4028234660000000f , 234.56f, 4234.442234f);
+ LLVector3 vect2(741.434f, 23.00034f, 6567.223423f);
+ LLVector3 vect3(566.003034f, 12.98705f, 234.764423f);
+ llmat.setRows(vect1, vect2, vect3);
+
+ ensure("LLMatrix3::setRows fn failed.", 3.4028234660000000f == llmat.mMatrix[0][0] &&
+ 234.56f == llmat.mMatrix[0][1] &&
+ 4234.442234f == llmat.mMatrix[0][2] &&
+ 741.434f == llmat.mMatrix[1][0] &&
+ 23.00034f == llmat.mMatrix[1][1] &&
+ 6567.223423f == llmat.mMatrix[1][2] &&
+ 566.003034f == llmat.mMatrix[2][0] &&
+ 12.98705f == llmat.mMatrix[2][1] &&
+ 234.764423f == llmat.mMatrix[2][2]);
+ }
+
+ //test case for LLQuaternion(F32 x, F32 y, F32 z, F32 w), setQuatInit() and normQuat() fns.
+ template<> template<>
+ void llquat_test_object_t::test<4>()
+ {
+ F32 x_val = 3.0f;
+ F32 y_val = 2.0f;
+ F32 z_val = 6.0f;
+ F32 w_val = 1.0f;
+
+ LLQuaternion res_quat;
+ res_quat.setQuatInit(x_val, y_val, z_val, w_val);
+ res_quat.normQuat();
+
+ ensure("LLQuaternion::normQuat() fn failed",
+ is_approx_equal(0.42426407f, res_quat.mQ[0]) &&
+ is_approx_equal(0.28284273f, res_quat.mQ[1]) &&
+ is_approx_equal(0.84852815f, res_quat.mQ[2]) &&
+ is_approx_equal(0.14142136f, res_quat.mQ[3]));
+
+ x_val = 0.0f;
+ y_val = 0.0f;
+ z_val = 0.0f;
+ w_val = 0.0f;
+
+ res_quat.setQuatInit(x_val, y_val, z_val, w_val);
+ res_quat.normQuat();
+
+ ensure("LLQuaternion::normQuat() fn. failed.",
+ is_approx_equal(0.0f, res_quat.mQ[0]) &&
+ is_approx_equal(0.0f, res_quat.mQ[1]) &&
+ is_approx_equal(0.0f, res_quat.mQ[2]) &&
+ is_approx_equal(1.0f, res_quat.mQ[3]));
+
+
+ ensure("LLQuaternion::normQuat() fn. failed.",
+ is_approx_equal(0.0f, res_quat.mQ[0]) &&
+ is_approx_equal(0.0f, res_quat.mQ[1]) &&
+ is_approx_equal(0.0f, res_quat.mQ[2]) &&
+ is_approx_equal(1.0f, res_quat.mQ[3]));
+ }
+
+ //test case for conjQuat() and transQuat() fns.
+ template<> template<>
+ void llquat_test_object_t::test<5>()
+ {
+ F32 x_val = 3.0f;
+ F32 y_val = 2.0f;
+ F32 z_val = 6.0f;
+ F32 w_val = 1.0f;
+
+ LLQuaternion res_quat;
+ LLQuaternion result, result1;
+ result1 = result = res_quat.setQuatInit(x_val, y_val, z_val, w_val);
+
+ result.conjQuat();
+ result1.transQuat();
+
+ ensure("LLQuaternion::conjQuat and LLQuaternion::transQuat failed ",
+ is_approx_equal(result1.mQ[0], result.mQ[0]) &&
+ is_approx_equal(result1.mQ[1], result.mQ[1]) &&
+ is_approx_equal(result1.mQ[2], result.mQ[2]));
+
+ }
+
+ //test case for dot(const LLQuaternion &a, const LLQuaternion &b) fn.
+ template<> template<>
+ void llquat_test_object_t::test<6>()
+ {
+ LLQuaternion quat1(3.0f, 2.0f, 6.0f, 0.0f), quat2(1.0f, 1.0f, 1.0f, 1.0f);
+ ensure("1. The two values are different", llround(12.000000f, 2) == llround(dot(quat1, quat2), 2));
+
+ LLQuaternion quat0(3.0f, 9.334f, 34.5f, 23.0f), quat(34.5f, 23.23f, 2.0f, 45.5f);
+ ensure("2. The two values are different", llround(1435.828807f, 2) == llround(dot(quat0, quat), 2));
+ }
+
+ //test case for LLQuaternion &LLQuaternion::constrain(F32 radians) fn.
+ template<> template<>
+ void llquat_test_object_t::test<7>()
+ {
+ F32 radian = 60.0f;
+ LLQuaternion quat(3.0f, 2.0f, 6.0f, 0.0f);
+ LLQuaternion quat1;
+ quat1 = quat.constrain(radian);
+ ensure("1. LLQuaternion::constrain(F32 radians) failed",
+ is_approx_equal_fraction(-0.423442f, quat1.mQ[0], 8) &&
+ is_approx_equal_fraction(-0.282295f, quat1.mQ[1], 8) &&
+ is_approx_equal_fraction(-0.846884f, quat1.mQ[2], 8) &&
+ is_approx_equal_fraction(0.154251f, quat1.mQ[3], 8));
+
+
+ radian = 30.0f;
+ LLQuaternion quat0(37.50f, 12.0f, 86.023f, 40.32f);
+ quat1 = quat0.constrain(radian);
+
+ ensure("2. LLQuaternion::constrain(F32 radians) failed",
+ is_approx_equal_fraction(37.500000f, quat1.mQ[0], 8) &&
+ is_approx_equal_fraction(12.0000f, quat1.mQ[1], 8) &&
+ is_approx_equal_fraction(86.0230f, quat1.mQ[2], 8) &&
+ is_approx_equal_fraction(40.320000f, quat1.mQ[3], 8));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<8>()
+ {
+ F32 value1 = 15.0f;
+ LLQuaternion quat1(1.0f, 2.0f, 4.0f, 1.0f);
+ LLQuaternion quat2(4.0f, 3.0f, 6.5f, 9.7f);
+ LLQuaternion res_lerp, res_slerp, res_nlerp;
+
+ //test case for lerp(F32 t, const LLQuaternion &q) fn.
+ res_lerp = lerp(value1, quat1);
+ ensure("1. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.181355f, res_lerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.362711f, res_lerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.725423f, res_lerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.556158f, res_lerp.mQ[3], 16));
+
+ //test case for lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) fn.
+ res_lerp = lerp(value1, quat1, quat2);
+ ensure("2. LLQuaternion lerp(F32 t, const LLQuaternion &p, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.314306f, res_lerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.116156f, res_lerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.283559f, res_lerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.898506f, res_lerp.mQ[3], 16));
+
+ //test case for slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b ) fn.
+ res_slerp = slerp(value1, quat1, quat2);
+ ensure("3. LLQuaternion slerp( F32 u, const LLQuaternion &a, const LLQuaternion &b) failed",
+ is_approx_equal_fraction(46.000f, res_slerp.mQ[0], 16) &&
+ is_approx_equal_fraction(17.00f, res_slerp.mQ[1], 16) &&
+ is_approx_equal_fraction(41.5f, res_slerp.mQ[2], 16) &&
+ is_approx_equal_fraction(131.5f, res_slerp.mQ[3], 16));
+
+ //test case for nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) fn.
+ res_nlerp = nlerp(value1, quat1, quat2);
+ ensure("4. LLQuaternion nlerp(F32 t, const LLQuaternion &a, const LLQuaternion &b) failed",
+ is_approx_equal_fraction(0.314306f, res_nlerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.116157f, res_nlerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.283559f, res_nlerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.898506f, res_nlerp.mQ[3], 16));
+
+ //test case for nlerp(F32 t, const LLQuaternion &q) fn.
+ res_slerp = slerp(value1, quat1);
+ ensure("5. LLQuaternion slerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(1.0f, res_slerp.mQ[0], 16) &&
+ is_approx_equal_fraction(2.0f, res_slerp.mQ[1], 16) &&
+ is_approx_equal_fraction(4.0000f, res_slerp.mQ[2], 16) &&
+ is_approx_equal_fraction(1.000f, res_slerp.mQ[3], 16));
+
+ LLQuaternion quat3(2.0f, 1.0f, 5.5f, 10.5f);
+ LLQuaternion res_nlerp1;
+ value1 = 100.0f;
+ res_nlerp1 = nlerp(value1, quat3);
+ ensure("6. LLQuaternion nlerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.268245f, res_nlerp1.mQ[0], 16) && is_approx_equal_fraction(0.134122f, res_nlerp1.mQ[1], 2) &&
+ is_approx_equal_fraction(0.737673f, res_nlerp1.mQ[2], 16) &&
+ is_approx_equal_fraction(0.604892f, res_nlerp1.mQ[3], 16));
+
+ //test case for lerp(F32 t, const LLQuaternion &q) fn.
+ res_lerp = lerp(value1, quat2);
+ ensure("7. LLQuaternion lerp(F32 t, const LLQuaternion &q) failed",
+ is_approx_equal_fraction(0.404867f, res_lerp.mQ[0], 16) &&
+ is_approx_equal_fraction(0.303650f, res_lerp.mQ[1], 16) &&
+ is_approx_equal_fraction(0.657909f, res_lerp.mQ[2], 16) &&
+ is_approx_equal_fraction(0.557704f, res_lerp.mQ[3], 16));
+
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<9>()
+ {
+ //test case for LLQuaternion operator*(const LLQuaternion &a, const LLQuaternion &b) fn
+ LLQuaternion quat1(1.0f, 2.5f, 3.5f, 5.5f);
+ LLQuaternion quat2(4.0f, 3.0f, 5.0f, 1.0f);
+ LLQuaternion result = quat1 * quat2;
+ ensure("1. LLQuaternion Operator* failed", (21.0f == result.mQ[0]) &&
+ (10.0f == result.mQ[1]) &&
+ (38.0f == result.mQ[2]) &&
+ (-23.5f == result.mQ[3]));
+
+ LLQuaternion quat3(2341.340f, 2352.345f, 233.25f, 7645.5f);
+ LLQuaternion quat4(674.067f, 893.0897f, 578.0f, 231.0f);
+ result = quat3 * quat4;
+ ensure("2. LLQuaternion Operator* failed", (4543086.5f == result.mQ[0]) &&
+ (8567578.0f == result.mQ[1]) &&
+ (3967591.25f == result.mQ[2]) &&
+ is_approx_equal(-2047783.25f, result.mQ[3]));
+
+ //inline LLQuaternion operator+(const LLQuaternion &a, const LLQuaternion &b)fn.
+ result = quat1 + quat2;
+ ensure("3. LLQuaternion operator+ failed", (5.0f == result.mQ[0]) &&
+ (5.5f == result.mQ[1]) &&
+ (8.5f == result.mQ[2]) &&
+ (6.5f == result.mQ[3]));
+
+ result = quat3 + quat4;
+ ensure(
+ "4. LLQuaternion operator+ failed",
+ is_approx_equal(3015.407227f, result.mQ[0]) &&
+ is_approx_equal(3245.434570f, result.mQ[1]) &&
+ (811.25f == result.mQ[2]) &&
+ (7876.5f == result.mQ[3]));
+
+ //inline LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) fn
+ result = quat1 - quat2;
+ ensure(
+ "5. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed",
+ (-3.0f == result.mQ[0]) &&
+ (-0.5f == result.mQ[1]) &&
+ (-1.5f == result.mQ[2]) &&
+ (4.5f == result.mQ[3]));
+
+ result = quat3 - quat4;
+ ensure(
+ "6. LLQuaternion operator-(const LLQuaternion &a, const LLQuaternion &b) failed",
+ is_approx_equal(1667.273071f, result.mQ[0]) &&
+ is_approx_equal(1459.255249f, result.mQ[1]) &&
+ (-344.75f == result.mQ[2]) &&
+ (7414.50f == result.mQ[3]));
+ }
+
+ //test case for LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) fn.
+ template<> template<>
+ void llquat_test_object_t::test<10>()
+ {
+ LLVector4 vect(12.0f, 5.0f, 60.0f, 75.1f);
+ LLQuaternion quat(2323.034f, 23.5f, 673.23f, 57667.5f);
+ LLVector4 result = vect * quat;
+ ensure(
+ "1. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(39928406016.0f, result.mV[0]) &&
+ // gcc on x86 actually gives us more precision than we were expecting, verified with -ffloat-store - we forgive this
+ (1457802240.0f >= result.mV[1]) && // gcc+x86+linux
+ (1457800960.0f <= result.mV[1]) && // elsewhere
+ is_approx_equal(200580612096.0f, result.mV[2]) &&
+ (75.099998f == result.mV[3]));
+
+ LLVector4 vect1(22.0f, 45.0f, 40.0f, 78.1f);
+ LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f);
+ result = vect1 * quat1;
+ ensure(
+ "2. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(-58153.5390f, result.mV[0]) &&
+ (183787.8125f == result.mV[1]) &&
+ (116864.164063f == result.mV[2]) &&
+ (78.099998f == result.mV[3]));
+ }
+
+ //test case for LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) fn.
+ template<> template<>
+ void llquat_test_object_t::test<11>()
+ {
+ LLVector3 vect(12.0f, 5.0f, 60.0f);
+ LLQuaternion quat(23.5f, 6.5f, 3.23f, 56.5f);
+ LLVector3 result = vect * quat;
+ ensure(
+ "1. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(97182.953125f,result.mV[0]) &&
+ is_approx_equal(-135405.640625f, result.mV[1]) &&
+ is_approx_equal(162986.140f, result.mV[2]));
+
+ LLVector3 vect1(5.0f, 40.0f, 78.1f);
+ LLQuaternion quat1(2.034f, 45.5f, 37.23f, 7.5f);
+ result = vect1 * quat1;
+ ensure(
+ "2. LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) failed",
+ is_approx_equal(33217.703f, result.mV[0]) &&
+ is_approx_equal(295383.8125f, result.mV[1]) &&
+ is_approx_equal(84718.140f, result.mV[2]));
+ }
+
+ //test case for LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) fn.
+ template<> template<>
+ void llquat_test_object_t::test<12>()
+ {
+ LLVector3d vect(-2.0f, 5.0f, -6.0f);
+ LLQuaternion quat(-3.5f, 4.5f, 3.5f, 6.5f);
+ LLVector3d result = vect * quat;
+ ensure(
+ "1. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed ",
+ (-633.0f == result.mdV[0]) &&
+ (-300.0f == result.mdV[1]) &&
+ (-36.0f == result.mdV[2]));
+
+ LLVector3d vect1(5.0f, -4.5f, 8.21f);
+ LLQuaternion quat1(2.0f, 4.5f, -7.2f, 9.5f);
+ result = vect1 * quat1;
+ ensure(
+ "2. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed",
+ is_approx_equal_fraction(-120.29f, (F32) result.mdV[0], 8) &&
+ is_approx_equal_fraction(-1683.958f, (F32) result.mdV[1], 8) &&
+ is_approx_equal_fraction(516.56f, (F32) result.mdV[2], 8));
+
+ LLVector3d vect2(2.0f, 3.5f, 1.1f);
+ LLQuaternion quat2(1.0f, 4.0f, 2.0f, 5.0f);
+ result = vect2 * quat2;
+ ensure(
+ "3. LLVector3d operator*(const LLVector3d &a, const LLQuaternion &rot) failed",
+ is_approx_equal_fraction(18.400001f, (F32) result.mdV[0], 8) &&
+ is_approx_equal_fraction(188.6f, (F32) result.mdV[1], 8) &&
+ is_approx_equal_fraction(32.20f, (F32) result.mdV[2], 8));
+ }
+
+ //test case for inline LLQuaternion operator-(const LLQuaternion &a) fn.
+ template<> template<>
+ void llquat_test_object_t::test<13>()
+ {
+ LLQuaternion quat(23.5f, 34.5f, 16723.4f, 324.7f);
+ LLQuaternion result = -quat;
+ ensure(
+ "1. LLQuaternion operator-(const LLQuaternion &a) failed",
+ (-23.5f == result.mQ[0]) &&
+ (-34.5f == result.mQ[1]) &&
+ (-16723.4f == result.mQ[2]) &&
+ (-324.7f == result.mQ[3]));
+
+ LLQuaternion quat1(-3.5f, -34.5f, -16.4f, -154.7f);
+ result = -quat1;
+ ensure(
+ "2. LLQuaternion operator-(const LLQuaternion &a) failed.",
+ (3.5f == result.mQ[0]) &&
+ (34.5f == result.mQ[1]) &&
+ (16.4f == result.mQ[2]) &&
+ (154.7f == result.mQ[3]));
+ }
+
+ //test case for inline LLQuaternion operator*(F32 a, const LLQuaternion &q) and
+ //inline LLQuaternion operator*(F32 a, const LLQuaternion &q) fns.
+ template<> template<>
+ void llquat_test_object_t::test<14>()
+ {
+ LLQuaternion quat_value(9.0f, 8.0f, 7.0f, 6.0f);
+ F32 a =3.5f;
+ LLQuaternion result = a * quat_value;
+ LLQuaternion result1 = quat_value * a;
+
+ ensure(
+ "1. LLQuaternion operator* failed",
+ (result.mQ[0] == result1.mQ[0]) &&
+ (result.mQ[1] == result1.mQ[1]) &&
+ (result.mQ[2] == result1.mQ[2]) &&
+ (result.mQ[3] == result1.mQ[3]));
+
+
+ LLQuaternion quat_val(9454.0f, 43568.3450f, 456343247.0343f, 2346.03434f);
+ a =-3324.3445f;
+ result = a * quat_val;
+ result1 = quat_val * a;
+
+ ensure(
+ "2. LLQuaternion operator* failed",
+ (result.mQ[0] == result1.mQ[0]) &&
+ (result.mQ[1] == result1.mQ[1]) &&
+ (result.mQ[2] == result1.mQ[2]) &&
+ (result.mQ[3] == result1.mQ[3]));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<15>()
+ {
+ // test cases for inline LLQuaternion operator~(const LLQuaternion &a)
+ LLQuaternion quat_val(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ LLQuaternion result = ~quat_val;
+ ensure(
+ "1. LLQuaternion operator~(const LLQuaternion &a) failed ",
+ (-2323.634f == result.mQ[0]) &&
+ (43535.4f == result.mQ[1]) &&
+ (-3455.88f == result.mQ[2]) &&
+ (-32232.45f == result.mQ[3]));
+
+ //test case for inline bool LLQuaternion::operator==(const LLQuaternion &b) const
+ LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ LLQuaternion quat_val2(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ ensure(
+ "2. LLQuaternion::operator==(const LLQuaternion &b) failed",
+ quat_val1 == quat_val2);
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<16>()
+ {
+ //test case for inline bool LLQuaternion::operator!=(const LLQuaternion &b) const
+ LLQuaternion quat_val1(2323.634f, -43535.4f, 3455.88f, -32232.45f);
+ LLQuaternion quat_val2(0, -43535.4f, 3455.88f, -32232.45f);
+ ensure("LLQuaternion::operator!=(const LLQuaternion &b) failed", quat_val1 != quat_val2);
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<17>()
+ {
+ //test case for LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order)
+ F32 x = 2.0f;
+ F32 y = 1.0f;
+ F32 z = 3.0f;
+
+ LLQuaternion result = mayaQ(x, y, z, LLQuaternion::XYZ);
+ ensure(
+ "1. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ",
+ is_approx_equal_fraction(0.0172174f, result.mQ[0], 16) &&
+ is_approx_equal_fraction(0.009179f, result.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026020f, result.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999471f, result.mQ[3], 16));
+
+ LLQuaternion result1 = mayaQ(x, y, z, LLQuaternion::YZX);
+ ensure(
+ "2. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XYZ",
+ is_approx_equal_fraction(0.017217f, result1.mQ[0], 16) &&
+ is_approx_equal_fraction(0.008265f, result1.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026324f, result1.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999471f, result1.mQ[3], 16));
+
+ LLQuaternion result2 = mayaQ(x, y, z, LLQuaternion::ZXY);
+ ensure(
+ "3. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZXY",
+ is_approx_equal_fraction(0.017674f, result2.mQ[0], 16) &&
+ is_approx_equal_fraction(0.008265f, result2.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026020f, result2.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999471f, result2.mQ[3], 16));
+
+ LLQuaternion result3 = mayaQ(x, y, z, LLQuaternion::XZY);
+ ensure(
+ "4. TLLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for XZY",
+ is_approx_equal_fraction(0.017674f, result3.mQ[0], 16) &&
+ is_approx_equal_fraction(0.009179f, result3.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026020f, result3.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999463f, result3.mQ[3], 16));
+
+ LLQuaternion result4 = mayaQ(x, y, z, LLQuaternion::YXZ);
+ ensure(
+ "5. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for YXZ",
+ is_approx_equal_fraction(0.017217f, result4.mQ[0], 16) &&
+ is_approx_equal_fraction(0.009179f, result4.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026324f, result4.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999463f, result4.mQ[3], 16));
+
+ LLQuaternion result5 = mayaQ(x, y, z, LLQuaternion::ZYX);
+ ensure(
+ "6. LLQuaternion mayaQ(F32 xRot, F32 yRot, F32 zRot, LLQuaternion::Order order) failed for ZYX",
+ is_approx_equal_fraction(0.017674f, result5.mQ[0], 16) &&
+ is_approx_equal_fraction(0.008265f, result5.mQ[1], 16) &&
+ is_approx_equal_fraction(0.026324f, result5.mQ[2], 16) &&
+ is_approx_equal_fraction(0.999463f, result5.mQ[3], 16));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<18>()
+ {
+ // test case for friend std::ostream& operator<<(std::ostream &s, const LLQuaternion &a) fn
+ LLQuaternion a(1.0f, 1.0f, 1.0f, 1.0f);
+ std::ostringstream result_value;
+ result_value << a;
+ ensure_equals("1. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }");
+
+ LLQuaternion b(-31.034f, 231.2340f, 3451.344320f, -341.0f);
+ std::ostringstream result_value1;
+ result_value1 << b;
+ ensure_equals("2. Operator << failed", result_value1.str(), "{ -31.034, 231.234, 3451.34, -341 }");
+
+ LLQuaternion c(1.0f, 2.2f, 3.3f, 4.4f);
+ result_value << c;
+ ensure_equals("3. Operator << failed", result_value.str(), "{ 1, 1, 1, 1 }{ 1, 2.2, 3.3, 4.4 }");
+
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<19>()
+ {
+ //test case for const char *OrderToString( const LLQuaternion::Order order ) fn
+ const char* result = OrderToString(LLQuaternion::XYZ);
+ ensure("1. OrderToString failed for XYZ", (0 == strcmp("XYZ", result)));
+
+ result = OrderToString(LLQuaternion::YZX);
+ ensure("2. OrderToString failed for YZX", (0 == strcmp("YZX", result)));
+
+ result = OrderToString(LLQuaternion::ZXY);
+ ensure(
+ "3. OrderToString failed for ZXY",
+ (0 == strcmp("ZXY", result)) &&
+ (0 != strcmp("XYZ", result)) &&
+ (0 != strcmp("YXZ", result)) &&
+ (0 != strcmp("ZYX", result)) &&
+ (0 != strcmp("XYZ", result)));
+
+ result = OrderToString(LLQuaternion::XZY);
+ ensure("4. OrderToString failed for XZY", (0 == strcmp("XZY", result)));
+
+ result = OrderToString(LLQuaternion::ZYX);
+ ensure("5. OrderToString failed for ZYX", (0 == strcmp("ZYX", result)));
+
+ result = OrderToString(LLQuaternion::YXZ);
+ ensure("6.OrderToString failed for YXZ", (0 == strcmp("YXZ", result)));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<20>()
+ {
+ //test case for LLQuaternion::Order StringToOrder( const char *str ) fn
+ int result = StringToOrder("XYZ");
+ ensure("1. LLQuaternion::Order StringToOrder(const char *str ) failed for XYZ", 0 == result);
+
+ result = StringToOrder("YZX");
+ ensure("2. LLQuaternion::Order StringToOrder(const char *str) failed for YZX", 1 == result);
+
+ result = StringToOrder("ZXY");
+ ensure("3. LLQuaternion::Order StringToOrder(const char *str) failed for ZXY", 2 == result);
+
+ result = StringToOrder("XZY");
+ ensure("4. LLQuaternion::Order StringToOrder(const char *str) failed for XZY", 3 == result);
+
+ result = StringToOrder("YXZ");
+ ensure("5. LLQuaternion::Order StringToOrder(const char *str) failed for YXZ", 4 == result);
+
+ result = StringToOrder("ZYX");
+ ensure("6. LLQuaternion::Order StringToOrder(const char *str) failed for ZYX", 5 == result);
+
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<21>()
+ {
+ //void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const fn
+ F32 angle_value = 90.0f;
+ LLVector3 vect(12.0f, 4.0f, 1.0f);
+ LLQuaternion llquat(angle_value, vect);
+ llquat.getAngleAxis(&angle_value, vect);
+ ensure(
+ "LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) failed",
+ is_approx_equal_fraction(2.035406f, angle_value, 16) &&
+ is_approx_equal_fraction(0.315244f, vect.mV[1], 16) &&
+ is_approx_equal_fraction(0.078811f, vect.mV[2], 16) &&
+ is_approx_equal_fraction(0.945733f, vect.mV[0], 16));
+ }
+
+ template<> template<>
+ void llquat_test_object_t::test<22>()
+ {
+ //test case for void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const fn
+ F32 roll = -12.0f;
+ F32 pitch = -22.43f;
+ F32 yaw = 11.0f;
+
+ LLQuaternion llquat;
+ llquat.getEulerAngles(&roll, &pitch, &yaw);
+ ensure(
+ "LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) failed",
+ is_approx_equal(0.000f, llquat.mQ[0]) &&
+ is_approx_equal(0.000f, llquat.mQ[1]) &&
+ is_approx_equal(0.000f, llquat.mQ[2]) &&
+ is_approx_equal(1.000f, llquat.mQ[3]));
+ }
+
+}
diff --git a/indra/llmath/tests/llrect_test.cpp b/indra/llmath/tests/llrect_test.cpp
new file mode 100644
index 0000000000..d740173e69
--- /dev/null
+++ b/indra/llmath/tests/llrect_test.cpp
@@ -0,0 +1,526 @@
+/**
+ * @file llrect_test.cpp
+ * @author Martin Reddy
+ * @date 2009-06-25
+ * @brief Test for llrect.cpp.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "../llrect.h"
+
+namespace tut
+{
+ struct LLRectData
+ {
+ };
+
+ typedef test_group<LLRectData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory llrect_test_factory("LLRect");
+}
+
+namespace tut
+{
+ template<> template<>
+ void object::test<1>()
+ {
+ //
+ // test the LLRect default constructor
+ //
+
+ LLSD zero;
+ zero.append(0); zero.append(0); zero.append(0); zero.append(0);
+
+ // default constructor
+ LLRect rect1;
+ ensure_equals("Empty rect", rect1.getValue(), zero);
+ ensure_equals("Empty rect left", rect1.mLeft, 0);
+ ensure_equals("Empty rect top", rect1.mTop, 0);
+ ensure_equals("Empty rect right", rect1.mRight, 0);
+ ensure_equals("Empty rect bottom", rect1.mBottom, 0);
+ ensure_equals("Empty rect width", rect1.getWidth(), 0);
+ ensure_equals("Empty rect height", rect1.getHeight(), 0);
+ ensure_equals("Empty rect centerx", rect1.getCenterX(), 0);
+ ensure_equals("Empty rect centery", rect1.getCenterY(), 0);
+ }
+
+ template<> template<>
+ void object::test<2>()
+ {
+ //
+ // test the LLRectf default constructor
+ //
+
+ LLSD zerof;
+ zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f); zerof.append(0.0f);
+
+ LLRectf rect2;
+ ensure_equals("Empty rectf", rect2.getValue(), zerof);
+ ensure_equals("Empty rectf left", rect2.mLeft, 0.0f);
+ ensure_equals("Empty rectf top", rect2.mTop, 0.0f);
+ ensure_equals("Empty rectf right", rect2.mRight, 0.0f);
+ ensure_equals("Empty rectf bottom", rect2.mBottom, 0.0f);
+ ensure_equals("Empty rectf width", rect2.getWidth(), 0.0f);
+ ensure_equals("Empty rectf height", rect2.getHeight(), 0.0f);
+ ensure_equals("Empty rectf centerx", rect2.getCenterX(), 0.0f);
+ ensure_equals("Empty rectf centery", rect2.getCenterY(), 0.0f);
+ }
+
+ template<> template<>
+ void object::test<3>()
+ {
+ //
+ // test the LLRect constructor from another LLRect
+ //
+
+ LLRect rect3(LLRect(1, 6, 7, 2));
+ ensure_equals("Default rect left", rect3.mLeft, 1);
+ ensure_equals("Default rect top", rect3.mTop, 6);
+ ensure_equals("Default rect right", rect3.mRight, 7);
+ ensure_equals("Default rect bottom", rect3.mBottom, 2);
+ ensure_equals("Default rect width", rect3.getWidth(), 6);
+ ensure_equals("Default rect height", rect3.getHeight(), 4);
+ ensure_equals("Default rect centerx", rect3.getCenterX(), 4);
+ ensure_equals("Default rect centery", rect3.getCenterY(), 4);
+ }
+
+ template<> template<>
+ void object::test<4>()
+ {
+ //
+ // test the LLRectf four-float constructor
+ //
+
+ LLRectf rect4(1.0f, 5.0f, 6.0f, 2.0f);
+ ensure_equals("Default rectf left", rect4.mLeft, 1.0f);
+ ensure_equals("Default rectf top", rect4.mTop, 5.0f);
+ ensure_equals("Default rectf right", rect4.mRight, 6.0f);
+ ensure_equals("Default rectf bottom", rect4.mBottom, 2.0f);
+ ensure_equals("Default rectf width", rect4.getWidth(), 5.0f);
+ ensure_equals("Default rectf height", rect4.getHeight(), 3.0f);
+ ensure_equals("Default rectf centerx", rect4.getCenterX(), 3.5f);
+ ensure_equals("Default rectf centery", rect4.getCenterY(), 3.5f);
+ }
+
+ template<> template<>
+ void object::test<5>()
+ {
+ //
+ // test the LLRectf LLSD constructor
+ //
+
+ LLSD array;
+ array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f);
+ LLRectf rect5(array);
+ ensure_equals("LLSD rectf left", rect5.mLeft, -1.0f);
+ ensure_equals("LLSD rectf top", rect5.mTop, 0.0f);
+ ensure_equals("LLSD rectf right", rect5.mRight, 0.0f);
+ ensure_equals("LLSD rectf bottom", rect5.mBottom, -1.0f);
+ ensure_equals("LLSD rectf width", rect5.getWidth(), 1.0f);
+ ensure_equals("LLSD rectf height", rect5.getHeight(), 1.0f);
+ ensure_equals("LLSD rectf centerx", rect5.getCenterX(), -0.5f);
+ ensure_equals("LLSD rectf centery", rect5.getCenterY(), -0.5f);
+ }
+
+ template<> template<>
+ void object::test<6>()
+ {
+ //
+ // test directly setting the member variables for dimensions
+ //
+
+ LLRectf rectf;
+
+ rectf.mLeft = -1.0f;
+ rectf.mTop = 1.0f;
+ rectf.mRight = 1.0f;
+ rectf.mBottom = -1.0f;
+ ensure_equals("Member-set rectf left", rectf.mLeft, -1.0f);
+ ensure_equals("Member-set rectf top", rectf.mTop, 1.0f);
+ ensure_equals("Member-set rectf right", rectf.mRight, 1.0f);
+ ensure_equals("Member-set rectf bottom", rectf.mBottom, -1.0f);
+ ensure_equals("Member-set rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("Member-set rectf height", rectf.getHeight(), 2.0f);
+ ensure_equals("Member-set rectf centerx", rectf.getCenterX(), 0.0f);
+ ensure_equals("Member-set rectf centery", rectf.getCenterY(), 0.0f);
+ }
+
+ template<> template<>
+ void object::test<7>()
+ {
+ //
+ // test the setValue() method
+ //
+
+ LLRectf rectf;
+
+ LLSD array;
+ array.append(-1.0f); array.append(0.0f); array.append(0.0f); array.append(-1.0f);
+ rectf.setValue(array);
+ ensure_equals("setValue() rectf left", rectf.mLeft, -1.0f);
+ ensure_equals("setValue() rectf top", rectf.mTop, 0.0f);
+ ensure_equals("setValue() rectf right", rectf.mRight, 0.0f);
+ ensure_equals("setValue() rectf bottom", rectf.mBottom, -1.0f);
+ ensure_equals("setValue() rectf width", rectf.getWidth(), 1.0f);
+ ensure_equals("setValue() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setValue() rectf centerx", rectf.getCenterX(), -0.5f);
+ ensure_equals("setValue() rectf centery", rectf.getCenterY(), -0.5f);
+ }
+
+ template<> template<>
+ void object::test<8>()
+ {
+ //
+ // test the set() method
+ //
+
+ LLRect rect;
+
+ rect.set(10, 90, 70, 10);
+ ensure_equals("set() rectf left", rect.mLeft, 10);
+ ensure_equals("set() rectf top", rect.mTop, 90);
+ ensure_equals("set() rectf right", rect.mRight, 70);
+ ensure_equals("set() rectf bottom", rect.mBottom, 10);
+ ensure_equals("set() rectf width", rect.getWidth(), 60);
+ ensure_equals("set() rectf height", rect.getHeight(), 80);
+ ensure_equals("set() rectf centerx", rect.getCenterX(), 40);
+ ensure_equals("set() rectf centery", rect.getCenterY(), 50);
+ }
+
+ template<> template<>
+ void object::test<9>()
+ {
+ //
+ // test the setOriginAndSize() method
+ //
+
+ LLRectf rectf;
+
+ rectf.setOriginAndSize(0.0f, 0.0f, 2.0f, 1.0f);
+ ensure_equals("setOriginAndSize() rectf left", rectf.mLeft, 0.0f);
+ ensure_equals("setOriginAndSize() rectf top", rectf.mTop, 1.0f);
+ ensure_equals("setOriginAndSize() rectf right", rectf.mRight, 2.0f);
+ ensure_equals("setOriginAndSize() rectf bottom", rectf.mBottom, 0.0f);
+ ensure_equals("setOriginAndSize() rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("setOriginAndSize() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setOriginAndSize() rectf centerx", rectf.getCenterX(), 1.0f);
+ ensure_equals("setOriginAndSize() rectf centery", rectf.getCenterY(), 0.5f);
+ }
+
+ template<> template<>
+ void object::test<10>()
+ {
+ //
+ // test the setLeftTopAndSize() method
+ //
+
+ LLRectf rectf;
+
+ rectf.setLeftTopAndSize(0.0f, 0.0f, 2.0f, 1.0f);
+ ensure_equals("setLeftTopAndSize() rectf left", rectf.mLeft, 0.0f);
+ ensure_equals("setLeftTopAndSize() rectf top", rectf.mTop, 0.0f);
+ ensure_equals("setLeftTopAndSize() rectf right", rectf.mRight, 2.0f);
+ ensure_equals("setLeftTopAndSize() rectf bottom", rectf.mBottom, -1.0f);
+ ensure_equals("setLeftTopAndSize() rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("setLeftTopAndSize() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setLeftTopAndSize() rectf centerx", rectf.getCenterX(), 1.0f);
+ ensure_equals("setLeftTopAndSize() rectf centery", rectf.getCenterY(), -0.5f);
+ }
+
+ template<> template<>
+ void object::test<11>()
+ {
+ //
+ // test the setCenterAndSize() method
+ //
+
+ LLRectf rectf;
+
+ rectf.setCenterAndSize(0.0f, 0.0f, 2.0f, 1.0f);
+ ensure_equals("setCenterAndSize() rectf left", rectf.mLeft, -1.0f);
+ ensure_equals("setCenterAndSize() rectf top", rectf.mTop, 0.5f);
+ ensure_equals("setCenterAndSize() rectf right", rectf.mRight, 1.0f);
+ ensure_equals("setCenterAndSize() rectf bottom", rectf.mBottom, -0.5f);
+ ensure_equals("setCenterAndSize() rectf width", rectf.getWidth(), 2.0f);
+ ensure_equals("setCenterAndSize() rectf height", rectf.getHeight(), 1.0f);
+ ensure_equals("setCenterAndSize() rectf centerx", rectf.getCenterX(), 0.0f);
+ ensure_equals("setCenterAndSize() rectf centery", rectf.getCenterY(), 0.0f);
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ //
+ // test the validity checking method
+ //
+
+ LLRectf rectf;
+
+ rectf.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ ensure("BBox is valid", rectf.isValid());
+
+ rectf.mLeft = 2.0f;
+ ensure("BBox is not valid", ! rectf.isValid());
+
+ rectf.makeValid();
+ ensure("BBox forced valid", rectf.isValid());
+
+ rectf.set(-1.0f, -1.0f, -1.0f, -1.0f);
+ ensure("BBox(0,0,0,0) is valid", rectf.isValid());
+ }
+
+ template<> template<>
+ void object::test<13>()
+ {
+ //
+ // test the null checking methods
+ //
+
+ LLRectf rectf;
+
+ rectf.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ ensure("BBox is not Null", ! rectf.isEmpty());
+ ensure("BBox notNull", rectf.notEmpty());
+
+ rectf.mLeft = 2.0f;
+ rectf.makeValid();
+ ensure("BBox is now Null", rectf.isEmpty());
+
+ rectf.set(-1.0f, -1.0f, -1.0f, -1.0f);
+ ensure("BBox(0,0,0,0) is Null", rectf.isEmpty());
+ }
+
+ template<> template<>
+ void object::test<14>()
+ {
+ //
+ // test the (in)equality operators
+ //
+
+ LLRectf rect1, rect2;
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-1.0f, 0.9f, 1.0f, -1.0f);
+
+ ensure("rect1 == rect2 (false)", ! (rect1 == rect2));
+ ensure("rect1 != rect2 (true)", rect1 != rect2);
+
+ ensure("rect1 == rect1 (true)", rect1 == rect1);
+ ensure("rect1 != rect1 (false)", ! (rect1 != rect1));
+ }
+
+ template<> template<>
+ void object::test<15>()
+ {
+ //
+ // test the copy constructor
+ //
+
+ LLRectf rect1, rect2(rect1);
+
+ ensure("rect1 == rect2 (true)", rect1 == rect2);
+ ensure("rect1 != rect2 (false)", ! (rect1 != rect2));
+ }
+
+ template<> template<>
+ void object::test<16>()
+ {
+ //
+ // test the translate() method
+ //
+
+ LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f);
+ LLRectf rect2(rect1);
+
+ rect1.translate(0.0f, 0.0f);
+
+ ensure("translate(0, 0)", rect1 == rect2);
+
+ rect1.translate(100.0f, 100.0f);
+ rect1.translate(-100.0f, -100.0f);
+
+ ensure("translate(100, 100) + translate(-100, -100)", rect1 == rect2);
+
+ rect1.translate(10.0f, 0.0f);
+ rect2.set(9.0f, 1.0f, 11.0f, -1.0f);
+ ensure("translate(10, 0)", rect1 == rect2);
+
+ rect1.translate(0.0f, 10.0f);
+ rect2.set(9.0f, 11.0f, 11.0f, 9.0f);
+ ensure("translate(0, 10)", rect1 == rect2);
+
+ rect1.translate(-10.0f, -10.0f);
+ rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ ensure("translate(-10, -10)", rect1 == rect2);
+ }
+
+ template<> template<>
+ void object::test<17>()
+ {
+ //
+ // test the stretch() method
+ //
+
+ LLRectf rect1(-1.0f, 1.0f, 1.0f, -1.0f);
+ LLRectf rect2(rect1);
+
+ rect1.stretch(0.0f);
+ ensure("stretch(0)", rect1 == rect2);
+
+ rect1.stretch(0.0f, 0.0f);
+ ensure("stretch(0, 0)", rect1 == rect2);
+
+ rect1.stretch(10.0f);
+ rect1.stretch(-10.0f);
+ ensure("stretch(10) + stretch(-10)", rect1 == rect2);
+
+ rect1.stretch(2.0f, 1.0f);
+ rect2.set(-3.0f, 2.0f, 3.0f, -2.0f);
+ ensure("stretch(2, 1)", rect1 == rect2);
+ }
+
+
+ template<> template<>
+ void object::test<18>()
+ {
+ //
+ // test the unionWith() method
+ //
+
+ LLRectf rect1, rect2, rect3;
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect3 = rect1;
+ rect3.unionWith(rect2);
+ ensure_equals("union with self", rect3, rect1);
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-2.0f, 2.0f, 0.0f, 0.0f);
+ rect3 = rect1;
+ rect3.unionWith(rect2);
+ ensure_equals("union - overlap", rect3, LLRectf(-2.0f, 2.0f, 1.0f, -1.0f));
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(5.0f, 10.0f, 10.0f, 5.0f);
+ rect3 = rect1;
+ rect3.unionWith(rect2);
+ ensure_equals("union - no overlap", rect3, LLRectf(-1.0f, 10.0f, 10.0f, -1.0f));
+ }
+
+ template<> template<>
+ void object::test<19>()
+ {
+ //
+ // test the intersectWith() methods
+ //
+
+ LLRectf rect1, rect2, rect3;
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect3 = rect1;
+ rect3.intersectWith(rect2);
+ ensure_equals("intersect with self", rect3, rect1);
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(-2.0f, 2.0f, 0.0f, 0.0f);
+ rect3 = rect1;
+ rect3.intersectWith(rect2);
+ ensure_equals("intersect - overlap", rect3, LLRectf(-1.0f, 1.0f, 0.0f, 0.0f));
+
+ rect1.set(-1.0f, 1.0f, 1.0f, -1.0f);
+ rect2.set(5.0f, 10.0f, 10.0f, 5.0f);
+ rect3 = rect1;
+ rect3.intersectWith(rect2);
+ ensure("intersect - no overlap", rect3.isEmpty());
+ }
+
+ template<> template<>
+ void object::test<20>()
+ {
+ //
+ // test the pointInRect() method
+ //
+
+ LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
+
+ ensure("(0,0) not in rect", rect.pointInRect(0.0f, 0.0f) == FALSE);
+ ensure("(2,2) in rect", rect.pointInRect(2.0f, 2.0f) == TRUE);
+ ensure("(1,1) in rect", rect.pointInRect(1.0f, 1.0f) == TRUE);
+ ensure("(3,3) not in rect", rect.pointInRect(3.0f, 3.0f) == FALSE);
+ ensure("(2.999,2.999) in rect", rect.pointInRect(2.999f, 2.999f) == TRUE);
+ ensure("(2.999,3.0) not in rect", rect.pointInRect(2.999f, 3.0f) == FALSE);
+ ensure("(3.0,2.999) not in rect", rect.pointInRect(3.0f, 2.999f) == FALSE);
+ }
+
+ template<> template<>
+ void object::test<21>()
+ {
+ //
+ // test the localPointInRect() method
+ //
+
+ LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
+
+ ensure("(0,0) in local rect", rect.localPointInRect(0.0f, 0.0f) == TRUE);
+ ensure("(-0.0001,-0.0001) not in local rect", rect.localPointInRect(-0.0001f, -0.001f) == FALSE);
+ ensure("(1,1) in local rect", rect.localPointInRect(1.0f, 1.0f) == TRUE);
+ ensure("(2,2) not in local rect", rect.localPointInRect(2.0f, 2.0f) == FALSE);
+ ensure("(1.999,1.999) in local rect", rect.localPointInRect(1.999f, 1.999f) == TRUE);
+ ensure("(1.999,2.0) not in local rect", rect.localPointInRect(1.999f, 2.0f) == FALSE);
+ ensure("(2.0,1.999) not in local rect", rect.localPointInRect(2.0f, 1.999f) == FALSE);
+ }
+
+ template<> template<>
+ void object::test<22>()
+ {
+ //
+ // test the clampPointToRect() method
+ //
+
+ LLRectf rect(1.0f, 3.0f, 3.0f, 1.0f);
+ F32 x, y;
+
+ x = 2.0f; y = 2.0f;
+ rect.clampPointToRect(x, y);
+ ensure_equals("clamp x-coord within rect", x, 2.0f);
+ ensure_equals("clamp y-coord within rect", y, 2.0f);
+
+ x = -100.0f; y = 100.0f;
+ rect.clampPointToRect(x, y);
+ ensure_equals("clamp x-coord outside rect", x, 1.0f);
+ ensure_equals("clamp y-coord outside rect", y, 3.0f);
+
+ x = 3.0f; y = 1.0f;
+ rect.clampPointToRect(x, y);
+ ensure_equals("clamp x-coord edge rect", x, 3.0f);
+ ensure_equals("clamp y-coord edge rect", y, 1.0f);
+ }
+}
diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp
new file mode 100644
index 0000000000..8abf61b740
--- /dev/null
+++ b/indra/llmath/tests/m3math_test.cpp
@@ -0,0 +1,321 @@
+/**
+ * @file m3math_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief Test cases of m3math.h
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../m3math.h"
+#include "../v3math.h"
+#include "../v4math.h"
+#include "../m4math.h"
+#include "../llquaternion.h"
+#include "../v3dmath.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct m3math_test
+ {
+ };
+ typedef test_group<m3math_test> m3math_test_t;
+ typedef m3math_test_t::object m3math_test_object_t;
+ tut::m3math_test_t tut_m3math_test("m3math_h");
+
+ //test case for setIdentity() fn.
+ template<> template<>
+ void m3math_test_object_t::test<1>()
+ {
+ LLMatrix3 llmat3_obj;
+ llmat3_obj.setIdentity();
+ ensure("LLMatrix3::setIdentity failed", 1.f == llmat3_obj.mMatrix[0][0] &&
+ 0.f == llmat3_obj.mMatrix[0][1] &&
+ 0.f == llmat3_obj.mMatrix[0][2] &&
+ 0.f == llmat3_obj.mMatrix[1][0] &&
+ 1.f == llmat3_obj.mMatrix[1][1] &&
+ 0.f == llmat3_obj.mMatrix[1][2] &&
+ 0.f == llmat3_obj.mMatrix[2][0] &&
+ 0.f == llmat3_obj.mMatrix[2][1] &&
+ 1.f == llmat3_obj.mMatrix[2][2]);
+ }
+
+ //test case for LLMatrix3& setZero() fn.
+ template<> template<>
+ void m3math_test_object_t::test<2>()
+ {
+ LLMatrix3 llmat3_obj(30, 1, 2, 3);
+ llmat3_obj.setZero();
+
+ ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] &&
+ 0.f == llmat3_obj.setZero().mMatrix[0][1] &&
+ 0.f == llmat3_obj.setZero().mMatrix[0][2] &&
+ 0.f == llmat3_obj.setZero().mMatrix[1][0] &&
+ 0.f == llmat3_obj.setZero().mMatrix[1][1] &&
+ 0.f == llmat3_obj.setZero().mMatrix[1][2] &&
+ 0.f == llmat3_obj.setZero().mMatrix[2][0] &&
+ 0.f == llmat3_obj.setZero().mMatrix[2][1] &&
+ 0.f == llmat3_obj.setZero().mMatrix[2][2]);
+ }
+
+ //test case for setRows(const LLVector3 &x_axis, const LLVector3 &y_axis, const LLVector3 &z_axis) fns.
+ template<> template<>
+ void m3math_test_object_t::test<3>()
+ {
+ LLMatrix3 llmat3_obj;
+ LLVector3 vect1(2, 1, 4);
+ LLVector3 vect2(3, 5, 7);
+ LLVector3 vect3(6, 9, 7);
+ llmat3_obj.setRows(vect1, vect2, vect3);
+ ensure("LLVector3::setRows failed ", 2 == llmat3_obj.mMatrix[0][0] &&
+ 1 == llmat3_obj.mMatrix[0][1] &&
+ 4 == llmat3_obj.mMatrix[0][2] &&
+ 3 == llmat3_obj.mMatrix[1][0] &&
+ 5 == llmat3_obj.mMatrix[1][1] &&
+ 7 == llmat3_obj.mMatrix[1][2] &&
+ 6 == llmat3_obj.mMatrix[2][0] &&
+ 9 == llmat3_obj.mMatrix[2][1] &&
+ 7 == llmat3_obj.mMatrix[2][2]);
+ }
+
+ //test case for getFwdRow(), getLeftRow(), getUpRow() fns.
+ template<> template<>
+ void m3math_test_object_t::test<4>()
+ {
+ LLMatrix3 llmat3_obj;
+ LLVector3 vect1(2, 1, 4);
+ LLVector3 vect2(3, 5, 7);
+ LLVector3 vect3(6, 9, 7);
+ llmat3_obj.setRows(vect1, vect2, vect3);
+
+ ensure("LLVector3::getFwdRow failed ", vect1 == llmat3_obj.getFwdRow());
+ ensure("LLVector3::getLeftRow failed ", vect2 == llmat3_obj.getLeftRow());
+ ensure("LLVector3::getUpRow failed ", vect3 == llmat3_obj.getUpRow());
+ }
+
+ //test case for operator*(const LLMatrix3 &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<5>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLMatrix3 llmat_obj2;
+ LLMatrix3 llmat_obj3;
+
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 6, 1);
+ LLVector3 llvec3(4, 6, 9);
+
+ LLVector3 llvec4(1, 1, 5);
+ LLVector3 llvec5(3, 6, 8);
+ LLVector3 llvec6(8, 6, 2);
+
+ LLVector3 llvec7(0, 0, 0);
+ LLVector3 llvec8(0, 0, 0);
+ LLVector3 llvec9(0, 0, 0);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ llmat_obj2.setRows(llvec4, llvec5, llvec6);
+ llmat_obj3.setRows(llvec7, llvec8, llvec9);
+ llmat_obj3 = llmat_obj1 * llmat_obj2;
+ ensure("LLMatrix3::operator*(const LLMatrix3 &a, const LLMatrix3 &b) failed",
+ 50 == llmat_obj3.mMatrix[0][0] &&
+ 49 == llmat_obj3.mMatrix[0][1] &&
+ 39 == llmat_obj3.mMatrix[0][2] &&
+ 29 == llmat_obj3.mMatrix[1][0] &&
+ 45 == llmat_obj3.mMatrix[1][1] &&
+ 65 == llmat_obj3.mMatrix[1][2] &&
+ 94 == llmat_obj3.mMatrix[2][0] &&
+ 94 == llmat_obj3.mMatrix[2][1] &&
+ 86 == llmat_obj3.mMatrix[2][2]);
+ }
+
+
+ //test case for operator*(const LLVector3 &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<6>()
+ {
+
+ LLMatrix3 llmat_obj1;
+
+ LLVector3 llvec(1, 3, 5);
+ LLVector3 res_vec(0, 0, 0);
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 6, 1);
+ LLVector3 llvec3(4, 6, 9);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ res_vec = llvec * llmat_obj1;
+
+ LLVector3 expected_result(30, 51, 53);
+
+ ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", res_vec == expected_result);
+ }
+
+ //test case for operator*(const LLVector3d &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<7>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLVector3d llvec3d1;
+ LLVector3d llvec3d2(0, 3, 4);
+
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 2, 1);
+ LLVector3 llvec3(4, 6, 0);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ llvec3d1 = llvec3d2 * llmat_obj1;
+
+ LLVector3d expected_result(25, 30, 3);
+
+ ensure("LLMatrix3::operator*(const LLVector3 &a, const LLMatrix3 &b) failed", llvec3d1 == expected_result);
+ }
+
+ // test case for operator==(const LLMatrix3 &a, const LLMatrix3 &b)
+ template<> template<>
+ void m3math_test_object_t::test<8>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLMatrix3 llmat_obj2;
+
+ LLVector3 llvec1(1, 3, 5);
+ LLVector3 llvec2(3, 6, 1);
+ LLVector3 llvec3(4, 6, 9);
+
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ llmat_obj2.setRows(llvec1, llvec2, llvec3);
+ ensure("LLMatrix3::operator==(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 == llmat_obj2);
+
+ llmat_obj2.setRows(llvec2, llvec2, llvec3);
+ ensure("LLMatrix3::operator!=(const LLMatrix3 &a, const LLMatrix3 &b) failed", llmat_obj1 != llmat_obj2);
+ }
+
+ //test case for quaternion() fn.
+ template<> template<>
+ void m3math_test_object_t::test<9>()
+ {
+ LLMatrix3 llmat_obj1;
+ LLQuaternion llmat_quat;
+
+ LLVector3 llmat1(2.0f, 1.0f, 6.0f);
+ LLVector3 llmat2(1.0f, 1.0f, 3.0f);
+ LLVector3 llmat3(1.0f, 7.0f, 5.0f);
+
+ llmat_obj1.setRows(llmat1, llmat2, llmat3);
+ llmat_quat = llmat_obj1.quaternion();
+ ensure("LLMatrix3::quaternion failed ", is_approx_equal(-0.66666669f, llmat_quat.mQ[0]) &&
+ is_approx_equal(-0.83333337f, llmat_quat.mQ[1]) &&
+ is_approx_equal(0.0f, llmat_quat.mQ[2]) &&
+ is_approx_equal(1.5f, llmat_quat.mQ[3]));
+ }
+
+ //test case for transpose() fn.
+ template<> template<>
+ void m3math_test_object_t::test<10>()
+ {
+ LLMatrix3 llmat_obj;
+
+ LLVector3 llvec1(1, 2, 3);
+ LLVector3 llvec2(3, 2, 1);
+ LLVector3 llvec3(2, 2, 2);
+
+ llmat_obj.setRows(llvec1, llvec2, llvec3);
+ llmat_obj.transpose();
+
+ LLVector3 resllvec1(1, 3, 2);
+ LLVector3 resllvec2(2, 2, 2);
+ LLVector3 resllvec3(3, 1, 2);
+ LLMatrix3 expectedllmat_obj;
+ expectedllmat_obj.setRows(resllvec1, resllvec2, resllvec3);
+
+ ensure("LLMatrix3::transpose failed ", llmat_obj == expectedllmat_obj);
+ }
+
+ //test case for determinant() fn.
+ template<> template<>
+ void m3math_test_object_t::test<11>()
+ {
+ LLMatrix3 llmat_obj1;
+
+ LLVector3 llvec1(1, 2, 3);
+ LLVector3 llvec2(3, 2, 1);
+ LLVector3 llvec3(2, 2, 2);
+ llmat_obj1.setRows(llvec1, llvec2, llvec3);
+ ensure("LLMatrix3::determinant failed ", 0.0f == llmat_obj1.determinant());
+ }
+
+ //test case for orthogonalize() fn.
+ template<> template<>
+ void m3math_test_object_t::test<12>()
+ {
+ LLMatrix3 llmat_obj;
+
+ LLVector3 llvec1(1, 4, 3);
+ LLVector3 llvec2(1, 2, 0);
+ LLVector3 llvec3(2, 4, 2);
+
+ llmat_obj.setRows(llvec1, llvec2, llvec3);
+ llmat_obj.orthogonalize();
+
+ skip("Grr, LLMatrix3::orthogonalize test is failing. Has it ever worked?");
+ ensure("LLMatrix3::orthogonalize failed ",
+ is_approx_equal(0.19611613f, llmat_obj.mMatrix[0][0]) &&
+ is_approx_equal(0.78446454f, llmat_obj.mMatrix[0][1]) &&
+ is_approx_equal(0.58834839f, llmat_obj.mMatrix[0][2]) &&
+ is_approx_equal(0.47628206f, llmat_obj.mMatrix[1][0]) &&
+ is_approx_equal(0.44826555f, llmat_obj.mMatrix[1][1]) &&
+ is_approx_equal(-0.75644791f, llmat_obj.mMatrix[1][2]) &&
+ is_approx_equal(-0.85714287f, llmat_obj.mMatrix[2][0]) &&
+ is_approx_equal(0.42857143f, llmat_obj.mMatrix[2][1]) &&
+ is_approx_equal(-0.28571427f, llmat_obj.mMatrix[2][2]));
+ }
+
+ //test case for adjointTranspose() fn.
+ template<> template<>
+ void m3math_test_object_t::test<13>()
+ {
+ LLMatrix3 llmat_obj;
+
+ LLVector3 llvec1(3, 2, 1);
+ LLVector3 llvec2(6, 2, 1);
+ LLVector3 llvec3(3, 6, 8);
+
+ llmat_obj.setRows(llvec1, llvec2, llvec3);
+ llmat_obj.adjointTranspose();
+
+ ensure("LLMatrix3::adjointTranspose failed ", 10 == llmat_obj.mMatrix[0][0] &&
+ -45 == llmat_obj.mMatrix[1][0] &&
+ 30 == llmat_obj.mMatrix[2][0] &&
+ -10 == llmat_obj.mMatrix[0][1] &&
+ 21 == llmat_obj.mMatrix[1][1] &&
+ -12 == llmat_obj.mMatrix[2][1] &&
+ 0 == llmat_obj.mMatrix[0][2] &&
+ 3 == llmat_obj.mMatrix[1][2] &&
+ -6 == llmat_obj.mMatrix[2][2]);
+ }
+
+ /* TBD: Need to add test cases for getEulerAngles() and setRot() functions */
+}
diff --git a/indra/llmath/tests/mathmisc_test.cpp b/indra/llmath/tests/mathmisc_test.cpp
new file mode 100644
index 0000000000..91a2e6c009
--- /dev/null
+++ b/indra/llmath/tests/mathmisc_test.cpp
@@ -0,0 +1,723 @@
+/**
+ * @file math.cpp
+ * @author Phoenix
+ * @date 2005-09-26
+ * @brief Tests for the llmath library.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "llcrc.h"
+#include "llrand.h"
+#include "lluuid.h"
+
+#include "../llline.h"
+#include "../llmath.h"
+#include "../llsphere.h"
+#include "../v3math.h"
+
+namespace tut
+{
+ struct math_data
+ {
+ };
+ typedef test_group<math_data> math_test;
+ typedef math_test::object math_object;
+ tut::math_test tm("BasicLindenMath");
+
+ template<> template<>
+ void math_object::test<1>()
+ {
+ S32 val = 89543;
+ val = llabs(val);
+ ensure("integer absolute value 1", (89543 == val));
+ val = -500;
+ val = llabs(val);
+ ensure("integer absolute value 2", (500 == val));
+ }
+
+ template<> template<>
+ void math_object::test<2>()
+ {
+ F32 val = -2583.4f;
+ val = llabs(val);
+ ensure("float absolute value 1", (2583.4f == val));
+ val = 430903.f;
+ val = llabs(val);
+ ensure("float absolute value 2", (430903.f == val));
+ }
+
+ template<> template<>
+ void math_object::test<3>()
+ {
+ F64 val = 387439393.987329839;
+ val = llabs(val);
+ ensure("double absolute value 1", (387439393.987329839 == val));
+ val = -8937843.9394878;
+ val = llabs(val);
+ ensure("double absolute value 2", (8937843.9394878 == val));
+ }
+
+ template<> template<>
+ void math_object::test<4>()
+ {
+ F32 val = 430903.9f;
+ S32 val1 = lltrunc(val);
+ ensure("float truncate value 1", (430903 == val1));
+ val = -2303.9f;
+ val1 = lltrunc(val);
+ ensure("float truncate value 2", (-2303 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<5>()
+ {
+ F64 val = 387439393.987329839 ;
+ S32 val1 = lltrunc(val);
+ ensure("float truncate value 1", (387439393 == val1));
+ val = -387439393.987329839;
+ val1 = lltrunc(val);
+ ensure("float truncate value 2", (-387439393 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<6>()
+ {
+ F32 val = 430903.2f;
+ S32 val1 = llfloor(val);
+ ensure("float llfloor value 1", (430903 == val1));
+ val = -430903.9f;
+ val1 = llfloor(val);
+ ensure("float llfloor value 2", (-430904 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<7>()
+ {
+ F32 val = 430903.2f;
+ S32 val1 = llceil(val);
+ ensure("float llceil value 1", (430904 == val1));
+ val = -430903.9f;
+ val1 = llceil(val);
+ ensure("float llceil value 2", (-430903 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<8>()
+ {
+ F32 val = 430903.2f;
+ S32 val1 = llround(val);
+ ensure("float llround value 1", (430903 == val1));
+ val = -430903.9f;
+ val1 = llround(val);
+ ensure("float llround value 2", (-430904 == val1));
+ }
+
+ template<> template<>
+ void math_object::test<9>()
+ {
+ F32 val = 430905.2654f, nearest = 100.f;
+ val = llround(val, nearest);
+ ensure("float llround value 1", (430900 == val));
+ val = -430905.2654f, nearest = 10.f;
+ val = llround(val, nearest);
+ ensure("float llround value 1", (-430910 == val));
+ }
+
+ template<> template<>
+ void math_object::test<10>()
+ {
+ F64 val = 430905.2654, nearest = 100.0;
+ val = llround(val, nearest);
+ ensure("double llround value 1", (430900 == val));
+ val = -430905.2654, nearest = 10.0;
+ val = llround(val, nearest);
+ ensure("double llround value 1", (-430910.00000 == val));
+ }
+
+ template<> template<>
+ void math_object::test<11>()
+ {
+ const F32 F_PI = 3.1415926535897932384626433832795f;
+ F32 angle = 3506.f;
+ angle = llsimple_angle(angle);
+ ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI));
+ angle = -431.f;
+ angle = llsimple_angle(angle);
+ ensure("llsimple_angle value 1", (angle <=F_PI && angle >= -F_PI));
+ }
+}
+
+namespace tut
+{
+ struct uuid_data
+ {
+ LLUUID id;
+ };
+ typedef test_group<uuid_data> uuid_test;
+ typedef uuid_test::object uuid_object;
+ tut::uuid_test tu("LLUUID");
+
+ template<> template<>
+ void uuid_object::test<1>()
+ {
+ ensure("uuid null", id.isNull());
+ id.generate();
+ ensure("generate not null", id.notNull());
+ id.setNull();
+ ensure("set null", id.isNull());
+ }
+
+ template<> template<>
+ void uuid_object::test<2>()
+ {
+ id.generate();
+ LLUUID a(id);
+ ensure_equals("copy equal", id, a);
+ a.generate();
+ ensure_not_equals("generate not equal", id, a);
+ a = id;
+ ensure_equals("assignment equal", id, a);
+ }
+
+ template<> template<>
+ void uuid_object::test<3>()
+ {
+ id.generate();
+ LLUUID copy(id);
+ LLUUID mask;
+ mask.generate();
+ copy ^= mask;
+ ensure_not_equals("mask not equal", id, copy);
+ copy ^= mask;
+ ensure_equals("mask back", id, copy);
+ }
+
+ template<> template<>
+ void uuid_object::test<4>()
+ {
+ id.generate();
+ std::string id_str = id.asString();
+ LLUUID copy(id_str.c_str());
+ ensure_equals("string serialization", id, copy);
+ }
+
+}
+
+namespace tut
+{
+ struct crc_data
+ {
+ };
+ typedef test_group<crc_data> crc_test;
+ typedef crc_test::object crc_object;
+ tut::crc_test tc("LLCrc");
+
+ template<> template<>
+ void crc_object::test<1>()
+ {
+ /* Test buffer update and individual char update */
+ const char TEST_BUFFER[] = "hello &#$)$&Nd0";
+ LLCRC c1, c2;
+ c1.update((U8*)TEST_BUFFER, sizeof(TEST_BUFFER) - 1);
+ char* rh = (char*)TEST_BUFFER;
+ while(*rh != '\0')
+ {
+ c2.update(*rh);
+ ++rh;
+ }
+ ensure_equals("crc update 1", c1.getCRC(), c2.getCRC());
+ }
+
+ template<> template<>
+ void crc_object::test<2>()
+ {
+ /* Test mixing of buffer and individual char update */
+ const char TEST_BUFFER1[] = "Split Buffer one $^%$%#@$";
+ const char TEST_BUFFER2[] = "Split Buffer two )(8723#5dsds";
+ LLCRC c1, c2;
+ c1.update((U8*)TEST_BUFFER1, sizeof(TEST_BUFFER1) - 1);
+ char* rh = (char*)TEST_BUFFER2;
+ while(*rh != '\0')
+ {
+ c1.update(*rh);
+ ++rh;
+ }
+
+ rh = (char*)TEST_BUFFER1;
+ while(*rh != '\0')
+ {
+ c2.update(*rh);
+ ++rh;
+ }
+ c2.update((U8*)TEST_BUFFER2, sizeof(TEST_BUFFER2) - 1);
+
+ ensure_equals("crc update 2", c1.getCRC(), c2.getCRC());
+ }
+}
+
+namespace tut
+{
+ struct sphere_data
+ {
+ };
+ typedef test_group<sphere_data> sphere_test;
+ typedef sphere_test::object sphere_object;
+ tut::sphere_test tsphere("LLSphere");
+
+ template<> template<>
+ void sphere_object::test<1>()
+ {
+ // test LLSphere::contains() and ::overlaps()
+ S32 number_of_tests = 10;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ LLVector3 first_center(1.f, 1.f, 1.f);
+ F32 first_radius = 3.f;
+ LLSphere first_sphere( first_center, first_radius );
+
+ F32 half_millimeter = 0.0005f;
+ LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
+ direction.normalize();
+
+ F32 distance = ll_frand(first_radius - 2.f * half_millimeter);
+ LLVector3 second_center = first_center + distance * direction;
+ F32 second_radius = first_radius - distance - half_millimeter;
+ LLSphere second_sphere( second_center, second_radius );
+ ensure("first sphere should contain the second", first_sphere.contains(second_sphere));
+ ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
+
+ distance = first_radius + ll_frand(first_radius);
+ second_center = first_center + distance * direction;
+ second_radius = distance - first_radius + half_millimeter;
+ second_sphere.set( second_center, second_radius );
+ ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
+ ensure("first sphere should overlap the second", first_sphere.overlaps(second_sphere));
+
+ distance = first_radius + ll_frand(first_radius) + half_millimeter;
+ second_center = first_center + distance * direction;
+ second_radius = distance - first_radius - half_millimeter;
+ second_sphere.set( second_center, second_radius );
+ ensure("first sphere should NOT contain the second", !first_sphere.contains(second_sphere));
+ ensure("first sphere should NOT overlap the second", !first_sphere.overlaps(second_sphere));
+ }
+ }
+
+ template<> template<>
+ void sphere_object::test<2>()
+ {
+ skip("See SNOW-620. Neither the test nor the code being tested seem good. Also sim-only.");
+
+ // test LLSphere::getBoundingSphere()
+ S32 number_of_tests = 100;
+ S32 number_of_spheres = 10;
+ F32 sphere_center_range = 32.f;
+ F32 sphere_radius_range = 5.f;
+
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // gegnerate a bunch of random sphere
+ std::vector< LLSphere > sphere_list;
+ for (S32 sphere_count=0; sphere_count < number_of_spheres; ++sphere_count)
+ {
+ LLVector3 direction( ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f, ll_frand(2.f) - 1.f);
+ direction.normalize();
+ F32 distance = ll_frand(sphere_center_range);
+ LLVector3 center = distance * direction;
+ F32 radius = ll_frand(sphere_radius_range);
+ LLSphere sphere( center, radius );
+ sphere_list.push_back(sphere);
+ }
+
+ // compute the bounding sphere
+ LLSphere bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
+
+ // make sure all spheres are inside the bounding sphere
+ {
+ std::vector< LLSphere >::const_iterator sphere_itr;
+ for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
+ {
+ ensure("sphere should be contained by the bounding sphere", bounding_sphere.contains(*sphere_itr));
+ }
+ }
+
+ // TODO -- improve LLSphere::getBoundingSphere() to the point where
+ // we can reduce the 'expansion' in the two tests below to about
+ // 2 mm or less
+
+ F32 expansion = 0.005f;
+ // move all spheres out a little bit
+ // and count how many are NOT contained
+ {
+ std::vector< LLVector3 > uncontained_directions;
+ std::vector< LLSphere >::iterator sphere_itr;
+ for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
+ {
+ LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
+ direction.normalize();
+
+ sphere_itr->setCenter( sphere_itr->getCenter() + expansion * direction );
+ if (! bounding_sphere.contains( *sphere_itr ) )
+ {
+ uncontained_directions.push_back(direction);
+ }
+ }
+ ensure("when moving spheres out there should be at least two uncontained spheres",
+ uncontained_directions.size() > 1);
+
+ /* TODO -- when the bounding sphere algorithm is improved we can open up this test
+ * at the moment it occasionally fails when the sphere collection is tight and small
+ * (2 meters or less)
+ if (2 == uncontained_directions.size() )
+ {
+ // if there were only two uncontained spheres then
+ // the two directions should be nearly opposite
+ F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
+ ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
+ }
+ */
+ }
+
+ // compute the new bounding sphere
+ bounding_sphere = LLSphere::getBoundingSphere(sphere_list);
+
+ // increase the size of all spheres a little bit
+ // and count how many are NOT contained
+ {
+ std::vector< LLVector3 > uncontained_directions;
+ std::vector< LLSphere >::iterator sphere_itr;
+ for (sphere_itr = sphere_list.begin(); sphere_itr != sphere_list.end(); ++sphere_itr)
+ {
+ LLVector3 direction = sphere_itr->getCenter() - bounding_sphere.getCenter();
+ direction.normalize();
+
+ sphere_itr->setRadius( sphere_itr->getRadius() + expansion );
+ if (! bounding_sphere.contains( *sphere_itr ) )
+ {
+ uncontained_directions.push_back(direction);
+ }
+ }
+ ensure("when boosting sphere radii there should be at least two uncontained spheres",
+ uncontained_directions.size() > 1);
+
+ /* TODO -- when the bounding sphere algorithm is improved we can open up this test
+ * at the moment it occasionally fails when the sphere collection is tight and small
+ * (2 meters or less)
+ if (2 == uncontained_directions.size() )
+ {
+ // if there were only two uncontained spheres then
+ // the two directions should be nearly opposite
+ F32 dir_dot = uncontained_directions[0] * uncontained_directions[1];
+ ensure("two uncontained spheres should lie opposite the bounding center", dir_dot < -0.95f);
+ }
+ */
+ }
+ }
+ }
+}
+
+namespace tut
+{
+ F32 SMALL_RADIUS = 1.0f;
+ F32 MEDIUM_RADIUS = 5.0f;
+ F32 LARGE_RADIUS = 10.0f;
+
+ struct line_data
+ {
+ };
+ typedef test_group<line_data> line_test;
+ typedef line_test::object line_object;
+ tut::line_test tline("LLLine");
+
+ template<> template<>
+ void line_object::test<1>()
+ {
+ // this is a test for LLLine::intersects(point) which returns TRUE
+ // if the line passes within some tolerance of point
+
+ // these tests will have some floating point error,
+ // so we need to specify how much error is ok
+ F32 allowable_relative_error = 0.00001f;
+ S32 number_of_tests = 100;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // generate some random point to be on the line
+ LLVector3 point_on_line( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ point_on_line.normalize();
+ point_on_line *= ll_frand(LARGE_RADIUS);
+
+ // generate some random point to "intersect"
+ LLVector3 random_direction ( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ random_direction.normalize();
+
+ LLVector3 random_offset( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ random_offset.normalize();
+ random_offset *= ll_frand(SMALL_RADIUS);
+
+ LLVector3 point = point_on_line + MEDIUM_RADIUS * random_direction
+ + random_offset;
+
+ // compute the axis of approach (a unit vector between the points)
+ LLVector3 axis_of_approach = point - point_on_line;
+ axis_of_approach.normalize();
+
+ // compute the direction of the the first line (perp to axis_of_approach)
+ LLVector3 first_dir( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ first_dir.normalize();
+ F32 dot = first_dir * axis_of_approach;
+ first_dir -= dot * axis_of_approach; // subtract component parallel to axis
+ first_dir.normalize();
+
+ // construct the line
+ LLVector3 another_point_on_line = point_on_line + ll_frand(LARGE_RADIUS) * first_dir;
+ LLLine line(another_point_on_line, point_on_line);
+
+ // test that the intersection point is within MEDIUM_RADIUS + SMALL_RADIUS
+ F32 test_radius = MEDIUM_RADIUS + SMALL_RADIUS;
+ test_radius += (LARGE_RADIUS * allowable_relative_error);
+ ensure("line should pass near intersection point", line.intersects(point, test_radius));
+
+ test_radius = allowable_relative_error * (point - point_on_line).length();
+ ensure("line should intersect point used to define it", line.intersects(point_on_line, test_radius));
+ }
+ }
+
+ template<> template<>
+ void line_object::test<2>()
+ {
+ /*
+ These tests fail intermittently on all platforms - see DEV-16600
+ Commenting this out until dev has time to investigate.
+
+ // this is a test for LLLine::nearestApproach(LLLIne) method
+ // which computes the point on a line nearest another line
+
+ // these tests will have some floating point error,
+ // so we need to specify how much error is ok
+ // TODO -- make nearestApproach() algorithm more accurate so
+ // we can tighten the allowable_error. Most tests are tighter
+ // than one milimeter, however when doing randomized testing
+ // you can walk into inaccurate cases.
+ F32 allowable_relative_error = 0.001f;
+ S32 number_of_tests = 100;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // generate two points to be our known nearest approaches
+ LLVector3 some_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ some_point.normalize();
+ some_point *= ll_frand(LARGE_RADIUS);
+
+ LLVector3 another_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ another_point.normalize();
+ another_point *= ll_frand(LARGE_RADIUS);
+
+ // compute the axis of approach (a unit vector between the points)
+ LLVector3 axis_of_approach = another_point - some_point;
+ axis_of_approach.normalize();
+
+ // compute the direction of the the first line (perp to axis_of_approach)
+ LLVector3 first_dir( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ F32 dot = first_dir * axis_of_approach;
+ first_dir -= dot * axis_of_approach; // subtract component parallel to axis
+ first_dir.normalize(); // normalize
+
+ // compute the direction of the the second line
+ LLVector3 second_dir( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ dot = second_dir * axis_of_approach;
+ second_dir -= dot * axis_of_approach;
+ second_dir.normalize();
+
+ // make sure the lines aren't too parallel,
+ dot = fabsf(first_dir * second_dir);
+ if (dot > 0.99f)
+ {
+ // skip this test, we're not interested in testing
+ // the intractible cases
+ continue;
+ }
+
+ // construct the lines
+ LLVector3 first_point = some_point + ll_frand(LARGE_RADIUS) * first_dir;
+ LLLine first_line(first_point, some_point);
+
+ LLVector3 second_point = another_point + ll_frand(LARGE_RADIUS) * second_dir;
+ LLLine second_line(second_point, another_point);
+
+ // compute the points of nearest approach
+ LLVector3 some_computed_point = first_line.nearestApproach(second_line);
+ LLVector3 another_computed_point = second_line.nearestApproach(first_line);
+
+ // compute the error
+ F32 first_error = (some_point - some_computed_point).length();
+ F32 scale = llmax((some_point - another_point).length(), some_point.length());
+ scale = llmax(scale, another_point.length());
+ scale = llmax(scale, 1.f);
+ F32 first_relative_error = first_error / scale;
+
+ F32 second_error = (another_point - another_computed_point).length();
+ F32 second_relative_error = second_error / scale;
+
+ //if (first_relative_error > allowable_relative_error)
+ //{
+ // std::cout << "first_error = " << first_error
+ // << " first_relative_error = " << first_relative_error
+ // << " scale = " << scale
+ // << " dir_dot = " << (first_dir * second_dir)
+ // << std::endl;
+ //}
+ //if (second_relative_error > allowable_relative_error)
+ //{
+ // std::cout << "second_error = " << second_error
+ // << " second_relative_error = " << second_relative_error
+ // << " scale = " << scale
+ // << " dist = " << (some_point - another_point).length()
+ // << " dir_dot = " << (first_dir * second_dir)
+ // << std::endl;
+ //}
+
+ // test that the errors are small
+
+ ensure("first line should accurately compute its closest approach",
+ first_relative_error <= allowable_relative_error);
+ ensure("second line should accurately compute its closest approach",
+ second_relative_error <= allowable_relative_error);
+ }
+ */
+ }
+
+ F32 ALMOST_PARALLEL = 0.99f;
+ template<> template<>
+ void line_object::test<3>()
+ {
+ // this is a test for LLLine::getIntersectionBetweenTwoPlanes() method
+
+ // first some known tests
+ LLLine xy_plane(LLVector3(0.f, 0.f, 2.f), LLVector3(0.f, 0.f, 3.f));
+ LLLine yz_plane(LLVector3(2.f, 0.f, 0.f), LLVector3(3.f, 0.f, 0.f));
+ LLLine zx_plane(LLVector3(0.f, 2.f, 0.f), LLVector3(0.f, 3.f, 0.f));
+
+ LLLine x_line;
+ LLLine y_line;
+ LLLine z_line;
+
+ bool x_success = LLLine::getIntersectionBetweenTwoPlanes(x_line, xy_plane, zx_plane);
+ bool y_success = LLLine::getIntersectionBetweenTwoPlanes(y_line, yz_plane, xy_plane);
+ bool z_success = LLLine::getIntersectionBetweenTwoPlanes(z_line, zx_plane, yz_plane);
+
+ ensure("xy and zx planes should intersect", x_success);
+ ensure("yz and xy planes should intersect", y_success);
+ ensure("zx and yz planes should intersect", z_success);
+
+ LLVector3 direction = x_line.getDirection();
+ ensure("x_line should be parallel to x_axis", fabs(direction.mV[VX]) == 1.f
+ && 0.f == direction.mV[VY]
+ && 0.f == direction.mV[VZ] );
+ direction = y_line.getDirection();
+ ensure("y_line should be parallel to y_axis", 0.f == direction.mV[VX]
+ && fabs(direction.mV[VY]) == 1.f
+ && 0.f == direction.mV[VZ] );
+ direction = z_line.getDirection();
+ ensure("z_line should be parallel to z_axis", 0.f == direction.mV[VX]
+ && 0.f == direction.mV[VY]
+ && fabs(direction.mV[VZ]) == 1.f );
+
+ // next some random tests
+ F32 allowable_relative_error = 0.0001f;
+ S32 number_of_tests = 20;
+ for (S32 test = 0; test < number_of_tests; ++test)
+ {
+ // generate the known line
+ LLVector3 some_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ some_point.normalize();
+ some_point *= ll_frand(LARGE_RADIUS);
+ LLVector3 another_point( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ another_point.normalize();
+ another_point *= ll_frand(LARGE_RADIUS);
+ LLLine known_intersection(some_point, another_point);
+
+ // compute a plane that intersect the line
+ LLVector3 point_on_plane( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ point_on_plane.normalize();
+ point_on_plane *= ll_frand(LARGE_RADIUS);
+ LLVector3 plane_normal = (point_on_plane - some_point) % known_intersection.getDirection();
+ plane_normal.normalize();
+ LLLine first_plane(point_on_plane, point_on_plane + plane_normal);
+
+ // compute a different plane that intersect the line
+ LLVector3 point_on_different_plane( ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f,
+ ll_frand(2.f) - 1.f);
+ point_on_different_plane.normalize();
+ point_on_different_plane *= ll_frand(LARGE_RADIUS);
+ LLVector3 different_plane_normal = (point_on_different_plane - another_point) % known_intersection.getDirection();
+ different_plane_normal.normalize();
+ LLLine second_plane(point_on_different_plane, point_on_different_plane + different_plane_normal);
+
+ if (fabs(plane_normal * different_plane_normal) > ALMOST_PARALLEL)
+ {
+ // the two planes are approximately parallel, so we won't test this case
+ continue;
+ }
+
+ LLLine measured_intersection;
+ bool success = LLLine::getIntersectionBetweenTwoPlanes(
+ measured_intersection,
+ first_plane,
+ second_plane);
+
+ ensure("plane intersection should succeed", success);
+
+ F32 dot = fabs(known_intersection.getDirection() * measured_intersection.getDirection());
+ ensure("measured intersection should be parallel to known intersection",
+ dot > ALMOST_PARALLEL);
+
+ ensure("measured intersection should pass near known point",
+ measured_intersection.intersects(some_point, LARGE_RADIUS * allowable_relative_error));
+ }
+ }
+}
+
diff --git a/indra/llmath/tests/v2math_test.cpp b/indra/llmath/tests/v2math_test.cpp
new file mode 100644
index 0000000000..9747996b25
--- /dev/null
+++ b/indra/llmath/tests/v2math_test.cpp
@@ -0,0 +1,448 @@
+/**
+ * @file v2math_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief v2math test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../v2math.h"
+
+
+namespace tut
+{
+ struct v2math_data
+ {
+ };
+ typedef test_group<v2math_data> v2math_test;
+ typedef v2math_test::object v2math_object;
+ tut::v2math_test v2math_testcase("v2math_h");
+
+ template<> template<>
+ void v2math_object::test<1>()
+ {
+ LLVector2 vec2;
+ ensure("LLVector2:Fail to initialize ", (0.f == vec2.mV[VX] && 0.f == vec2.mV[VY]));
+
+ F32 x =2.0f, y = 3.2f ;
+ LLVector2 vec3(x,y);
+ ensure("LLVector2(F32 x, F32 y):Fail to initialize ", (x == vec3.mV[VX]) && (y == vec3.mV[VY]));
+
+ const F32 vec[2] = {3.2f, 4.5f};
+ LLVector2 vec4(vec);
+ ensure("LLVector2(const F32 *vec):Fail to initialize ", (vec[0] == vec4.mV[VX]) && (vec[1] == vec4.mV[VY]));
+
+ vec4.clearVec();
+ ensure("clearVec():Fail to clean the values ", (0.f == vec4.mV[VX] && 0.f == vec4.mV[VY]));
+
+ vec3.zeroVec();
+ ensure("zeroVec():Fail to fill the zero ", (0.f == vec3.mV[VX] && 0.f == vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<2>()
+ {
+ F32 x = 123.356f, y = 2387.453f;
+ LLVector2 vec2,vec3;
+ vec2.setVec(x, y);
+ ensure("1:setVec: Fail ", (x == vec2.mV[VX]) && (y == vec2.mV[VY]));
+
+ vec3.setVec(vec2);
+ ensure("2:setVec: Fail " ,(vec2 == vec3));
+
+ vec3.zeroVec();
+ const F32 vec[2] = {3.24653f, 457653.4f};
+ vec3.setVec(vec);
+ ensure("3:setVec: Fail ", (vec[0] == vec3.mV[VX]) && (vec[1] == vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<3>()
+ {
+ F32 x = 2.2345f, y = 3.5678f ;
+ LLVector2 vec2(x,y);
+ ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y)));
+ ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), fsqrtf(x*x + y*y)));
+ }
+
+ template<> template<>
+ void v2math_object::test<4>()
+ {
+ F32 x =-2.0f, y = -3.0f ;
+ LLVector2 vec2(x,y);
+ ensure_equals("abs():Fail", vec2.abs(), TRUE);
+ ensure("abs() x", is_approx_equal(vec2.mV[VX], 2.f));
+ ensure("abs() y", is_approx_equal(vec2.mV[VY], 3.f));
+
+ ensure("isNull():Fail ", FALSE == vec2.isNull()); //Returns TRUE if vector has a _very_small_ length
+
+ x =.00000001f, y = .000001001f;
+ vec2.setVec(x, y);
+ ensure("isNull(): Fail ", TRUE == vec2.isNull());
+ }
+
+ template<> template<>
+ void v2math_object::test<5>()
+ {
+ F32 x =1.f, y = 2.f;
+ LLVector2 vec2(x, y), vec3;
+ vec3 = vec3.scaleVec(vec2);
+ ensure("scaleVec: Fail ", vec3.mV[VX] == 0. && vec3.mV[VY] == 0.);
+ ensure("isExactlyZero(): Fail", TRUE == vec3.isExactlyZero());
+
+ vec3.setVec(2.f, 1.f);
+ vec3 = vec3.scaleVec(vec2);
+ ensure("scaleVec: Fail ", (2.f == vec3.mV[VX]) && (2.f == vec3.mV[VY]));
+ ensure("isExactlyZero():Fail", FALSE == vec3.isExactlyZero());
+ }
+
+ template<> template<>
+ void v2math_object::test<6>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
+ vec4 = vec2 + vec3 ;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("1:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec4 = vec2 + vec3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("2:operator+ failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+ }
+
+ template<> template<>
+ void v2math_object::test<7>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
+ vec4 = vec2 - vec3 ;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("1:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ vec4.clearVec();
+ x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec4 = vec2 - vec3;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("2:operator- failed",(val1 == vec4.mV[VX]) && ((val2 == vec4.mV[VY])));
+ }
+
+ template<> template<>
+ void v2math_object::test<8>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ val1 = vec2 * vec3;
+ val2 = x1*x2 + y1*y2;
+ ensure("1:operator* failed",(val1 == val2));
+
+ vec3.clearVec();
+ F32 mulVal = 4.332f;
+ vec3 = vec2 * mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ ensure("2:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY]));
+
+ vec3.clearVec();
+ vec3 = mulVal * vec2;
+ ensure("3:operator* failed",(val1 == vec3.mV[VX]) && (val2 == vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<9>()
+ {
+ F32 x1 =1.f, y1 = 2.f, div = 3.2f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3;
+ vec3 = vec2 / div;
+ val1 = x1 / div;
+ val2 = y1 / div;
+ ensure("1:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]));
+
+ vec3.clearVec();
+ x1 = -.235f, y1 = -24.32f, div = -2.2f;
+ vec2.setVec(x1, y1);
+ vec3 = vec2 / div;
+ val1 = x1 / div;
+ val2 = y1 / div;
+ ensure("2:operator/ failed", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<10>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2), vec4;
+ vec4 = vec2 % vec3;
+ val1 = x1*y2 - x2*y1;
+ val2 = y1*x2 - y2*x1;
+ ensure("1:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ vec4.clearVec();
+ x1 = -.235f, y1 = -24.32f, x2 = -2.3f, y2 = 1.f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec4 = vec2 % vec3;
+ val1 = x1*y2 - x2*y1;
+ val2 = y1*x2 - y2*x1;
+ ensure("2:operator% failed",(val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY]));
+ }
+ template<> template<>
+ void v2math_object::test<11>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ LLVector2 vec2(x1, y1), vec3(x1, y1);
+ ensure("1:operator== failed",(vec2 == vec3));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ x1 = -.235f, y1 = -24.32f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(vec2);
+ ensure("2:operator== failed",(vec2 == vec3));
+ }
+
+ template<> template<>
+ void v2math_object::test<12>()
+ {
+ F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ ensure("1:operator!= failed",(vec2 != vec3));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ vec2.setVec(x1, y1);
+ vec3.setVec(vec2);
+ ensure("2:operator!= failed", (FALSE == (vec2 != vec3)));
+ }
+ template<> template<>
+ void v2math_object::test<13>()
+ {
+ F32 x1 = 1.f, y1 = 2.f,x2 = 2.332f, y2 = -1.23f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ vec2 +=vec3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("1:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.setVec(x1, y1);
+ vec2 -=vec3;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("2:operator-= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.clearVec();
+ vec3.clearVec();
+ x1 = -21.000466f, y1 = 2.98382f,x2 = 0.332f, y2 = -01.23f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ vec2 +=vec3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ ensure("3:operator+= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.setVec(x1, y1);
+ vec2 -=vec3;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ ensure("4:operator-= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<14>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ F32 val1, val2, mulVal = 4.332f;
+ LLVector2 vec2(x1, y1);
+ vec2 /=mulVal;
+ val1 = x1 / mulVal;
+ val2 = y1 / mulVal;
+ ensure("1:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
+
+ vec2.clearVec();
+ x1 = .213f, y1 = -2.34f, mulVal = -.23f;
+ vec2.setVec(x1, y1);
+ vec2 /=mulVal;
+ val1 = x1 / mulVal;
+ val2 = y1 / mulVal;
+ ensure("2:operator/= failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<15>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ F32 val1, val2, mulVal = 4.332f;
+ LLVector2 vec2(x1, y1);
+ vec2 *=mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ ensure("1:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+
+ vec2.clearVec();
+ x1 = .213f, y1 = -2.34f, mulVal = -.23f;
+ vec2.setVec(x1, y1);
+ vec2 *=mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ ensure("2:operator*= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<16>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -2.3f, y2 = 1.11f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1), vec3(x2, y2);
+ vec2 %= vec3;
+ val1 = x1*y2 - x2*y1;
+ val2 = y1*x2 - y2*x1;
+ ensure("1:operator%= failed",(val1 == vec2.mV[VX]) && (val2 == vec2.mV[VY]));
+ }
+
+ template<> template<>
+ void v2math_object::test<17>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ LLVector2 vec2(x1, y1),vec3;
+ vec3 = -vec2;
+ ensure("1:operator- failed",(-vec3 == vec2));
+ }
+
+ template<> template<>
+ void v2math_object::test<18>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ std::ostringstream stream1, stream2;
+ LLVector2 vec2(x1, y1),vec3;
+ stream1 << vec2;
+ vec3.setVec(x1, y1);
+ stream2 << vec3;
+ ensure("1:operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v2math_object::test<19>()
+ {
+ F32 x1 =1.0f, y1 = 2.0f, x2 = -.32f, y2 = .2234f;
+ LLVector2 vec2(x1, y1),vec3(x2, y2);
+ ensure("1:operator < failed",(vec3 < vec2));
+
+ x1 = 1.0f, y1 = 2.0f, x2 = 1.0f, y2 = 3.2234f;
+ vec2.setVec(x1, y1);
+ vec3.setVec(x2, y2);
+ ensure("2:operator < failed", (FALSE == (vec3 < vec2)));
+ }
+
+ template<> template<>
+ void v2math_object::test<20>()
+ {
+ F32 x1 =1.0f, y1 = 2.0f;
+ LLVector2 vec2(x1, y1);
+ ensure("1:operator [] failed",( x1 == vec2[0]));
+ ensure("2:operator [] failed",( y1 == vec2[1]));
+
+ vec2.clearVec();
+ x1 = 23.0f, y1 = -.2361f;
+ vec2.setVec(x1, y1);
+ F32 ref1 = vec2[0];
+ ensure("3:operator [] failed", ( ref1 == x1));
+ F32 ref2 = vec2[1];
+ ensure("4:operator [] failed", ( ref2 == y1));
+ }
+
+ template<> template<>
+ void v2math_object::test<21>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1),vec3(x2, y2);
+ val1 = dist_vec_squared2D(vec2, vec3);
+ val2 = (x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2);
+ ensure_equals("dist_vec_squared2D values are not equal",val2, val1);
+
+ val1 = dist_vec_squared(vec2, vec3);
+ ensure_equals("dist_vec_squared values are not equal",val2, val1);
+
+ val1 = dist_vec(vec2, vec3);
+ val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2));
+ ensure_equals("dist_vec values are not equal",val2, val1);
+ }
+
+ template<> template<>
+ void v2math_object::test<22>()
+ {
+ F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f,fVal = .0121f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1),vec3(x2, y2);
+ LLVector2 vec4 = lerp(vec2, vec3, fVal);
+ val1 = x1 + (x2 - x1) * fVal;
+ val2 = y1 + (y2 - y1) * fVal;
+ ensure("lerp values are not equal", ((val1 == vec4.mV[VX]) && (val2 == vec4.mV[VY])));
+ }
+
+ template<> template<>
+ void v2math_object::test<23>()
+ {
+ F32 x1 =1.f, y1 = 2.f;
+ F32 val1, val2;
+ LLVector2 vec2(x1, y1);
+
+ F32 vecMag = vec2.normVec();
+ F32 mag = fsqrtf(x1*x1 + y1*y1);
+
+ F32 oomag = 1.f / mag;
+ val1 = x1 * oomag;
+ val2 = y1 * oomag;
+
+ ensure("normVec failed", is_approx_equal(val1, vec2.mV[VX]) && is_approx_equal(val2, vec2.mV[VY]) && is_approx_equal(vecMag, mag));
+
+ x1 =.00000001f, y1 = 0.f;
+
+ vec2.setVec(x1, y1);
+ vecMag = vec2.normVec();
+ ensure("normVec failed should be 0.", 0. == vec2.mV[VX] && 0. == vec2.mV[VY] && vecMag == 0.);
+ }
+}
diff --git a/indra/llmath/tests/v3color_test.cpp b/indra/llmath/tests/v3color_test.cpp
new file mode 100644
index 0000000000..2c00f00ab3
--- /dev/null
+++ b/indra/llmath/tests/v3color_test.cpp
@@ -0,0 +1,309 @@
+/**
+ * @file v3color_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v3color test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../v3color.h"
+
+
+namespace tut
+{
+ struct v3color_data
+ {
+ };
+ typedef test_group<v3color_data> v3color_test;
+ typedef v3color_test::object v3color_object;
+ tut::v3color_test v3color_testcase("v3color_h");
+
+ template<> template<>
+ void v3color_object::test<1>()
+ {
+ LLColor3 llcolor3;
+ ensure("1:LLColor3:Fail to default-initialize ", (0.0f == llcolor3.mV[0]) && (0.0f == llcolor3.mV[1]) && (0.0f == llcolor3.mV[2]));
+ F32 r = 2.0f, g = 3.2f, b = 1.f;
+ F32 v1,v2,v3;
+ LLColor3 llcolor3a(r,g,b);
+ ensure("2:LLColor3:Fail to initialize " ,(2.0f == llcolor3a.mV[0]) && (3.2f == llcolor3a.mV[1]) && (1.f == llcolor3a.mV[2]));
+
+ const F32 vec[3] = {2.0f, 3.2f,1.f};
+ LLColor3 llcolor3b(vec);
+ ensure("3:LLColor3:Fail to initialize " ,(2.0f == llcolor3b.mV[0]) && (3.2f == llcolor3b.mV[1]) && (1.f == llcolor3b.mV[2]));
+ const char* str = "561122";
+ LLColor3 llcolor3c(str);
+ v1 = (F32)86.0f/255.0f; // 0x56 = 86
+ v2 = (F32)17.0f/255.0f; // 0x11 = 17
+ v3 = (F32)34.0f/255.f; // 0x22 = 34
+ ensure("4:LLColor3:Fail to initialize " , is_approx_equal(v1, llcolor3c.mV[0]) && is_approx_equal(v2, llcolor3c.mV[1]) && is_approx_equal(v3, llcolor3c.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<2>()
+ {
+ LLColor3 llcolor3;
+ llcolor3.setToBlack();
+ ensure("setToBlack:Fail to set black ", ((llcolor3.mV[0] == 0.f) && (llcolor3.mV[1] == 0.f) && (llcolor3.mV[2] == 0.f)));
+ llcolor3.setToWhite();
+ ensure("setToWhite:Fail to set white ", ((llcolor3.mV[0] == 1.f) && (llcolor3.mV[1] == 1.f) && (llcolor3.mV[2] == 1.f)));
+ }
+
+ template<> template<>
+ void v3color_object::test<3>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3, llcolor3a;
+ llcolor3.setVec(r,g,b);
+ ensure("1:setVec(r,g,b) Fail ",((r == llcolor3.mV[0]) && (g == llcolor3.mV[1]) && (b == llcolor3.mV[2])));
+ llcolor3a.setVec(llcolor3);
+ ensure_equals("2:setVec(LLColor3) Fail ", llcolor3,llcolor3a);
+ F32 vec[3] = {1.2324f, 2.45634f, .234563f};
+ llcolor3.setToBlack();
+ llcolor3.setVec(vec);
+ ensure("3:setVec(F32*) Fail ",((vec[0] == llcolor3.mV[0]) && (vec[1] == llcolor3.mV[1]) && (vec[2] == llcolor3.mV[2])));
+ }
+
+ template<> template<>
+ void v3color_object::test<4>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3(r,g,b);
+ ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b)));
+ ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), fsqrtf(r*r + g*g + b*b)));
+ }
+
+ template<> template<>
+ void v3color_object::test<5>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ F32 val1, val2,val3;
+ LLColor3 llcolor3(r,g,b);
+ F32 vecMag = llcolor3.normVec();
+ F32 mag = fsqrtf(r*r + g*g + b*b);
+ F32 oomag = 1.f / mag;
+ val1 = r * oomag;
+ val2 = g * oomag;
+ val3 = b * oomag;
+ ensure("1:normVec failed ", (is_approx_equal(val1, llcolor3.mV[0]) && is_approx_equal(val2, llcolor3.mV[1]) && is_approx_equal(val3, llcolor3.mV[2]) && is_approx_equal(vecMag, mag)));
+ r = .000000000f, g = 0.f, b = 0.0f;
+ llcolor3.setVec(r,g,b);
+ vecMag = llcolor3.normVec();
+ ensure("2:normVec failed should be 0. ", (0. == llcolor3.mV[0] && 0. == llcolor3.mV[1] && 0. == llcolor3.mV[2] && vecMag == 0.));
+ }
+
+ template<> template<>
+ void v3color_object::test<6>()
+ {
+ F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
+ std::ostringstream stream1, stream2;
+ LLColor3 llcolor3(r,g,b),llcolor3a;
+ stream1 << llcolor3;
+ llcolor3a.setVec(r,g,b);
+ stream2 << llcolor3a;
+ ensure("operator << failed ", (stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v3color_object::test<7>()
+ {
+ F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
+ LLColor3 llcolor3(r,g,b),llcolor3a;
+ llcolor3a = llcolor3;
+ ensure("operator == failed ", (llcolor3a == llcolor3));
+ }
+
+ template<> template<>
+ void v3color_object::test<8>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
+ llcolor3b = llcolor3 + llcolor3a ;
+ ensure("1:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2]));
+ r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f;
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3b = llcolor3 + llcolor3a;
+ ensure("2:operator+ failed",is_approx_equal(r1+r2 ,llcolor3b.mV[0]) && is_approx_equal(g1+g2,llcolor3b.mV[1])&& is_approx_equal(b1+b2,llcolor3b.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<9>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
+ llcolor3b = llcolor3 - llcolor3a ;
+ ensure("1:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2]));
+ r1 = -.235f, g1 = -24.32f, b1 = 2.13f, r2 = -2.3f, g2 = 1.f, b2 = 34.21f;
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3b = llcolor3 - llcolor3a;
+ ensure("2:operator- failed",is_approx_equal(r1-r2 ,llcolor3b.mV[0]) && is_approx_equal(g1-g2,llcolor3b.mV[1])&& is_approx_equal(b1-b2,llcolor3b.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<10>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2),llcolor3b;
+ llcolor3b = llcolor3 * llcolor3a;
+ ensure("1:operator* failed",is_approx_equal(r1*r2 ,llcolor3b.mV[0]) && is_approx_equal(g1*g2,llcolor3b.mV[1])&& is_approx_equal(b1*b2,llcolor3b.mV[2]));
+ llcolor3a.setToBlack();
+ F32 mulVal = 4.332f;
+ llcolor3a = llcolor3 * mulVal;
+ ensure("2:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2]));
+ llcolor3a.setToBlack();
+ llcolor3a = mulVal * llcolor3;
+ ensure("3:operator* failed",is_approx_equal(r1*mulVal ,llcolor3a.mV[0]) && is_approx_equal(g1*mulVal,llcolor3a.mV[1])&& is_approx_equal(b1*mulVal,llcolor3a.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<11>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3(r,g,b),llcolor3a;
+ llcolor3a = -llcolor3;
+ ensure("operator- failed ", (-llcolor3a == llcolor3));
+ }
+
+ template<> template<>
+ void v3color_object::test<12>()
+ {
+ F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f;
+ LLColor3 llcolor3(r,g,b),llcolor3a(r,g,b);
+ ensure_equals("1:operator== failed",llcolor3a,llcolor3);
+ r = 13.3436212f, g = -11.f, b = .7849321232f;
+ llcolor3.setVec(r,g,b);
+ llcolor3a.setVec(r,g,b);
+ ensure_equals("2:operator== failed",llcolor3a,llcolor3);
+ }
+
+ template<> template<>
+ void v3color_object::test<13>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ ensure("1:operator!= failed",(llcolor3 != llcolor3a));
+ llcolor3.setToBlack();
+ llcolor3a.setVec(llcolor3);
+ ensure("2:operator!= failed", ( FALSE == (llcolor3a != llcolor3)));
+ }
+
+ template<> template<>
+ void v3color_object::test<14>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ llcolor3a += llcolor3;
+ ensure("1:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2]));
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3a += llcolor3;
+ ensure("2:operator+= failed",is_approx_equal(r1+r2 ,llcolor3a.mV[0]) && is_approx_equal(g1+g2,llcolor3a.mV[1])&& is_approx_equal(b1+b2,llcolor3a.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<15>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ llcolor3a -= llcolor3;
+ ensure("1:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0]));
+ ensure("2:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1]));
+ ensure("3:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2]));
+ llcolor3.setVec(r1,g1,b1);
+ llcolor3a.setVec(r2,g2,b2);
+ llcolor3a -= llcolor3;
+ ensure("4:operator-= failed", is_approx_equal(r2-r1, llcolor3a.mV[0]));
+ ensure("5:operator-= failed", is_approx_equal(g2-g1, llcolor3a.mV[1]));
+ ensure("6:operator-= failed", is_approx_equal(b2-b1, llcolor3a.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<16>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ llcolor3a *= llcolor3;
+ ensure("1:operator*= failed",is_approx_equal(r1*r2 ,llcolor3a.mV[0]) && is_approx_equal(g1*g2,llcolor3a.mV[1])&& is_approx_equal(b1*b2,llcolor3a.mV[2]));
+ F32 mulVal = 4.332f;
+ llcolor3 *=mulVal;
+ ensure("2:operator*= failed",is_approx_equal(r1*mulVal ,llcolor3.mV[0]) && is_approx_equal(g1*mulVal,llcolor3.mV[1])&& is_approx_equal(b1*mulVal,llcolor3.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<17>()
+ {
+ F32 r = 2.3436212f, g = -1231.f, b = .7849321232f;
+ LLColor3 llcolor3(r,g,b);
+ llcolor3.clamp();
+ ensure("1:clamp:Fail to clamp " ,(1.0f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (b == llcolor3.mV[2]));
+ r = -2.3436212f, g = -1231.f, b = 67.7849321232f;
+ llcolor3.setVec(r,g,b);
+ llcolor3.clamp();
+ ensure("2:clamp:Fail to clamp " ,(0.f == llcolor3.mV[0]) && (0.f == llcolor3.mV[1]) && (1.f == llcolor3.mV[2]));
+ }
+
+ template<> template<>
+ void v3color_object::test<18>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ F32 val = 2.3f,val1,val2,val3;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ val1 = r1 + (r2 - r1)* val;
+ val2 = g1 + (g2 - g1)* val;
+ val3 = b1 + (b2 - b1)* val;
+ LLColor3 llcolor3b = lerp(llcolor3,llcolor3a,val);
+ ensure("lerp failed ", ((val1 ==llcolor3b.mV[0])&& (val2 ==llcolor3b.mV[1]) && (val3 ==llcolor3b.mV[2])));
+ }
+
+ template<> template<>
+ void v3color_object::test<19>()
+ {
+ F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f;
+ LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2);
+ F32 val = distVec(llcolor3,llcolor3a);
+ ensure("distVec failed ", is_approx_equal(fsqrtf((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val));
+
+ F32 val1 = distVec_squared(llcolor3,llcolor3a);
+ ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1));
+ }
+
+ template<> template<>
+ void v3color_object::test<20>()
+ {
+ F32 r1 = 1.02223f, g1 = 22222.212f, b1 = 122222.00002f;
+ LLColor3 llcolor31(r1,g1,b1);
+
+ LLSD sd = llcolor31.getValue();
+ LLColor3 llcolor32;
+ llcolor32.setValue(sd);
+ ensure_equals("LLColor3::setValue/getValue failed", llcolor31, llcolor32);
+
+ LLColor3 llcolor33(sd);
+ ensure_equals("LLColor3(LLSD) failed", llcolor31, llcolor33);
+ }
+}
diff --git a/indra/llmath/tests/v3dmath_test.cpp b/indra/llmath/tests/v3dmath_test.cpp
new file mode 100644
index 0000000000..b67346f4e5
--- /dev/null
+++ b/indra/llmath/tests/v3dmath_test.cpp
@@ -0,0 +1,526 @@
+/**
+ * @file v3dmath_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v3dmath test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llsd.h"
+#include "../test/lltut.h"
+
+#include "../llquaternion.h"
+#include "../m3math.h"
+#include "../v4math.h"
+#include "../v3dmath.h"
+#include "../v3dmath.h"
+
+namespace tut
+{
+ struct v3dmath_data
+ {
+ };
+ typedef test_group<v3dmath_data> v3dmath_test;
+ typedef v3dmath_test::object v3dmath_object;
+ tut::v3dmath_test v3dmath_testcase("v3dmath_h");
+
+ template<> template<>
+ void v3dmath_object::test<1>()
+ {
+ LLVector3d vec3D;
+ ensure("1:LLVector3d:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
+ F64 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3d vec3Da(x,y,z);
+ ensure("2:LLVector3d:Fail to initialize ", ((2.32f == vec3Da.mdV[VX]) && (1.212f == vec3Da.mdV[VY]) && (-.12f == vec3Da.mdV[VZ])));
+ const F64 vec[3] = {1.2f ,3.2f, -4.2f};
+ LLVector3d vec3Db(vec);
+ ensure("3:LLVector3d:Fail to initialize ", ((1.2f == vec3Db.mdV[VX]) && (3.2f == vec3Db.mdV[VY]) && (-4.2f == vec3Db.mdV[VZ])));
+ LLVector3 vec3((F32)x,(F32)y,(F32)z);
+ LLVector3d vec3Dc(vec3);
+ ensure_equals("4:LLVector3d Fail to initialize",vec3Da,vec3Dc);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<2>()
+ {
+ S32 a = -235;
+ LLSD llsd(a);
+ LLVector3d vec3d(llsd);
+ LLSD sd = vec3d.getValue();
+ LLVector3d vec3da(sd);
+ ensure("1:getValue:Fail ", (vec3d == vec3da));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<3>()
+ {
+ F64 a = 232345521.411132;
+ LLSD llsd(a);
+ LLVector3d vec3d;
+ vec3d.setValue(llsd);
+ LLSD sd = vec3d.getValue();
+ LLVector3d vec3da(sd);
+ ensure("1:setValue:Fail to initialize ", (vec3d == vec3da));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<4>()
+ {
+ F64 a[3] = {222231.43222, 12345.2343, -434343.33222};
+ LLSD llsd;
+ llsd[0] = a[0];
+ llsd[1] = a[1];
+ llsd[2] = a[2];
+ LLVector3d vec3D;
+ vec3D = (LLVector3d)llsd;
+ ensure("1:operator=:Fail to initialize ", ((llsd[0].asReal()== vec3D.mdV[VX]) && (llsd[1].asReal() == vec3D.mdV[VY]) && (llsd[2].asReal() == vec3D.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<5>()
+ {
+ F64 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3d vec3D(x,y,z);
+ vec3D.clearVec();
+ ensure("1:clearVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
+ vec3D.setVec(x,y,z);
+ ensure("2:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
+ vec3D.zeroVec();
+ ensure("3:zeroVec:Fail to initialize ", ((0 == vec3D.mdV[VX]) && (0 == vec3D.mdV[VY]) && (0 == vec3D.mdV[VZ])));
+ vec3D.clearVec();
+ LLVector3 vec3((F32)x,(F32)y,(F32)z);
+ vec3D.setVec(vec3);
+ ensure("4:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
+ vec3D.clearVec();
+ const F64 vec[3] = {x,y,z};
+ vec3D.setVec(vec);
+ ensure("5:setVec:Fail to initialize ", ((x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (z == vec3D.mdV[VZ])));
+ LLVector3d vec3Da;
+ vec3Da.setVec(vec3D);
+ ensure_equals("6:setVec: Fail to initialize", vec3D, vec3Da);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<6>()
+ {
+ F64 x = -2.32, y = 1.212, z = -.12;
+ LLVector3d vec3D(x,y,z);
+ vec3D.abs();
+ ensure("1:abs:Fail ", ((-x == vec3D.mdV[VX]) && (y == vec3D.mdV[VY]) && (-z == vec3D.mdV[VZ])));
+ ensure("2:isNull():Fail ", (FALSE == vec3D.isNull()));
+ vec3D.clearVec();
+ x =.00000001, y = .000001001, z = .000001001;
+ vec3D.setVec(x,y,z);
+ ensure("3:isNull():Fail ", (TRUE == vec3D.isNull()));
+ ensure("4:isExactlyZero():Fail ", (FALSE == vec3D.isExactlyZero()));
+ x =.0000000, y = .00000000, z = .00000000;
+ vec3D.setVec(x,y,z);
+ ensure("5:isExactlyZero():Fail ", (TRUE == vec3D.isExactlyZero()));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<7>()
+ {
+ F64 x = -2.32, y = 1.212, z = -.12;
+ LLVector3d vec3D(x,y,z);
+
+ ensure("1:operator [] failed",( x == vec3D[0]));
+ ensure("2:operator [] failed",( y == vec3D[1]));
+ ensure("3:operator [] failed",( z == vec3D[2]));
+ vec3D.clearVec();
+ x = 23.23, y = -.2361, z = 3.25;
+ vec3D.setVec(x,y,z);
+ F64 &ref1 = vec3D[0];
+ ensure("4:operator [] failed",( ref1 == vec3D[0]));
+ F64 &ref2 = vec3D[1];
+ ensure("5:operator [] failed",( ref2 == vec3D[1]));
+ F64 &ref3 = vec3D[2];
+ ensure("6:operator [] failed",( ref3 == vec3D[2]));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<8>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.f;
+ LLVector4 vec4(x,y,z);
+ LLVector3d vec3D;
+ vec3D = vec4;
+ ensure("1:operator=:Fail to initialize ", ((vec4.mV[VX] == vec3D.mdV[VX]) && (vec4.mV[VY] == vec3D.mdV[VY]) && (vec4.mV[VZ] == vec3D.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<9>()
+ {
+ F64 x1 = 1.78787878, y1 = 232322.2121, z1 = -12121.121212;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db;
+ vec3Db = vec3Da+ vec3D;
+ ensure("1:operator+:Fail to initialize ", ((x1+x2 == vec3Db.mdV[VX]) && (y1+y2 == vec3Db.mdV[VY]) && (z1+z2 == vec3Db.mdV[VZ])));
+ x1 = -2.45, y1 = 2.1, z1 = 3.0;
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ vec3D.setVec(x1,y1,z1);
+ vec3Da += vec3D;
+ ensure_equals("2:operator+=: Fail to initialize", vec3Da,vec3D);
+ vec3Da += vec3D;
+ ensure("3:operator+=:Fail to initialize ", ((2*x1 == vec3Da.mdV[VX]) && (2*y1 == vec3Da.mdV[VY]) && (2*z1 == vec3Da.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<10>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2),vec3Db;
+ vec3Db = vec3Da - vec3D;
+ ensure("1:operator-:Fail to initialize ", ((x2-x1 == vec3Db.mdV[VX]) && (y2-y1 == vec3Db.mdV[VY]) && (z2-z1 == vec3Db.mdV[VZ])));
+ x1 = -2.45, y1 = 2.1, z1 = 3.0;
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ vec3D.setVec(x1,y1,z1);
+ vec3Da -=vec3D;
+ ensure("2:operator-=:Fail to initialize ", ((2.45 == vec3Da.mdV[VX]) && (-2.1 == vec3Da.mdV[VY]) && (-3.0 == vec3Da.mdV[VZ])));
+ vec3Da -= vec3D;
+ ensure("3:operator-=:Fail to initialize ", ((-2*x1 == vec3Da.mdV[VX]) && (-2*y1 == vec3Da.mdV[VY]) && (-2*z1 == vec3Da.mdV[VZ])));
+ }
+ template<> template<>
+ void v3dmath_object::test<11>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2);
+ F64 res = vec3D * vec3Da;
+ ensure_approximately_equals(
+ "1:operator* failed",
+ res,
+ (x1*x2 + y1*y2 + z1*z2),
+ 8);
+ vec3Da.clearVec();
+ F64 mulVal = 4.2;
+ vec3Da = vec3D * mulVal;
+ ensure_approximately_equals(
+ "2a:operator* failed",
+ vec3Da.mdV[VX],
+ x1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "2b:operator* failed",
+ vec3Da.mdV[VY],
+ y1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "2c:operator* failed",
+ vec3Da.mdV[VZ],
+ z1*mulVal,
+ 8);
+ vec3Da.clearVec();
+ vec3Da = mulVal * vec3D;
+ ensure_approximately_equals(
+ "3a:operator* failed",
+ vec3Da.mdV[VX],
+ x1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "3b:operator* failed",
+ vec3Da.mdV[VY],
+ y1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "3c:operator* failed",
+ vec3Da.mdV[VZ],
+ z1*mulVal,
+ 8);
+ vec3D *= mulVal;
+ ensure_approximately_equals(
+ "4a:operator*= failed",
+ vec3D.mdV[VX],
+ x1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "4b:operator*= failed",
+ vec3D.mdV[VY],
+ y1*mulVal,
+ 8);
+ ensure_approximately_equals(
+ "4c:operator*= failed",
+ vec3D.mdV[VZ],
+ z1*mulVal,
+ 8);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<12>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ F64 val1, val2, val3;
+ LLVector3d vec3D(x1,y1,z1),vec3Da(x2,y2,z2), vec3Db;
+ vec3Db = vec3D % vec3Da;
+ val1 = y1*z2 - y2*z1;
+ val2 = z1*x2 -z2*x1;
+ val3 = x1*y2-x2*y1;
+ ensure("1:operator% failed",(val1 == vec3Db.mdV[VX]) && (val2 == vec3Db.mdV[VY]) && (val3 == vec3Db.mdV[VZ]));
+ vec3D %= vec3Da;
+ ensure("2:operator%= failed",
+ is_approx_equal(vec3D.mdV[VX],vec3Db.mdV[VX]) &&
+ is_approx_equal(vec3D.mdV[VY],vec3Db.mdV[VY]) &&
+ is_approx_equal(vec3D.mdV[VZ],vec3Db.mdV[VZ]) );
+ }
+
+ template<> template<>
+ void v3dmath_object::test<13>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1,div = 4.2;
+ F64 t = 1.f / div;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ vec3Da = vec3D/div;
+ ensure_approximately_equals(
+ "1a:operator/ failed",
+ vec3Da.mdV[VX],
+ x1*t,
+ 8);
+ ensure_approximately_equals(
+ "1b:operator/ failed",
+ vec3Da.mdV[VY],
+ y1*t,
+ 8);
+ ensure_approximately_equals(
+ "1c:operator/ failed",
+ vec3Da.mdV[VZ],
+ z1*t,
+ 8);
+ x1 = 1.23, y1 = 4., z1 = -2.32;
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ vec3D.setVec(x1,y1,z1);
+ vec3Da = vec3D/div;
+ ensure_approximately_equals(
+ "2a:operator/ failed",
+ vec3Da.mdV[VX],
+ x1*t,
+ 8);
+ ensure_approximately_equals(
+ "2b:operator/ failed",
+ vec3Da.mdV[VY],
+ y1*t,
+ 8);
+ ensure_approximately_equals(
+ "2c:operator/ failed",
+ vec3Da.mdV[VZ],
+ z1*t,
+ 8);
+ vec3D /= div;
+ ensure_approximately_equals(
+ "3a:operator/= failed",
+ vec3D.mdV[VX],
+ x1*t,
+ 8);
+ ensure_approximately_equals(
+ "3b:operator/= failed",
+ vec3D.mdV[VY],
+ y1*t,
+ 8);
+ ensure_approximately_equals(
+ "3c:operator/= failed",
+ vec3D.mdV[VZ],
+ z1*t,
+ 8);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<14>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ ensure("1:operator!= failed",(TRUE == (vec3D !=vec3Da)));
+ vec3Da = vec3D;
+ ensure("2:operator== failed",(vec3D ==vec3Da));
+ vec3D.clearVec();
+ vec3Da.clearVec();
+ x1 = .211, y1 = 21.111, z1 = 23.22;
+ vec3D.setVec(x1,y1,z1);
+ vec3Da.setVec(x1,y1,z1);
+ ensure("3:operator== failed",(vec3D ==vec3Da));
+ ensure("4:operator!= failed",(FALSE == (vec3D !=vec3Da)));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<15>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ std::ostringstream stream1, stream2;
+ stream1 << vec3D;
+ vec3Da.setVec(x1,y1,z1);
+ stream2 << vec3Da;
+ ensure("1:operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<16>()
+ {
+ F64 x1 = 1.23, y1 = 2.0, z1 = 4.;
+ std::string buf("1.23 2. 4");
+ LLVector3d vec3D, vec3Da(x1,y1,z1);
+ LLVector3d::parseVector3d(buf, &vec3D);
+ ensure_equals("1:parseVector3d: failed " , vec3D, vec3Da);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<17>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ LLVector3d vec3D(x1,y1,z1), vec3Da;
+ vec3Da = -vec3D;
+ ensure("1:operator- failed", (vec3D == - vec3Da));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<18>()
+ {
+ F64 x = 1., y = 2., z = -1.1;
+ LLVector3d vec3D(x,y,z);
+ F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared();
+ ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO)));
+ res = fsqrtf(x*x + y*y + z*z) - vec3D.magVec();
+ ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO)));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<19>()
+ {
+ F64 x = 1., y = 2., z = -1.1;
+ LLVector3d vec3D(x,y,z);
+ F64 mag = vec3D.normVec();
+ mag = 1.f/ mag;
+ ensure_approximately_equals(
+ "1a:normVec: Fail ",
+ vec3D.mdV[VX],
+ x * mag,
+ 8);
+ ensure_approximately_equals(
+ "1b:normVec: Fail ",
+ vec3D.mdV[VY],
+ y * mag,
+ 8);
+ ensure_approximately_equals(
+ "1c:normVec: Fail ",
+ vec3D.mdV[VZ],
+ z * mag,
+ 8);
+ x = 0.000000001, y = 0.000000001, z = 0.000000001;
+ vec3D.clearVec();
+ vec3D.setVec(x,y,z);
+ mag = vec3D.normVec();
+ ensure_approximately_equals(
+ "2a:normVec: Fail ",
+ vec3D.mdV[VX],
+ x * mag,
+ 8);
+ ensure_approximately_equals(
+ "2b:normVec: Fail ",
+ vec3D.mdV[VY],
+ y * mag,
+ 8);
+ ensure_approximately_equals(
+ "2c:normVec: Fail ",
+ vec3D.mdV[VZ],
+ z * mag,
+ 8);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<20>()
+ {
+ F64 x1 = 1111.232222;
+ F64 y1 = 2222222222.22;
+ F64 z1 = 422222222222.0;
+ std::string buf("1111.232222 2222222222.22 422222222222");
+ LLVector3d vec3Da, vec3Db(x1,y1,z1);
+ LLVector3d::parseVector3d(buf, &vec3Da);
+ ensure_equals("1:parseVector3 failed", vec3Da, vec3Db);
+ }
+
+ template<> template<>
+ void v3dmath_object::test<21>()
+ {
+ F64 x1 = 1., y1 = 2., z1 = -1.1;
+ F64 x2 = 1.2, y2 = 2.5, z2 = 1.;
+ F64 val = 2.3f,val1,val2,val3;
+ val1 = x1 + (x2 - x1)* val;
+ val2 = y1 + (y2 - y1)* val;
+ val3 = z1 + (z2 - z1)* val;
+ LLVector3d vec3Da(x1,y1,z1),vec3Db(x2,y2,z2);
+ LLVector3d vec3d = lerp(vec3Da,vec3Db,val);
+ ensure("1:lerp failed", ((val1 ==vec3d.mdV[VX])&& (val2 ==vec3d.mdV[VY]) && (val3 ==vec3d.mdV[VZ])));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<22>()
+ {
+ F64 x = 2.32, y = 1.212, z = -.12;
+ F64 min = 0.0001, max = 3.0;
+ LLVector3d vec3d(x,y,z);
+ ensure("1:clamp:Fail ", (TRUE == (vec3d.clamp(min, max))));
+ x = 0.000001f, z = 5.3f;
+ vec3d.setVec(x,y,z);
+ ensure("2:clamp:Fail ", (TRUE == (vec3d.clamp(min, max))));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<23>()
+ {
+ F64 x = 10., y = 20., z = -15.;
+ F64 epsilon = .23425;
+ LLVector3d vec3Da(x,y,z), vec3Db(x,y,z);
+ ensure("1:are_parallel: Fail ", (TRUE == are_parallel(vec3Da,vec3Db,epsilon)));
+ F64 x1 = -12., y1 = -20., z1 = -100.;
+ vec3Db.clearVec();
+ vec3Db.setVec(x1,y1,z1);
+ ensure("2:are_parallel: Fail ", (FALSE == are_parallel(vec3Da,vec3Db,epsilon)));
+ }
+
+ template<> template<>
+ void v3dmath_object::test<24>()
+ {
+#if LL_WINDOWS && _MSC_VER < 1400
+ skip("This fails on VS2003!");
+#else
+ F64 x = 10., y = 20., z = -15.;
+ F64 angle1, angle2;
+ LLVector3d vec3Da(x,y,z), vec3Db(x,y,z);
+ angle1 = angle_between(vec3Da, vec3Db);
+ ensure("1:angle_between: Fail ", (0 == angle1));
+ F64 x1 = -1., y1 = -20., z1 = -1.;
+ vec3Da.clearVec();
+ vec3Da.setVec(x1,y1,z1);
+ angle2 = angle_between(vec3Da, vec3Db);
+ vec3Db.normVec();
+ vec3Da.normVec();
+ F64 angle = vec3Db*vec3Da;
+ angle = acos(angle);
+ ensure("2:angle_between: Fail ", (angle == angle2));
+#endif
+ }
+}
diff --git a/indra/llmath/tests/v3math_test.cpp b/indra/llmath/tests/v3math_test.cpp
new file mode 100644
index 0000000000..e4732bf861
--- /dev/null
+++ b/indra/llmath/tests/v3math_test.cpp
@@ -0,0 +1,567 @@
+/**
+ * @file v3math_test.cpp
+ * @author Adroit
+ * @date 2007-02
+ * @brief v3math test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "llsd.h"
+
+#include "../llquaternion.h"
+#include "../llquantize.h"
+#include "../v3dmath.h"
+#include "../m3math.h"
+#include "../v4math.h"
+#include "../v3math.h"
+
+
+namespace tut
+{
+ struct v3math_data
+ {
+ };
+ typedef test_group<v3math_data> v3math_test;
+ typedef v3math_test::object v3math_object;
+ tut::v3math_test v3math_testcase("v3math_h");
+
+ template<> template<>
+ void v3math_object::test<1>()
+ {
+ LLVector3 vec3;
+ ensure("1:LLVector3:Fail to initialize ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3a(x,y,z);
+ ensure("2:LLVector3:Fail to initialize ", ((2.32f == vec3a.mV[VX]) && (1.212f == vec3a.mV[VY]) && (-.12f == vec3a.mV[VZ])));
+ const F32 vec[3] = {1.2f ,3.2f, -4.2f};
+ LLVector3 vec3b(vec);
+ ensure("3:LLVector3:Fail to initialize ", ((1.2f == vec3b.mV[VX]) && (3.2f == vec3b.mV[VY]) && (-4.2f == vec3b.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<2>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z);
+ LLVector3d vector3d(vec3);
+ LLVector3 vec3a(vector3d);
+ ensure("1:LLVector3:Fail to initialize ", vec3 == vec3a);
+ LLVector4 vector4(vec3);
+ LLVector3 vec3b(vector4);
+ ensure("2:LLVector3:Fail to initialize ", vec3 == vec3b);
+ }
+
+ template<> template<>
+ void v3math_object::test<3>()
+ {
+ S32 a = 231;
+ LLSD llsd(a);
+ LLVector3 vec3(llsd);
+ LLSD sd = vec3.getValue();
+ LLVector3 vec3a(sd);
+ ensure("1:LLVector3:Fail to initialize ", (vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<4>()
+ {
+ S32 a = 231;
+ LLSD llsd(a);
+ LLVector3 vec3(llsd),vec3a;
+ vec3a = vec3;
+ ensure("1:Operator= Fail to initialize " ,(vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<5>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z);
+ ensure("1:isFinite= Fail to initialize ", (TRUE == vec3.isFinite()));//need more test cases:
+ vec3.clearVec();
+ ensure("2:clearVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
+ vec3.setVec(x,y,z);
+ ensure("3:setVec:Fail to set values ", ((2.32f == vec3.mV[VX]) && (1.212f == vec3.mV[VY]) && (-.12f == vec3.mV[VZ])));
+ vec3.zeroVec();
+ ensure("4:zeroVec:Fail to set values ", ((0.f == vec3.mV[VX]) && (0.f == vec3.mV[VY]) && (0.f == vec3.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<6>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z),vec3a;
+ vec3.abs();
+ ensure("1:abs:Fail ", ((x == vec3.mV[VX]) && (y == vec3.mV[VY]) && (-z == vec3.mV[VZ])));
+ vec3a.setVec(vec3);
+ ensure("2:setVec:Fail to initialize ", (vec3a == vec3));
+ const F32 vec[3] = {1.2f ,3.2f, -4.2f};
+ vec3.clearVec();
+ vec3.setVec(vec);
+ ensure("3:setVec:Fail to initialize ", ((1.2f == vec3.mV[VX]) && (3.2f == vec3.mV[VY]) && (-4.2f == vec3.mV[VZ])));
+ vec3a.clearVec();
+ LLVector3d vector3d(vec3);
+ vec3a.setVec(vector3d);
+ ensure("4:setVec:Fail to initialize ", (vec3 == vec3a));
+ LLVector4 vector4(vec3);
+ vec3a.clearVec();
+ vec3a.setVec(vector4);
+ ensure("5:setVec:Fail to initialize ", (vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<7>()
+ {
+ F32 x = 2.32f, y = 3.212f, z = -.12f;
+ F32 min = 0.0001f, max = 3.0f;
+ LLVector3 vec3(x,y,z);
+ ensure("1:clamp:Fail ", TRUE == vec3.clamp(min, max) && x == vec3.mV[VX] && max == vec3.mV[VY] && min == vec3.mV[VZ]);
+ x = 1.f, y = 2.2f, z = 2.8f;
+ vec3.setVec(x,y,z);
+ ensure("2:clamp:Fail ", FALSE == vec3.clamp(min, max));
+ }
+
+ template<> template<>
+ void v3math_object::test<8>()
+ {
+ F32 x = 2.32f, y = 1.212f, z = -.12f;
+ LLVector3 vec3(x,y,z);
+ ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z)));
+ ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), fsqrtf(x*x + y*y + z*z)));
+ }
+
+ template<> template<>
+ void v3math_object::test<9>()
+ {
+ F32 x =-2.0f, y = -3.0f, z = 1.23f ;
+ LLVector3 vec3(x,y,z);
+ ensure("1:abs():Fail ", (TRUE == vec3.abs()));
+ ensure("2:isNull():Fail", (FALSE == vec3.isNull())); //Returns TRUE if vector has a _very_small_ length
+ x =.00000001f, y = .000001001f, z = .000001001f;
+ vec3.setVec(x,y,z);
+ ensure("3:isNull(): Fail ", (TRUE == vec3.isNull()));
+ }
+
+ template<> template<>
+ void v3math_object::test<10>()
+ {
+ F32 x =-2.0f, y = -3.0f, z = 1.f ;
+ LLVector3 vec3(x,y,z),vec3a;
+ ensure("1:isExactlyZero():Fail ", (TRUE == vec3a.isExactlyZero()));
+ vec3a = vec3a.scaleVec(vec3);
+ ensure("2:scaleVec: Fail ", vec3a.mV[VX] == 0.f && vec3a.mV[VY] == 0.f && vec3a.mV[VZ] == 0.f);
+ vec3a.setVec(x,y,z);
+ vec3a = vec3a.scaleVec(vec3);
+ ensure("3:scaleVec: Fail ", ((4 == vec3a.mV[VX]) && (9 == vec3a.mV[VY]) &&(1 == vec3a.mV[VZ])));
+ ensure("4:isExactlyZero():Fail ", (FALSE == vec3.isExactlyZero()));
+ }
+
+ template<> template<>
+ void v3math_object::test<11>()
+ {
+ F32 x =20.0f, y = 30.0f, z = 15.f ;
+ F32 angle = 100.f;
+ LLVector3 vec3(x,y,z),vec3a(1.f,2.f,3.f);
+ vec3a = vec3a.rotVec(angle, vec3);
+ LLVector3 vec3b(1.f,2.f,3.f);
+ vec3b = vec3b.rotVec(angle, vec3);
+ ensure_equals("rotVec():Fail" ,vec3b,vec3a);
+ }
+
+ template<> template<>
+ void v3math_object::test<12>()
+ {
+ F32 x =-2.0f, y = -3.0f, z = 1.f ;
+ LLVector3 vec3(x,y,z);
+ ensure("1:operator [] failed",( x == vec3[0]));
+ ensure("2:operator [] failed",( y == vec3[1]));
+ ensure("3:operator [] failed",( z == vec3[2]));
+
+ vec3.clearVec();
+ x = 23.f, y = -.2361f, z = 3.25;
+ vec3.setVec(x,y,z);
+ F32 &ref1 = vec3[0];
+ ensure("4:operator [] failed",( ref1 == vec3[0]));
+ F32 &ref2 = vec3[1];
+ ensure("5:operator [] failed",( ref2 == vec3[1]));
+ F32 &ref3 = vec3[2];
+ ensure("6:operator [] failed",( ref3 == vec3[2]));
+ }
+
+ template<> template<>
+ void v3math_object::test<13>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
+ vec3b = vec3 + vec3a ;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ val3 = z1+z2;
+ ensure("1:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3b.clearVec();
+ x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ vec3b = vec3 + vec3a;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ val3 = z1+z2;
+ ensure("2:operator+ failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<14>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
+ vec3b = vec3 - vec3a ;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ val3 = z1-z2;
+ ensure("1:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3b.clearVec();
+ x1 = -.235f, y1 = -24.32f,z1 = 2.13f, x2 = -2.3f, y2 = 1.f, z2 = 34.21f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ vec3b = vec3 - vec3a;
+ val1 = x1-x2;
+ val2 = y1-y2;
+ val3 = z1-z2;
+ ensure("2:operator- failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<15>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ val1 = vec3 * vec3a;
+ val2 = x1*x2 + y1*y2 + z1*z2;
+ ensure_equals("1:operator* failed",val1,val2);
+
+ vec3a.clearVec();
+ F32 mulVal = 4.332f;
+ vec3a = vec3 * mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ val3 = z1*mulVal;
+ ensure("2:operator* failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ vec3a.clearVec();
+ vec3a = mulVal * vec3;
+ ensure("3:operator* failed ", (val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<16>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2), vec3b;
+ vec3b = vec3 % vec3a ;
+ val1 = y1*z2 - y2*z1;
+ val2 = z1*x2 -z2*x1;
+ val3 = x1*y2-x2*y1;
+ ensure("1:operator% failed",(val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3b.clearVec();
+ x1 =112.f, y1 = 22.3f,z1 = 1.2f, x2 = -2.3f, y2 = 341.11f, z2 = 1234.234f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ vec3b = vec3 % vec3a ;
+ val1 = y1*z2 - y2*z1;
+ val2 = z1*x2 -z2*x1;
+ val3 = x1*y2-x2*y1;
+ ensure("2:operator% failed ", (val1 == vec3b.mV[VX]) && (val2 == vec3b.mV[VY]) && (val3 == vec3b.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<17>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f;
+ F32 t = 1.f / div, val1, val2, val3;
+ LLVector3 vec3(x1,y1,z1), vec3a;
+ vec3a = vec3 / div;
+ val1 = x1 * t;
+ val2 = y1 * t;
+ val3 = z1 *t;
+ ensure("1:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
+
+ vec3a.clearVec();
+ x1 = -.235f, y1 = -24.32f, z1 = .342f, div = -2.2f;
+ t = 1.f / div;
+ vec3.setVec(x1,y1,z1);
+ vec3a = vec3 / div;
+ val1 = x1 * t;
+ val2 = y1 * t;
+ val3 = z1 *t;
+ ensure("2:operator/ failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<18>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
+ LLVector3 vec3(x1,y1,z1), vec3a(x1,y1,z1);
+ ensure("1:operator== failed",(vec3 == vec3a));
+
+ vec3a.clearVec();
+ x1 = -.235f, y1 = -24.32f, z1 = .342f;
+ vec3.clearVec();
+ vec3a.clearVec();
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x1,y1,z1);
+ ensure("2:operator== failed ", (vec3 == vec3a));
+ }
+
+ template<> template<>
+ void v3math_object::test<19>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.234f,z2 = 11.2f;;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ ensure("1:operator!= failed",(vec3a != vec3));
+
+ vec3.clearVec();
+ vec3.clearVec();
+ vec3a.setVec(vec3);
+ ensure("2:operator!= failed", ( FALSE == (vec3a != vec3)));
+ }
+
+ template<> template<>
+ void v3math_object::test<20>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ vec3a += vec3;
+ F32 val1, val2, val3;
+ val1 = x1+x2;
+ val2 = y1+y2;
+ val3 = z1+z2;
+ ensure("1:operator+= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<21>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 =112.f, y2 = 2.2f,z2 = 11.2f;;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ vec3a -= vec3;
+ F32 val1, val2, val3;
+ val1 = x2-x1;
+ val2 = y2-y1;
+ val3 = z2-z1;
+ ensure("1:operator-= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<22>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val1,val2,val3;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ vec3a *= vec3;
+ val1 = x1*x2;
+ val2 = y1*y2;
+ val3 = z1*z2;
+ ensure("1:operator*= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY])&& (val3 == vec3a.mV[VZ]));
+
+ F32 mulVal = 4.332f;
+ vec3 *=mulVal;
+ val1 = x1*mulVal;
+ val2 = y1*mulVal;
+ val3 = z1*mulVal;
+ ensure("2:operator*= failed ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<23>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, x2 = -2.3f, y2 = 1.11f, z2 = 1234.234f;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2),vec3b;
+ vec3b = vec3a % vec3;
+ vec3a %= vec3;
+ ensure_equals("1:operator%= failed",vec3a,vec3b);
+ }
+
+ template<> template<>
+ void v3math_object::test<24>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f, div = 3.2f;
+ F32 t = 1.f / div, val1, val2, val3;
+ LLVector3 vec3a(x1,y1,z1);
+ vec3a /= div;
+ val1 = x1 * t;
+ val2 = y1 * t;
+ val3 = z1 *t;
+ ensure("1:operator/= failed",(val1 == vec3a.mV[VX]) && (val2 == vec3a.mV[VY]) && (val3 == vec3a.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<25>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
+ LLVector3 vec3(x1,y1,z1), vec3a;
+ vec3a = -vec3;
+ ensure("1:operator- failed",(-vec3a == vec3));
+ }
+
+ template<> template<>
+ void v3math_object::test<26>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 1.2f;
+ std::ostringstream stream1, stream2;
+ LLVector3 vec3(x1,y1,z1), vec3a;
+ stream1 << vec3;
+ vec3a.setVec(x1,y1,z1);
+ stream2 << vec3a;
+ ensure("1:operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v3math_object::test<27>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f;
+ LLVector3 vec3(x1,y1,z1), vec3a(x2,y2,z2);
+ ensure("1:operator< failed", (TRUE == (vec3 < vec3a)));
+ x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 2.f, z2 = 1234.234f;
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ ensure("2:operator< failed ", (TRUE == (vec3 < vec3a)));
+ x1 =2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f,
+ vec3.setVec(x1,y1,z1);
+ vec3a.setVec(x2,y2,z2);
+ ensure("3:operator< failed ", (FALSE == (vec3 < vec3a)));
+ }
+
+ template<> template<>
+ void v3math_object::test<28>()
+ {
+ F32 x1 =1.23f, y1 = 2.f,z1 = 4.f;
+ std::string buf("1.23 2. 4");
+ LLVector3 vec3, vec3a(x1,y1,z1);
+ LLVector3::parseVector3(buf, &vec3);
+ ensure_equals("1:parseVector3 failed", vec3, vec3a);
+ }
+
+ template<> template<>
+ void v3math_object::test<29>()
+ {
+ F32 x1 =1.f, y1 = 2.f,z1 = 4.f;
+ LLVector3 vec3(x1,y1,z1),vec3a,vec3b;
+ vec3a.setVec(1,1,1);
+ vec3a.scaleVec(vec3);
+ ensure_equals("1:scaleVec failed", vec3, vec3a);
+ vec3a.clearVec();
+ vec3a.setVec(x1,y1,z1);
+ vec3a.scaleVec(vec3);
+ ensure("2:scaleVec failed", ((1.f ==vec3a.mV[VX])&& (4.f ==vec3a.mV[VY]) && (16.f ==vec3a.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<30>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.11f, z2 = 1234.234f;
+ F32 val = 2.3f,val1,val2,val3;
+ val1 = x1 + (x2 - x1)* val;
+ val2 = y1 + (y2 - y1)* val;
+ val3 = z1 + (z2 - z1)* val;
+ LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2);
+ LLVector3 vec3b = lerp(vec3,vec3a,val);
+ ensure("1:lerp failed", ((val1 ==vec3b.mV[VX])&& (val2 ==vec3b.mV[VY]) && (val3 ==vec3b.mV[VZ])));
+ }
+
+ template<> template<>
+ void v3math_object::test<31>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f;
+ F32 val1,val2;
+ LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2);
+ val1 = dist_vec(vec3,vec3a);
+ val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("1:dist_vec: Fail ",val2, val1);
+ val1 = dist_vec_squared(vec3,vec3a);
+ val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("2:dist_vec_squared: Fail ",val2, val1);
+ val1 = dist_vec_squared2D(vec3, vec3a);
+ val2 =(x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2);
+ ensure_equals("3:dist_vec_squared2D: Fail ",val2, val1);
+ }
+
+ template<> template<>
+ void v3math_object::test<32>()
+ {
+ F32 x =12.3524f, y = -342.f,z = 4.126341f;
+ LLVector3 vec3(x,y,z);
+ F32 mag = vec3.normVec();
+ mag = 1.f/ mag;
+ F32 val1 = x* mag, val2 = y* mag, val3 = z* mag;
+ ensure("1:normVec: Fail ", is_approx_equal(val1, vec3.mV[VX]) && is_approx_equal(val2, vec3.mV[VY]) && is_approx_equal(val3, vec3.mV[VZ]));
+ x = 0.000000001f, y = 0.f, z = 0.f;
+ vec3.clearVec();
+ vec3.setVec(x,y,z);
+ mag = vec3.normVec();
+ val1 = x* mag, val2 = y* mag, val3 = z* mag;
+ ensure("2:normVec: Fail ", (mag == 0.) && (0. == vec3.mV[VX]) && (0. == vec3.mV[VY])&& (0. == vec3.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<33>()
+ {
+ F32 x = -202.23412f, y = 123.2312f, z = -89.f;
+ LLVector3 vec(x,y,z);
+ vec.snap(2);
+ ensure("1:snap: Fail ", is_approx_equal(-202.23f, vec.mV[VX]) && is_approx_equal(123.23f, vec.mV[VY]) && is_approx_equal(-89.f, vec.mV[VZ]));
+ }
+
+ template<> template<>
+ void v3math_object::test<34>()
+ {
+ F32 x = 10.f, y = 20.f, z = -15.f;
+ F32 x1, y1, z1;
+ F32 lowerxy = 0.f, upperxy = 1.0f, lowerz = -1.0f, upperz = 1.f;
+ LLVector3 vec3(x,y,z);
+ vec3.quantize16(lowerxy,upperxy,lowerz,upperz);
+ x1 = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy);
+ y1 = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy);
+ z1 = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz);
+ ensure("1:quantize16: Fail ", is_approx_equal(x1, vec3.mV[VX]) && is_approx_equal(y1, vec3.mV[VY]) && is_approx_equal(z1, vec3.mV[VZ]));
+ LLVector3 vec3a(x,y,z);
+ vec3a.quantize8(lowerxy,upperxy,lowerz,upperz);
+ x1 = U8_to_F32(F32_to_U8(x, lowerxy, upperxy), lowerxy, upperxy);
+ y1 = U8_to_F32(F32_to_U8(y, lowerxy, upperxy), lowerxy, upperxy);
+ z1 = U8_to_F32(F32_to_U8(z, lowerz, upperz), lowerz, upperz);
+ ensure("2:quantize8: Fail ", is_approx_equal(x1, vec3a.mV[VX]) && is_approx_equal(y1, vec3a.mV[VY]) && is_approx_equal(z1, vec3a.mV[VZ]));
+ }
+}
diff --git a/indra/llmath/tests/v4color_test.cpp b/indra/llmath/tests/v4color_test.cpp
new file mode 100644
index 0000000000..fbd43625d1
--- /dev/null
+++ b/indra/llmath/tests/v4color_test.cpp
@@ -0,0 +1,359 @@
+/**
+ * @file v4color_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v4color test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../v4coloru.h"
+#include "llsd.h"
+#include "../v3color.h"
+#include "../v4color.h"
+
+
+namespace tut
+{
+ struct v4color_data
+ {
+ };
+ typedef test_group<v4color_data> v4color_test;
+ typedef v4color_test::object v4color_object;
+ tut::v4color_test v4color_testcase("v4color_h");
+
+ template<> template<>
+ void v4color_object::test<1>()
+ {
+ LLColor4 llcolor4;
+ ensure("1:LLColor4:Fail to initialize ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
+
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF;
+ LLColor4 llcolor4a(r,g,b);
+ ensure("2:LLColor4:Fail to initialize ", ((r == llcolor4a.mV[VX]) && (g == llcolor4a.mV[VY]) && (b == llcolor4a.mV[VZ])&& (1.0f == llcolor4a.mV[VW])));
+
+ LLColor4 llcolor4b(r,g,b,a);
+ ensure("3:LLColor4:Fail to initialize ", ((r == llcolor4b.mV[VX]) && (g == llcolor4b.mV[VY]) && (b == llcolor4b.mV[VZ])&& (a == llcolor4b.mV[VW])));
+
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLColor4 llcolor4c(vec);
+ ensure("4:LLColor4:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW])));
+
+ LLColor3 llcolor3(-2.23f,1.01f,42.3f);
+ F32 val = -.1f;
+ LLColor4 llcolor4d(llcolor3,val);
+ ensure("5:LLColor4:Fail to initialize ", ((llcolor3.mV[VX] == llcolor4d.mV[VX]) && (llcolor3.mV[VY] == llcolor4d.mV[VY]) && (llcolor3.mV[VZ] == llcolor4d.mV[VZ])&& (val == llcolor4d.mV[VW])));
+
+ LLSD sd = llcolor4d.getValue();
+ LLColor4 llcolor4e(sd);
+ ensure_equals("6:LLColor4:(LLSD) failed ", llcolor4d, llcolor4e);
+
+ U8 r1 = 0xF2, g1 = 0xFA, b1 = 0xBF;
+ LLColor4U color4u(r1,g1,b1);
+ LLColor4 llcolor4g(color4u);
+ const F32 SCALE = 1.f/255.f;
+ F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE;
+ ensure("7:LLColor4:Fail to initialize ", ((r2 == llcolor4g.mV[VX]) && (g2 == llcolor4g.mV[VY]) && (b2 == llcolor4g.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<2>()
+ {
+ LLColor4 llcolor(1.0, 2.0, 3.0, 4.0);
+ LLSD llsd = llcolor.getValue();
+ LLColor4 llcolor4(llsd), llcolor4a;
+ llcolor4a.setValue(llsd);
+ ensure("setValue: failed", (llcolor4 == llcolor4a));
+ LLSD sd = llcolor4a.getValue();
+ LLColor4 llcolor4b(sd);
+ ensure("getValue: Failed ", (llcolor4b == llcolor4a));
+ }
+
+ template<> template<>
+ void v4color_object::test<3>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0xAF;
+ LLColor4 llcolor4(r,g,b,a);
+ llcolor4.setToBlack();
+ ensure("setToBlack:Fail to set the black ", ((0 == llcolor4.mV[VX]) && (0 == llcolor4.mV[VY]) && (0 == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
+
+ llcolor4.setToWhite();
+ ensure("setToWhite:Fail to set the white ", ((1.f == llcolor4.mV[VX]) && (1.f == llcolor4.mV[VY]) && (1.f == llcolor4.mV[VZ])&& (1.0f == llcolor4.mV[VW])));
+ }
+
+ template<> template<>
+ void v4color_object::test<4>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF, a = 0xAF;
+ LLColor4 llcolor4;
+ llcolor4.setVec(r,g,b);
+ ensure("1:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (1.f == llcolor4.mV[VW])));
+
+ llcolor4.setVec(r,g,b,a);
+ ensure("2:setVec:Fail to set the values ", ((r == llcolor4.mV[VX]) && (g == llcolor4.mV[VY]) && (b == llcolor4.mV[VZ])&& (a == llcolor4.mV[VW])));
+
+ LLColor4 llcolor4a;
+ llcolor4a.setVec(llcolor4);
+ ensure_equals("3:setVec:Fail to set the values ", llcolor4a,llcolor4);
+
+ LLColor3 llcolor3(-2.23f,1.01f,42.3f);
+ llcolor4a.setVec(llcolor3);
+ ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ])));
+
+ F32 val = -.33f;
+ llcolor4a.setVec(llcolor3,val);
+ ensure("4:setVec:Fail to set the values ", ((llcolor3.mV[VX] == llcolor4a.mV[VX]) && (llcolor3.mV[VY] == llcolor4a.mV[VY]) && (llcolor3.mV[VZ] == llcolor4a.mV[VZ]) && (val == llcolor4a.mV[VW])));
+
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLColor4 llcolor4c;
+ llcolor4c.setVec(vec);
+ ensure("5:setVec:Fail to initialize ", ((vec[0] == llcolor4c.mV[VX]) && (vec[1] == llcolor4c.mV[VY]) && (vec[2] == llcolor4c.mV[VZ])&& (vec[3] == llcolor4c.mV[VW])));
+
+ U8 r1 = 0xF2, g1 = 0xFA, b1= 0xBF;
+ LLColor4U color4u(r1,g1,b1);
+ llcolor4.setVec(color4u);
+ const F32 SCALE = 1.f/255.f;
+ F32 r2 = r1*SCALE, g2 = g1* SCALE, b2 = b1* SCALE;
+ ensure("6:setVec:Fail to initialize ", ((r2 == llcolor4.mV[VX]) && (g2 == llcolor4.mV[VY]) && (b2 == llcolor4.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<5>()
+ {
+ F32 alpha = 0xAF;
+ LLColor4 llcolor4;
+ llcolor4.setAlpha(alpha);
+ ensure("setAlpha:Fail to initialize ", (alpha == llcolor4.mV[VW]));
+ }
+
+ template<> template<>
+ void v4color_object::test<6>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4(r,g,b);
+ ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b)));
+ ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), fsqrtf(r*r + g*g + b*b)));
+ }
+
+ template<> template<>
+ void v4color_object::test<7>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4(r,g,b);
+ F32 vecMag = llcolor4.normVec();
+ F32 mag = fsqrtf(r*r + g*g + b*b);
+ F32 oomag = 1.f / mag;
+ F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag;
+ ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag)));
+ }
+
+ template<> template<>
+ void v4color_object::test<8>()
+ {
+ LLColor4 llcolor4;
+ ensure("1:isOpaque failed ",(1 == llcolor4.isOpaque()));
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 1.f;
+ llcolor4.setVec(r,g,b,a);
+ ensure("2:isOpaque failed ",(1 == llcolor4.isOpaque()));
+ a = 2.f;
+ llcolor4.setVec(r,g,b,a);
+ ensure("3:isOpaque failed ",(0 == llcolor4.isOpaque()));
+ }
+
+ template<> template<>
+ void v4color_object::test<9>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4(r,g,b);
+ ensure("1:operator [] failed",( r == llcolor4[0]));
+ ensure("2:operator [] failed",( g == llcolor4[1]));
+ ensure("3:operator [] failed",( b == llcolor4[2]));
+
+ r = 0xA20, g = 0xFBFF, b = 0xFFF;
+ llcolor4.setVec(r,g,b);
+ F32 &ref1 = llcolor4[0];
+ ensure("4:operator [] failed",( ref1 == llcolor4[0]));
+ F32 &ref2 = llcolor4[1];
+ ensure("5:operator [] failed",( ref2 == llcolor4[1]));
+ F32 &ref3 = llcolor4[2];
+ ensure("6:operator [] failed",( ref3 == llcolor4[2]));
+ }
+
+ template<> template<>
+ void v4color_object::test<10>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor3 llcolor3(r,g,b);
+ LLColor4 llcolor4a,llcolor4b;
+ llcolor4a = llcolor3;
+ ensure("Operator=:Fail to initialize ", ((llcolor3.mV[0] == llcolor4a.mV[VX]) && (llcolor3.mV[1] == llcolor4a.mV[VY]) && (llcolor3.mV[2] == llcolor4a.mV[VZ])));
+ LLSD sd = llcolor4a.getValue();
+ llcolor4b = LLColor4(sd);
+ ensure_equals("Operator= LLSD:Fail ", llcolor4a, llcolor4b);
+ }
+
+ template<> template<>
+ void v4color_object::test<11>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ std::ostringstream stream1, stream2;
+ LLColor4 llcolor4a(r,g,b),llcolor4b;
+ stream1 << llcolor4a;
+ llcolor4b.setVec(r,g,b);
+ stream2 << llcolor4b;
+ ensure("operator << failed ", (stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v4color_object::test<12>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = llcolor4b + llcolor4a;
+ ensure("operator+:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4c.mV[VX]) && is_approx_equal(g1+g2,llcolor4c.mV[VY]) && is_approx_equal(b1+b2,llcolor4c.mV[VZ])));
+
+ llcolor4b += llcolor4a;
+ ensure("operator+=:Fail to Add the values ", (is_approx_equal(r1+r2,llcolor4b.mV[VX]) && is_approx_equal(g1+g2,llcolor4b.mV[VY]) && is_approx_equal(b1+b2,llcolor4b.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<13>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = llcolor4a - llcolor4b;
+ ensure("operator-:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4c.mV[VX]) && is_approx_equal(g1-g2,llcolor4c.mV[VY]) && is_approx_equal(b1-b2,llcolor4c.mV[VZ])));
+
+ llcolor4a -= llcolor4b;
+ ensure("operator-=:Fail to subtract the values ", (is_approx_equal(r1-r2,llcolor4a.mV[VX]) && is_approx_equal(g1-g2,llcolor4a.mV[VY]) && is_approx_equal(b1-b2,llcolor4a.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<14>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = llcolor4a * llcolor4b;
+ ensure("1:operator*:Fail to multiply the values", (is_approx_equal(r1*r2,llcolor4c.mV[VX]) && is_approx_equal(g1*g2,llcolor4c.mV[VY]) && is_approx_equal(b1*b2,llcolor4c.mV[VZ])));
+
+ F32 mulVal = 3.33f;
+ llcolor4c = llcolor4a * mulVal;
+ ensure("2:operator*:Fail ", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ])));
+ llcolor4c = mulVal * llcolor4a;
+ ensure("3:operator*:Fail to multiply the values", (is_approx_equal(r1*mulVal,llcolor4c.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4c.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4c.mV[VZ])));
+
+ llcolor4a *= mulVal;
+ ensure("4:operator*=:Fail to multiply the values ", (is_approx_equal(r1*mulVal,llcolor4a.mV[VX]) && is_approx_equal(g1*mulVal,llcolor4a.mV[VY]) && is_approx_equal(b1*mulVal,llcolor4a.mV[VZ])));
+
+ LLColor4 llcolor4d(r1,g1,b1),llcolor4e(r2,g2,b2);
+ llcolor4e *= llcolor4d;
+ ensure("5:operator*=:Fail to multiply the values ", (is_approx_equal(r1*r2,llcolor4e.mV[VX]) && is_approx_equal(g1*g2,llcolor4e.mV[VY]) && is_approx_equal(b1*b2,llcolor4e.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<15>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30;
+ F32 div = 12.345f;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ llcolor4b = llcolor4a % div;//chnage only alpha value nor r,g,b;
+ ensure("1operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW])));
+
+ llcolor4b = div % llcolor4a;
+ ensure("2operator%:Fail ", (is_approx_equal(r,llcolor4b.mV[VX]) && is_approx_equal(g,llcolor4b.mV[VY]) && is_approx_equal(b,llcolor4b.mV[VZ])&& is_approx_equal(div*a,llcolor4b.mV[VW])));
+
+ llcolor4a %= div;
+ ensure("operator%=:Fail ", (is_approx_equal(a*div,llcolor4a.mV[VW])));
+ }
+
+ template<> template<>
+ void v4color_object::test<16>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF,a = 0x30;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ llcolor4b = llcolor4a;
+ ensure("1:operator== failed to ensure the equality ", (llcolor4b == llcolor4a));
+ F32 r1 = 0x2, g1 = 0xFF, b1 = 0xFA;
+ LLColor3 llcolor3(r1,g1,b1);
+ llcolor4b = llcolor3;
+ ensure("2:operator== failed to ensure the equality ", (llcolor4b == llcolor3));
+ ensure("2:operator!= failed to ensure the equality ", (llcolor4a != llcolor3));
+ }
+
+ template<> template<>
+ void v4color_object::test<17>()
+ {
+ F32 r = 0x20, g = 0xFFFF, b = 0xFF;
+ LLColor4 llcolor4a(r,g,b),llcolor4b;
+ LLColor3 llcolor3 = vec4to3(llcolor4a);
+ ensure("vec4to3:Fail to convert vec4 to vec3 ", (is_approx_equal(llcolor3.mV[VX],llcolor4a.mV[VX]) && is_approx_equal(llcolor3.mV[VY],llcolor4a.mV[VY]) && is_approx_equal(llcolor3.mV[VZ],llcolor4a.mV[VZ])));
+ llcolor4b = vec3to4(llcolor3);
+ ensure_equals("vec3to4:Fail to convert vec3 to vec4 ", llcolor4b, llcolor4a);
+ }
+
+ template<> template<>
+ void v4color_object::test<18>()
+ {
+ F32 r1 = 0x20, g1 = 0xFFFF, b1 = 0xFF, val = 0x20;
+ F32 r2 = 0xABF, g2 = 0xFB, b2 = 0xFFF;
+ LLColor4 llcolor4a(r1,g1,b1),llcolor4b(r2,g2,b2),llcolor4c;
+ llcolor4c = lerp(llcolor4a,llcolor4b,val);
+ ensure("lerp:Fail ", (is_approx_equal(r1 + (r2 - r1)* val,llcolor4c.mV[VX]) && is_approx_equal(g1 + (g2 - g1)* val,llcolor4c.mV[VY]) && is_approx_equal(b1 + (b2 - b1)* val,llcolor4c.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4color_object::test<19>()
+ {
+ F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ std::string color("red");
+ LLColor4::parseColor(color, &llcolor4b);
+ ensure_equals("1:parseColor() failed to parse the color value ", llcolor4b, LLColor4::red);
+
+ color = "12.0, -2.3, 1.32, 5.0";
+ LLColor4::parseColor(color, &llcolor4b);
+ llcolor4a = llcolor4a * (1.f / 255.f);
+ ensure_equals("2:parseColor() failed to parse the color value ", llcolor4a,llcolor4b);
+
+ color = "yellow5";
+ llcolor4a.setVec(r,g,b);
+ LLColor4::parseColor(color, &llcolor4a);
+ ensure_equals("3:parseColor() failed to parse the color value ", llcolor4a, LLColor4::yellow5);
+ }
+
+ template<> template<>
+ void v4color_object::test<20>()
+ {
+ F32 r = 12.0f, g = -2.3f, b = 1.32f, a = 5.0f;
+ LLColor4 llcolor4a(r,g,b,a),llcolor4b;
+ std::string color("12.0, -2.3, 1.32, 5.0");
+ LLColor4::parseColor4(color, &llcolor4b);
+ ensure_equals("parseColor4() failed to parse the color value ", llcolor4a, llcolor4b);
+ }
+}
diff --git a/indra/llmath/tests/v4coloru_test.cpp b/indra/llmath/tests/v4coloru_test.cpp
new file mode 100644
index 0000000000..6d84ba41ef
--- /dev/null
+++ b/indra/llmath/tests/v4coloru_test.cpp
@@ -0,0 +1,336 @@
+/**
+ * @file v4coloru_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v4coloru test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "llsd.h"
+
+#include "../v4coloru.h"
+
+
+namespace tut
+{
+ struct v4coloru_data
+ {
+ };
+ typedef test_group<v4coloru_data> v4coloru_test;
+ typedef v4coloru_test::object v4coloru_object;
+ tut::v4coloru_test v4coloru_testcase("v4coloru_h");
+
+ template<> template<>
+ void v4coloru_object::test<1>()
+ {
+ LLColor4U llcolor4u;
+ ensure("1:LLColor4u:Fail to initialize ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4u1(r,g,b);
+ ensure("2:LLColor4u:Fail to initialize ", ((r == llcolor4u1.mV[VX]) && (g == llcolor4u1.mV[VY]) && (b == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW])));
+
+ LLColor4U llcolor4u2(r,g,b,a);
+ ensure("3:LLColor4u:Fail to initialize ", ((r == llcolor4u2.mV[VX]) && (g == llcolor4u2.mV[VY]) && (b == llcolor4u2.mV[VZ])&& (a == llcolor4u2.mV[VW])));
+
+ const U8 vec[4] = {0x12,0xFF,0xAF,0x23};
+ LLColor4U llcolor4u3(vec);
+ ensure("4:LLColor4u:Fail to initialize ", ((vec[0] == llcolor4u3.mV[VX]) && (vec[1] == llcolor4u3.mV[VY]) && (vec[2] == llcolor4u3.mV[VZ])&& (vec[3] == llcolor4u3.mV[VW])));
+
+ LLSD sd = llcolor4u3.getValue();
+ LLColor4U llcolor4u4(sd);
+ ensure_equals("5:LLColor4u (LLSD) Failed ", llcolor4u4, llcolor4u3);
+ }
+
+ template<> template<>
+ void v4coloru_object::test<2>()
+ {
+ LLColor4U llcolor4ua(1, 2, 3, 4);
+ LLSD sd = llcolor4ua.getValue();
+ LLColor4U llcolor4u;
+ llcolor4u.setValue(sd);
+ ensure_equals("setValue(LLSD)/getValue Failed ", llcolor4u, llcolor4ua);
+ }
+
+ template<> template<>
+ void v4coloru_object::test<3>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4u(r,g,b,a);
+ llcolor4u.setToBlack();
+ ensure("setToBlack:Fail to set black ", ((0 == llcolor4u.mV[VX]) && (0 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+
+ llcolor4u.setToWhite();
+ ensure("setToWhite:Fail to white ", ((255 == llcolor4u.mV[VX]) && (255 == llcolor4u.mV[VY]) && (255 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<4>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4ua(r,g,b,a);
+ LLSD sd = llcolor4ua.getValue();
+ LLColor4U llcolor4u = (LLColor4U)sd;
+ ensure_equals("Operator=(LLSD) Failed ", llcolor4u, llcolor4ua);
+ }
+
+ template<> template<>
+ void v4coloru_object::test<5>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 0x23;
+ LLColor4U llcolor4u;
+ llcolor4u.setVec(r,g,b,a);
+ ensure("1:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (a == llcolor4u.mV[VW])));
+
+ llcolor4u.setToBlack();
+ llcolor4u.setVec(r,g,b);
+ ensure("2:setVec:Fail to set the values ", ((r == llcolor4u.mV[VX]) && (g == llcolor4u.mV[VY]) && (b == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+
+ LLColor4U llcolor4u1;
+ llcolor4u1.setVec(llcolor4u);
+ ensure_equals("3:setVec:Fail to set the values ", llcolor4u1,llcolor4u);
+
+ const U8 vec[4] = {0x12,0xFF,0xAF,0x23};
+ LLColor4U llcolor4u2;
+ llcolor4u2.setVec(vec);
+ ensure("4:setVec:Fail to set the values ", ((vec[0] == llcolor4u2.mV[VX]) && (vec[1] == llcolor4u2.mV[VY]) && (vec[2] == llcolor4u2.mV[VZ])&& (vec[3] == llcolor4u2.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<6>()
+ {
+ U8 alpha = 0x12;
+ LLColor4U llcolor4u;
+ llcolor4u.setAlpha(alpha);
+ ensure("setAlpha:Fail to set alpha value ", (alpha == llcolor4u.mV[VW]));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<7>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF;
+ LLColor4U llcolor4u(r,g,b);
+ ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b)));
+ ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), fsqrtf(r*r + g*g + b*b)));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<8>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF;
+ std::ostringstream stream1, stream2;
+ LLColor4U llcolor4u1(r,g,b),llcolor4u2;
+ stream1 << llcolor4u1;
+ llcolor4u2.setVec(r,g,b);
+ stream2 << llcolor4u2;
+ ensure("operator << failed ", (stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<9>()
+ {
+ U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
+ U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
+ LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
+ llcolor4u3 = llcolor4u1 + llcolor4u2;
+ ensure_equals(
+ "1a.operator+:Fail to Add the values ",
+ llcolor4u3.mV[VX],
+ (U8)(r1+r2));
+ ensure_equals(
+ "1b.operator+:Fail to Add the values ",
+ llcolor4u3.mV[VY],
+ (U8)(g1+g2));
+ ensure_equals(
+ "1c.operator+:Fail to Add the values ",
+ llcolor4u3.mV[VZ],
+ (U8)(b1+b2));
+
+ llcolor4u2 += llcolor4u1;
+ ensure_equals(
+ "2a.operator+=:Fail to Add the values ",
+ llcolor4u2.mV[VX],
+ (U8)(r1+r2));
+ ensure_equals(
+ "2b.operator+=:Fail to Add the values ",
+ llcolor4u2.mV[VY],
+ (U8)(g1+g2));
+ ensure_equals(
+ "2c.operator+=:Fail to Add the values ",
+ llcolor4u2.mV[VZ],
+ (U8)(b1+b2));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<10>()
+ {
+ U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
+ U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
+ LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
+ llcolor4u3 = llcolor4u1 - llcolor4u2;
+ ensure_equals(
+ "1a. operator-:Fail to Add the values ",
+ llcolor4u3.mV[VX],
+ (U8)(r1-r2));
+ ensure_equals(
+ "1b. operator-:Fail to Add the values ",
+ llcolor4u3.mV[VY],
+ (U8)(g1-g2));
+ ensure_equals(
+ "1c. operator-:Fail to Add the values ",
+ llcolor4u3.mV[VZ],
+ (U8)(b1-b2));
+
+ llcolor4u1 -= llcolor4u2;
+ ensure_equals(
+ "2a. operator-=:Fail to Add the values ",
+ llcolor4u1.mV[VX],
+ (U8)(r1-r2));
+ ensure_equals(
+ "2b. operator-=:Fail to Add the values ",
+ llcolor4u1.mV[VY],
+ (U8)(g1-g2));
+ ensure_equals(
+ "2c. operator-=:Fail to Add the values ",
+ llcolor4u1.mV[VZ],
+ (U8)(b1-b2));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<11>()
+ {
+ U8 r1 = 0x12, g1 = 0xFF, b1 = 0xAF;
+ U8 r2 = 0x1C, g2 = 0x9A, b2 = 0x1B;
+ LLColor4U llcolor4u1(r1,g1,b1), llcolor4u2(r2,g2,b2),llcolor4u3;
+ llcolor4u3 = llcolor4u1 * llcolor4u2;
+ ensure_equals(
+ "1a. operator*:Fail to multiply the values",
+ llcolor4u3.mV[VX],
+ (U8)(r1*r2));
+ ensure_equals(
+ "1b. operator*:Fail to multiply the values",
+ llcolor4u3.mV[VY],
+ (U8)(g1*g2));
+ ensure_equals(
+ "1c. operator*:Fail to multiply the values",
+ llcolor4u3.mV[VZ],
+ (U8)(b1*b2));
+
+ U8 mulVal = 123;
+ llcolor4u1 *= mulVal;
+ ensure_equals(
+ "2a. operator*=:Fail to multiply the values",
+ llcolor4u1.mV[VX],
+ (U8)(r1*mulVal));
+ ensure_equals(
+ "2b. operator*=:Fail to multiply the values",
+ llcolor4u1.mV[VY],
+ (U8)(g1*mulVal));
+ ensure_equals(
+ "2c. operator*=:Fail to multiply the values",
+ llcolor4u1.mV[VZ],
+ (U8)(b1*mulVal));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<12>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF;
+ LLColor4U llcolor4u(r,g,b),llcolor4u1;
+ llcolor4u1 = llcolor4u;
+ ensure("operator== failed to ensure the equality ", (llcolor4u1 == llcolor4u));
+ llcolor4u1.setToBlack();
+ ensure("operator!= failed to ensure the equality ", (llcolor4u1 != llcolor4u));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<13>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12;
+ LLColor4U llcolor4u(r,g,b,a);
+ U8 modVal = 45;
+ llcolor4u %= modVal;
+ ensure_equals("operator%=:Fail ", llcolor4u.mV[VW], (U8)(a * modVal));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<14>()
+ {
+ U8 r = 0x12, g = 0xFF, b = 0xAF, a = 12;
+ LLColor4U llcolor4u1(r,g,b,a);
+ std::string color("12, 23, 132, 50");
+ LLColor4U::parseColor4U(color, &llcolor4u1);
+ ensure("parseColor4U() failed to parse the color value ", ((12 == llcolor4u1.mV[VX]) && (23 == llcolor4u1.mV[VY]) && (132 == llcolor4u1.mV[VZ])&& (50 == llcolor4u1.mV[VW])));
+
+ color = "12, 23, 132";
+ ensure("2:parseColor4U() failed to parse the color value ", (FALSE == LLColor4U::parseColor4U(color, &llcolor4u1)));
+
+ color = "12";
+ ensure("2:parseColor4U() failed to parse the color value ", (FALSE == LLColor4U::parseColor4U(color, &llcolor4u1)));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<15>()
+ {
+ U8 r = 12, g = 123, b = 3, a = 2;
+ LLColor4U llcolor4u(r,g,b,a),llcolor4u1;
+ const F32 fVal = 3.f;
+ llcolor4u1 = llcolor4u.multAll(fVal);
+ ensure("multAll:Fail to multiply ", (((U8)llround(r * fVal) == llcolor4u1.mV[VX]) && (U8)llround(g * fVal) == llcolor4u1.mV[VY]
+ && ((U8)llround(b * fVal) == llcolor4u1.mV[VZ])&& ((U8)llround(a * fVal) == llcolor4u1.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<16>()
+ {
+ U8 r1 = 12, g1 = 123, b1 = 3, a1 = 2;
+ U8 r2 = 23, g2 = 230, b2 = 124, a2 = 255;
+ LLColor4U llcolor4u(r1,g1,b1,a1),llcolor4u1(r2,g2,b2,a2);
+ llcolor4u1 = llcolor4u1.addClampMax(llcolor4u);
+ ensure("1:addClampMax():Fail to add the value ", ((r1+r2 == llcolor4u1.mV[VX]) && (255 == llcolor4u1.mV[VY]) && (b1+b2 == llcolor4u1.mV[VZ])&& (255 == llcolor4u1.mV[VW])));
+
+ r1 = 132, g1 = 3, b1 = 3, a1 = 2;
+ r2 = 123, g2 = 230, b2 = 154, a2 = 25;
+ LLColor4U llcolor4u2(r1,g1,b1,a1),llcolor4u3(r2,g2,b2,a2);
+ llcolor4u3 = llcolor4u3.addClampMax(llcolor4u2);
+ ensure("2:addClampMax():Fail to add the value ", ((255 == llcolor4u3.mV[VX]) && (g1+g2 == llcolor4u3.mV[VY]) && (b1+b2 == llcolor4u3.mV[VZ])&& (a1+a2 == llcolor4u3.mV[VW])));
+ }
+
+ template<> template<>
+ void v4coloru_object::test<17>()
+ {
+ F32 r = 23.f, g = 12.32f, b = -12.3f;
+ LLColor3 color3(r,g,b);
+ LLColor4U llcolor4u;
+ llcolor4u.setVecScaleClamp(color3);
+ const S32 MAX_COLOR = 255;
+ F32 color_scale_factor = MAX_COLOR/r;
+ S32 r2 = llround(r * color_scale_factor);
+ S32 g2 = llround(g * color_scale_factor);
+ ensure("setVecScaleClamp():Fail to add the value ", ((r2 == llcolor4u.mV[VX]) && (g2 == llcolor4u.mV[VY]) && (0 == llcolor4u.mV[VZ])&& (255 == llcolor4u.mV[VW])));
+ }
+}
diff --git a/indra/llmath/tests/v4math_test.cpp b/indra/llmath/tests/v4math_test.cpp
new file mode 100644
index 0000000000..b1f934e555
--- /dev/null
+++ b/indra/llmath/tests/v4math_test.cpp
@@ -0,0 +1,382 @@
+/**
+ * @file v4math_test.cpp
+ * @author Adroit
+ * @date 2007-03
+ * @brief v4math test cases.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+#include "llsd.h"
+
+#include "../llquaternion.h"
+#include "../m4math.h"
+#include "../v4math.h"
+
+namespace tut
+{
+ struct v4math_data
+ {
+ };
+ typedef test_group<v4math_data> v4math_test;
+ typedef v4math_test::object v4math_object;
+ tut::v4math_test v4math_testcase("v4math_h");
+
+ template<> template<>
+ void v4math_object::test<1>()
+ {
+ LLVector4 vec4;
+ ensure("1:LLVector4:Fail to initialize " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4a(x,y,z);
+ ensure("2:LLVector4:Fail to initialize " ,((x == vec4a.mV[VX]) && (y == vec4a.mV[VY]) && (z == vec4a.mV[VZ])&& (1.0f == vec4a.mV[VW])));
+ LLVector4 vec4b(x,y,z,w);
+ ensure("3:LLVector4:Fail to initialize " ,((x == vec4b.mV[VX]) && (y == vec4b.mV[VY]) && (z == vec4b.mV[VZ])&& (w == vec4b.mV[VW])));
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLVector4 vec4c(vec);
+ ensure("4:LLVector4:Fail to initialize " ,((vec[0] == vec4c.mV[VX]) && (vec[1] == vec4c.mV[VY]) && (vec[2] == vec4c.mV[VZ])&& (vec[3] == vec4c.mV[VW])));
+ LLVector3 vec3(-2.23f,1.01f,42.3f);
+ LLVector4 vec4d(vec3);
+ ensure("5:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4d.mV[VX]) && (vec3.mV[VY] == vec4d.mV[VY]) && (vec3.mV[VZ] == vec4d.mV[VZ])&& (1.f == vec4d.mV[VW])));
+ F32 w1 = -.234f;
+ LLVector4 vec4e(vec3,w1);
+ ensure("6:LLVector4:Fail to initialize " ,((vec3.mV[VX] == vec4e.mV[VX]) && (vec3.mV[VY] == vec4e.mV[VY]) && (vec3.mV[VZ] == vec4e.mV[VZ])&& (w1 == vec4e.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<2>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4;
+ vec4.setVec(x,y,z);
+ ensure("1:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
+ vec4.clearVec();
+ ensure("2:clearVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (1.0f == vec4.mV[VW])));
+ vec4.setVec(x,y,z,w);
+ ensure("3:setVec:Fail to initialize " ,((x == vec4.mV[VX]) && (y == vec4.mV[VY]) && (z == vec4.mV[VZ])&& (w == vec4.mV[VW])));
+ vec4.zeroVec();
+ ensure("4:zeroVec:Fail " ,((0 == vec4.mV[VX]) && (0 == vec4.mV[VY]) && (0 == vec4.mV[VZ])&& (0 == vec4.mV[VW])));
+ LLVector3 vec3(-2.23f,1.01f,42.3f);
+ vec4.clearVec();
+ vec4.setVec(vec3);
+ ensure("5:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (1.f == vec4.mV[VW])));
+ F32 w1 = -.234f;
+ vec4.zeroVec();
+ vec4.setVec(vec3,w1);
+ ensure("6:setVec:Fail to initialize " ,((vec3.mV[VX] == vec4.mV[VX]) && (vec3.mV[VY] == vec4.mV[VY]) && (vec3.mV[VZ] == vec4.mV[VZ])&& (w1 == vec4.mV[VW])));
+ const F32 vec[4] = {.112f ,23.2f, -4.2f, -.0001f};
+ LLVector4 vec4a;
+ vec4a.setVec(vec);
+ ensure("7:setVec:Fail to initialize " ,((vec[0] == vec4a.mV[VX]) && (vec[1] == vec4a.mV[VY]) && (vec[2] == vec4a.mV[VZ])&& (vec[3] == vec4a.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<3>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f;
+ LLVector4 vec4(x,y,z);
+ ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), fsqrtf(x*x + y*y + z*z)));
+ ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z)));
+ }
+
+ template<> template<>
+ void v4math_object::test<4>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f;
+ LLVector4 vec4(x,y,z);
+ F32 mag = vec4.normVec();
+ mag = 1.f/ mag;
+ ensure("1:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ]));
+ x = 0.000000001f, y = 0.000000001f, z = 0.000000001f;
+ vec4.clearVec();
+ vec4.setVec(x,y,z);
+ mag = vec4.normVec();
+ ensure("2:normVec: Fail " ,is_approx_equal(mag*x,vec4.mV[VX]) && is_approx_equal(mag*y, vec4.mV[VY])&& is_approx_equal(mag*z, vec4.mV[VZ]));
+ }
+
+ template<> template<>
+ void v4math_object::test<5>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w);
+ vec4.abs();
+ ensure("abs:Fail " ,((x == vec4.mV[VX]) && (-y == vec4.mV[VY]) && (-z == vec4.mV[VZ])&& (-w == vec4.mV[VW])));
+ vec4.clearVec();
+ ensure("isExactlyClear:Fail " ,(TRUE == vec4.isExactlyClear()));
+ vec4.zeroVec();
+ ensure("isExactlyZero:Fail " ,(TRUE == vec4.isExactlyZero()));
+ }
+
+ template<> template<>
+ void v4math_object::test<6>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w),vec4a;
+ vec4a = vec4.scaleVec(vec4);
+ ensure("scaleVec:Fail " ,(is_approx_equal(x*x, vec4a.mV[VX]) && is_approx_equal(y*y, vec4a.mV[VY]) && is_approx_equal(z*z, vec4a.mV[VZ])&& is_approx_equal(w*w, vec4a.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<7>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w);
+ ensure("1:operator [] failed " ,( x == vec4[0]));
+ ensure("2:operator [] failed " ,( y == vec4[1]));
+ ensure("3:operator [] failed " ,( z == vec4[2]));
+ ensure("4:operator [] failed " ,( w == vec4[3]));
+ x = 23.f, y = -.2361f, z = 3.25;
+ vec4.setVec(x,y,z);
+ F32 &ref1 = vec4[0];
+ ensure("5:operator [] failed " ,( ref1 == vec4[0]));
+ F32 &ref2 = vec4[1];
+ ensure("6:operator [] failed " ,( ref2 == vec4[1]));
+ F32 &ref3 = vec4[2];
+ ensure("7:operator [] failed " ,( ref3 == vec4[2]));
+ F32 &ref4 = vec4[3];
+ ensure("8:operator [] failed " ,( ref4 == vec4[3]));
+ }
+
+ template<> template<>
+ void v4math_object::test<8>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ const F32 val[16] = {
+ 1.f, 2.f, 3.f, 0.f,
+ .34f, .1f, -.5f, 0.f,
+ 2.f, 1.23f, 1.234f, 0.f,
+ .89f, 0.f, 0.f, 0.f
+ };
+ LLMatrix4 mat(val);
+ LLVector4 vec4(x,y,z,w),vec4a;
+ vec4.rotVec(mat);
+ vec4a.setVec(x,y,z,w);
+ vec4a.rotVec(mat);
+ ensure_equals("1:rotVec: Fail " ,vec4a, vec4);
+ F32 a = 2.32f, b = -23.2f, c = -34.1112f, d = 1.010112f;
+ LLQuaternion q(a,b,c,d);
+ LLVector4 vec4b(a,b,c,d),vec4c;
+ vec4b.rotVec(q);
+ vec4c.setVec(a, b, c, d);
+ vec4c.rotVec(q);
+ ensure_equals("2:rotVec: Fail " ,vec4b, vec4c);
+ }
+
+ template<> template<>
+ void v4math_object::test<9>()
+ {
+ F32 x = 10.f, y = -2.3f, z = -.023f, w = -2.0f;
+ LLVector4 vec4(x,y,z,w),vec4a;;
+ std::ostringstream stream1, stream2;
+ stream1 << vec4;
+ vec4a.setVec(x,y,z,w);
+ stream2 << vec4a;
+ ensure("operator << failed",(stream1.str() == stream2.str()));
+ }
+
+ template<> template<>
+ void v4math_object::test<10>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f;
+ LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b;
+ vec4b = vec4a + vec4;
+ ensure("1:operator+:Fail to initialize " ,(is_approx_equal(x1+x2,vec4b.mV[VX]) && is_approx_equal(y1+y2,vec4b.mV[VY]) && is_approx_equal(z1+z2,vec4b.mV[VZ])));
+ x1 = -2.45f, y1 = 2.1f, z1 = 3.0f;
+ vec4.clearVec();
+ vec4a.clearVec();
+ vec4.setVec(x1,y1,z1);
+ vec4a +=vec4;
+ ensure_equals("2:operator+=: Fail to initialize", vec4a,vec4);
+ vec4a += vec4;
+ ensure("3:operator+=:Fail to initialize " ,(is_approx_equal(2*x1,vec4a.mV[VX]) && is_approx_equal(2*y1,vec4a.mV[VY]) && is_approx_equal(2*z1,vec4a.mV[VZ])));
+ }
+ template<> template<>
+ void v4math_object::test<11>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f, w1 = .23f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f, w2 = 1.3f;
+ LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2),vec4b;
+ vec4b = vec4a - vec4;
+ ensure("1:operator-:Fail to initialize " ,(is_approx_equal(x2-x1,vec4b.mV[VX]) && is_approx_equal(y2-y1,vec4b.mV[VY]) && is_approx_equal(z2-z1,vec4b.mV[VZ])));
+ x1 = -2.45f, y1 = 2.1f, z1 = 3.0f;
+ vec4.clearVec();
+ vec4a.clearVec();
+ vec4.setVec(x1,y1,z1);
+ vec4a -=vec4;
+ ensure_equals("2:operator-=: Fail to initialize" , vec4a,-vec4);
+ vec4a -=vec4;
+ ensure("3:operator-=:Fail to initialize " ,(is_approx_equal(-2*x1,vec4a.mV[VX]) && is_approx_equal(-2*y1,vec4a.mV[VY]) && is_approx_equal(-2*z1,vec4a.mV[VZ])));
+ }
+
+ template<> template<>
+ void v4math_object::test<12>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f;
+ LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2);
+ F32 res = vec4 * vec4a;
+ ensure("1:operator* failed " ,is_approx_equal(res, x1*x2 + y1*y2 + z1*z2));
+ vec4a.clearVec();
+ F32 mulVal = 4.2f;
+ vec4a = vec4 * mulVal;
+ ensure("2:operator* failed " ,is_approx_equal(x1*mulVal,vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ]));
+ vec4a.clearVec();
+ vec4a = mulVal * vec4 ;
+ ensure("3:operator* failed " ,is_approx_equal(x1*mulVal, vec4a.mV[VX]) && is_approx_equal(y1*mulVal, vec4a.mV[VY])&& is_approx_equal(z1*mulVal, vec4a.mV[VZ]));
+ vec4 *= mulVal;
+ ensure("4:operator*= failed " ,is_approx_equal(x1*mulVal, vec4.mV[VX]) && is_approx_equal(y1*mulVal, vec4.mV[VY])&& is_approx_equal(z1*mulVal, vec4.mV[VZ]));
+ }
+
+ template<> template<>
+ void v4math_object::test<13>()
+ {
+ F32 x1 = 1.f, y1 = 2.f, z1 = -1.1f;
+ F32 x2 = 1.2f, y2 = 2.5f, z2 = 1.f;
+ LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2),vec4b;
+ vec4b = vec4 % vec4a;
+ ensure("1:operator% failed " ,is_approx_equal(y1*z2 - y2*z1, vec4b.mV[VX]) && is_approx_equal(z1*x2 -z2*x1, vec4b.mV[VY]) && is_approx_equal(x1*y2-x2*y1, vec4b.mV[VZ]));
+ vec4 %= vec4a;
+ ensure_equals("operator%= failed " ,vec4,vec4b);
+ }
+
+ template<> template<>
+ void v4math_object::test<14>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f,div = 4.2f;
+ F32 t = 1.f / div;
+ LLVector4 vec4(x,y,z), vec4a;
+ vec4a = vec4/div;
+ ensure("1:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ]));
+ x = 1.23f, y = 4.f, z = -2.32f;
+ vec4.clearVec();
+ vec4a.clearVec();
+ vec4.setVec(x,y,z);
+ vec4a = vec4/div;
+ ensure("2:operator/ failed " ,is_approx_equal(x*t, vec4a.mV[VX]) && is_approx_equal(y*t, vec4a.mV[VY])&& is_approx_equal(z*t, vec4a.mV[VZ]));
+ vec4 /= div;
+ ensure("3:operator/ failed " ,is_approx_equal(x*t, vec4.mV[VX]) && is_approx_equal(y*t, vec4.mV[VY])&& is_approx_equal(z*t, vec4.mV[VZ]));
+ }
+
+ template<> template<>
+ void v4math_object::test<15>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z), vec4a;
+ ensure("operator!= failed " ,(vec4 != vec4a));
+ vec4a = vec4;
+ ensure("operator== failed " ,(vec4 ==vec4a));
+ }
+
+ template<> template<>
+ void v4math_object::test<16>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z), vec4a;
+ vec4a = - vec4;
+ ensure("operator- failed " , (vec4 == - vec4a));
+ }
+
+ template<> template<>
+ void v4math_object::test<17>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f,epsilon = .23425f;
+ LLVector4 vec4(x,y,z), vec4a(x,y,z);
+ ensure("1:are_parallel: Fail " ,(TRUE == are_parallel(vec4a,vec4,epsilon)));
+ x = 21.f, y = 12.f, z = -123.1f;
+ vec4a.clearVec();
+ vec4a.setVec(x,y,z);
+ ensure("2:are_parallel: Fail " ,(FALSE == are_parallel(vec4a,vec4,epsilon)));
+ }
+
+ template<> template<>
+ void v4math_object::test<18>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ F32 angle1, angle2;
+ LLVector4 vec4(x,y,z), vec4a(x,y,z);
+ angle1 = angle_between(vec4, vec4a);
+ vec4.normVec();
+ vec4a.normVec();
+ angle2 = acos(vec4 * vec4a);
+ ensure_approximately_equals("1:angle_between: Fail " ,angle1,angle2,8);
+ F32 x1 = 21.f, y1 = 2.23f, z1 = -1.1f;
+ LLVector4 vec4b(x,y,z), vec4c(x1,y1,z1);
+ angle1 = angle_between(vec4b, vec4c);
+ vec4b.normVec();
+ vec4c.normVec();
+ angle2 = acos(vec4b * vec4c);
+ ensure_approximately_equals("2:angle_between: Fail " ,angle1,angle2,8);
+ }
+
+ template<> template<>
+ void v4math_object::test<19>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f;
+ F32 val1,val2;
+ LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2);
+ val1 = dist_vec(vec4,vec4a);
+ val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("dist_vec: Fail ",val2, val1);
+ val1 = dist_vec_squared(vec4,vec4a);
+ val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2));
+ ensure_equals("dist_vec_squared: Fail ",val2, val1);
+ }
+
+ template<> template<>
+ void v4math_object::test<20>()
+ {
+ F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, w1 = -.23f, x2 = 1.3f, y2 = 1.f, z2 = 1.f,w2 = .12f;
+ F32 val = 2.3f,val1,val2,val3,val4;
+ LLVector4 vec4(x1,y1,z1,w1),vec4a(x2,y2,z2,w2);
+ val1 = x1 + (x2 - x1)* val;
+ val2 = y1 + (y2 - y1)* val;
+ val3 = z1 + (z2 - z1)* val;
+ val4 = w1 + (w2 - w1)* val;
+ LLVector4 vec4b = lerp(vec4,vec4a,val);
+ ensure("lerp failed", ((val1 ==vec4b.mV[VX])&& (val2 ==vec4b.mV[VY]) && (val3 ==vec4b.mV[VZ])&& (val4 ==vec4b.mV[VW])));
+ }
+
+ template<> template<>
+ void v4math_object::test<21>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z);
+ LLVector3 vec3 = vec4to3(vec4);
+ ensure("vec4to3 failed", ((x == vec3.mV[VX])&& (y == vec3.mV[VY]) && (z == vec3.mV[VZ])));
+ LLVector4 vec4a = vec3to4(vec3);
+ ensure_equals("vec3to4 failed",vec4a,vec4);
+ }
+
+ template<> template<>
+ void v4math_object::test<22>()
+ {
+ F32 x = 1.f, y = 2.f, z = -1.1f;
+ LLVector4 vec4(x,y,z);
+ LLSD llsd = vec4.getValue();
+ LLVector3 vec3(llsd);
+ LLVector4 vec4a = vec3to4(vec3);
+ ensure_equals("getValue failed",vec4a,vec4);
+ }
+}
diff --git a/indra/llmath/tests/xform_test.cpp b/indra/llmath/tests/xform_test.cpp
new file mode 100644
index 0000000000..49870eef3c
--- /dev/null
+++ b/indra/llmath/tests/xform_test.cpp
@@ -0,0 +1,245 @@
+/**
+ * @file xform_test.cpp
+ * @author Adroit
+ * @date March 2007
+ * @brief Test cases for LLXform
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "../test/lltut.h"
+
+#include "../xform.h"
+
+namespace tut
+{
+ struct xform_test
+ {
+ };
+ typedef test_group<xform_test> xform_test_t;
+ typedef xform_test_t::object xform_test_object_t;
+ tut::xform_test_t tut_xform_test("LLXForm");
+
+ //test case for init(), getParent(), getRotation(), getPositionW(), getWorldRotation() fns.
+ template<> template<>
+ void xform_test_object_t::test<1>()
+ {
+ LLXform xform_obj;
+ LLVector3 emptyVec(0.f,0.f,0.f);
+ LLVector3 initialScaleVec(1.f,1.f,1.f);
+
+ ensure("LLXform empty constructor failed: ", !xform_obj.getParent() && !xform_obj.isChanged() &&
+ xform_obj.getPosition() == emptyVec &&
+ (xform_obj.getRotation()).isIdentity() &&
+ xform_obj.getScale() == initialScaleVec &&
+ xform_obj.getPositionW() == emptyVec &&
+ (xform_obj.getWorldRotation()).isIdentity() &&
+ !xform_obj.getScaleChildOffset());
+ }
+
+ // test cases for
+ // setScale(const LLVector3& scale)
+ // setScale(const F32 x, const F32 y, const F32 z)
+ // setRotation(const F32 x, const F32 y, const F32 z)
+ // setPosition(const F32 x, const F32 y, const F32 z)
+ // getLocalMat4(LLMatrix4 &mat)
+ template<> template<>
+ void xform_test_object_t::test<2>()
+ {
+ LLMatrix4 llmat4;
+ LLXform xform_obj;
+
+ F32 x = 3.6f;
+ F32 y = 5.5f;
+ F32 z = 4.2f;
+ F32 w = 0.f;
+ F32 posz = z + 2.122f;
+ LLVector3 vec(x, y, z);
+ xform_obj.setScale(x, y, z);
+ xform_obj.setPosition(x, y, posz);
+ ensure("setScale failed: ", xform_obj.getScale() == vec);
+
+ vec.setVec(x, y, posz);
+ ensure("getPosition failed: ", xform_obj.getPosition() == vec);
+
+ x = x * 2.f;
+ y = y + 2.3f;
+ z = posz * 4.f;
+ vec.setVec(x, y, z);
+ xform_obj.setPositionX(x);
+ xform_obj.setPositionY(y);
+ xform_obj.setPositionZ(z);
+ ensure("setPositionX/Y/Z failed: ", xform_obj.getPosition() == vec);
+
+ xform_obj.setScaleChildOffset(TRUE);
+ ensure("setScaleChildOffset failed: ", xform_obj.getScaleChildOffset());
+
+ vec.setVec(x, y, z);
+
+ xform_obj.addPosition(vec);
+ vec += vec;
+ ensure("addPosition failed: ", xform_obj.getPosition() == vec);
+
+ xform_obj.setScale(vec);
+ ensure("setScale vector failed: ", xform_obj.getScale() == vec);
+
+ LLQuaternion quat(x, y, z, w);
+ xform_obj.setRotation(quat);
+ ensure("setRotation quat failed: ", xform_obj.getRotation() == quat);
+
+ xform_obj.setRotation(x, y, z, w);
+ ensure("getRotation 2 failed: ", xform_obj.getRotation() == quat);
+
+ xform_obj.setRotation(x, y, z);
+ quat.setQuat(x,y,z);
+ ensure("setRotation xyz failed: ", xform_obj.getRotation() == quat);
+
+ // LLXform::setRotation(const F32 x, const F32 y, const F32 z)
+ // Does normalization
+ // LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
+ // Simply copies the individual values - does not do any normalization.
+ // Is that the expected behavior?
+ }
+
+ // test cases for inline BOOL setParent(LLXform *parent) and getParent() fn.
+ template<> template<>
+ void xform_test_object_t::test<3>()
+ {
+ LLXform xform_obj;
+ LLXform par;
+ LLXform grandpar;
+ xform_obj.setParent(&par);
+ par.setParent(&grandpar);
+ ensure("setParent/getParent failed: ", &par == xform_obj.getParent());
+ ensure("getRoot failed: ", &grandpar == xform_obj.getRoot());
+ ensure("isRoot failed: ", grandpar.isRoot() && !par.isRoot() && !xform_obj.isRoot());
+ ensure("isRootEdit failed: ", grandpar.isRootEdit() && !par.isRootEdit() && !xform_obj.isRootEdit());
+ }
+
+ template<> template<>
+ void xform_test_object_t::test<4>()
+ {
+ LLXform xform_obj;
+ xform_obj.setChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED);
+ ensure("setChanged/isChanged failed: ", xform_obj.isChanged());
+
+ xform_obj.clearChanged(LLXform::TRANSLATED | LLXform::ROTATED | LLXform::SCALED);
+ ensure("clearChanged failed: ", !xform_obj.isChanged());
+
+ LLVector3 llvect3(12.4f, -5.6f, 0.34f);
+ xform_obj.setScale(llvect3);
+ ensure("setScale did not set SCALED flag: ", xform_obj.isChanged(LLXform::SCALED));
+ xform_obj.setPosition(1.2f, 2.3f, 3.4f);
+ ensure("setScale did not set TRANSLATED flag: ", xform_obj.isChanged(LLXform::TRANSLATED));
+ ensure("TRANSLATED reset SCALED flag: ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::SCALED));
+ xform_obj.clearChanged(LLXform::SCALED);
+ ensure("reset SCALED failed: ", !xform_obj.isChanged(LLXform::SCALED));
+ xform_obj.setRotation(1, 2, 3, 4);
+ ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::TRANSLATED | LLXform::ROTATED));
+ xform_obj.setScale(llvect3);
+ ensure("ROTATION flag not set ", xform_obj.isChanged(LLXform::MOVED));
+ }
+
+ //to test init() and getWorldMatrix() fns.
+ template<> template<>
+ void xform_test_object_t::test<5>()
+ {
+ LLXformMatrix formMatrix_obj;
+ formMatrix_obj.init();
+ LLMatrix4 mat4_obj;
+
+ ensure("1. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[0][0]);
+ ensure("2. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][1]);
+ ensure("3. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][2]);
+ ensure("4. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[0][3]);
+ ensure("5. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][0]);
+ ensure("6. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[1][1]);
+ ensure("7. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][2]);
+ ensure("8. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[1][3]);
+ ensure("9. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][0]);
+ ensure("10. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][1]);
+ ensure("11. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[2][2]);
+ ensure("12. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[2][3]);
+ ensure("13. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][0]);
+ ensure("14. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][1]);
+ ensure("15. The value is not NULL", 0.f == formMatrix_obj.getWorldMatrix().mMatrix[3][2]);
+ ensure("16. The value is not NULL", 1.f == formMatrix_obj.getWorldMatrix().mMatrix[3][3]);
+ }
+
+ //to test mMin.clearVec() and mMax.clearVec() fns
+ template<> template<>
+ void xform_test_object_t::test<6>()
+ {
+ LLXformMatrix formMatrix_obj;
+ formMatrix_obj.init();
+ LLVector3 llmin_vec3;
+ LLVector3 llmax_vec3;
+ formMatrix_obj.getMinMax(llmin_vec3, llmax_vec3);
+ ensure("1. The value is not NULL", 0.f == llmin_vec3.mV[0]);
+ ensure("2. The value is not NULL", 0.f == llmin_vec3.mV[1]);
+ ensure("3. The value is not NULL", 0.f == llmin_vec3.mV[2]);
+ ensure("4. The value is not NULL", 0.f == llmin_vec3.mV[0]);
+ ensure("5. The value is not NULL", 0.f == llmin_vec3.mV[1]);
+ ensure("6. The value is not NULL", 0.f == llmin_vec3.mV[2]);
+ }
+
+ //test case of update() fn.
+ template<> template<>
+ void xform_test_object_t::test<7>()
+ {
+ LLXformMatrix formMatrix_obj;
+
+ LLXformMatrix parent;
+ LLVector3 llvecpos(1.0, 2.0, 3.0);
+ LLVector3 llvecpospar(10.0, 20.0, 30.0);
+ formMatrix_obj.setPosition(llvecpos);
+ parent.setPosition(llvecpospar);
+
+ LLVector3 llvecparentscale(1.0, 2.0, 0);
+ parent.setScaleChildOffset(TRUE);
+ parent.setScale(llvecparentscale);
+
+ LLQuaternion quat(1, 2, 3, 4);
+ LLQuaternion quatparent(5, 6, 7, 8);
+ formMatrix_obj.setRotation(quat);
+ parent.setRotation(quatparent);
+ formMatrix_obj.setParent(&parent);
+
+ parent.update();
+ formMatrix_obj.update();
+
+ LLVector3 worldPos = llvecpos;
+ worldPos.scaleVec(llvecparentscale);
+ worldPos *= quatparent;
+ worldPos += llvecpospar;
+
+ LLQuaternion worldRot = quat * quatparent;
+
+ ensure("getWorldPosition failed: ", formMatrix_obj.getWorldPosition() == worldPos);
+ ensure("getWorldRotation failed: ", formMatrix_obj.getWorldRotation() == worldRot);
+
+ ensure("getWorldPosition for parent failed: ", parent.getWorldPosition() == llvecpospar);
+ ensure("getWorldRotation for parent failed: ", parent.getWorldRotation() == quatparent);
+ }
+}
+
diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp
index 7033048575..0180049b5d 100644
--- a/indra/llmath/v2math.cpp
+++ b/indra/llmath/v2math.cpp
@@ -2,30 +2,25 @@
* @file v2math.cpp
* @brief LLVector2 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,6 +28,7 @@
//#include "vmath.h"
#include "v2math.h"
+#include "v3math.h"
#include "v4math.h"
#include "m4math.h"
#include "m3math.h"
diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h
index 5f46655a07..f50a5e6633 100644
--- a/indra/llmath/v2math.h
+++ b/indra/llmath/v2math.h
@@ -2,30 +2,25 @@
* @file v2math.h
* @brief LLVector2 class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,6 +28,7 @@
#define LL_V2MATH_H
#include "llmath.h"
+#include "v3math.h"
class LLVector4;
class LLMatrix3;
@@ -49,9 +45,10 @@ class LLVector2
static LLVector2 zero;
- LLVector2(); // Initializes LLVector2 to (0, 0)
- LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y)
- LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1])
+ LLVector2(); // Initializes LLVector2 to (0, 0)
+ LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y)
+ LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1])
+ explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1])
// Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec.
void clear();
@@ -67,6 +64,8 @@ class LLVector2
void setVec(const LLVector2 &vec); // deprecated
void setVec(const F32 *vec); // deprecated
+ inline bool isFinite() const; // checks to see if all values of LLVector2 are finite
+
F32 length() const; // Returns magnitude of LLVector2
F32 lengthSquared() const; // Returns magnitude squared of LLVector2
F32 normalize(); // Normalizes and returns the magnitude of LLVector2
@@ -113,8 +112,8 @@ class LLVector2
F32 angle_between(const LLVector2 &a, const LLVector2 &b); // Returns angle (radians) between a and b
BOOL are_parallel(const LLVector2 &a, const LLVector2 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns TRUE if a and b are very close to parallel
F32 dist_vec(const LLVector2 &a, const LLVector2 &b); // Returns distance between a and b
-F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance sqaured between a and b
-F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance sqaured between a and b ignoring Z component
+F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b
+F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b ignoring Z component
LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u); // Returns a vector that is a linear interpolation between a and b
// Constructors
@@ -137,6 +136,12 @@ inline LLVector2::LLVector2(const F32 *vec)
mV[VY] = vec[VY];
}
+inline LLVector2::LLVector2(const LLVector3 &vec)
+{
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+}
+
// Clear and Assignment Functions
@@ -206,6 +211,7 @@ inline void LLVector2::setVec(const F32 *vec)
mV[VY] = vec[VY];
}
+
// LLVector2 Magnitude and Normalization Functions
inline F32 LLVector2::length(void) const
@@ -238,6 +244,12 @@ inline F32 LLVector2::normalize(void)
return (mag);
}
+// checker
+inline bool LLVector2::isFinite() const
+{
+ return (llfinite(mV[VX]) && llfinite(mV[VY]));
+}
+
// deprecated
inline F32 LLVector2::magVec(void) const
{
diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp
index 8a49be5615..d38f48b11e 100644
--- a/indra/llmath/v3color.cpp
+++ b/indra/llmath/v3color.cpp
@@ -2,30 +2,25 @@
* @file v3color.cpp
* @brief LLColor3 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -55,9 +50,7 @@ LLColor3::LLColor3(const LLVector4 &a)
LLColor3::LLColor3(const LLSD &sd)
{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
+ setValue(sd);
}
const LLColor3& LLColor3::operator=(const LLColor4 &a)
@@ -74,6 +67,42 @@ std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
return s;
}
+static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+{
+ if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
+ if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
+ if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
+ if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
+ if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
+ return ( val1In );
+}
+
+void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+{
+ if ( sValIn < 0.00001f )
+ {
+ mV[VRED] = lValIn;
+ mV[VGREEN] = lValIn;
+ mV[VBLUE] = lValIn;
+ }
+ else
+ {
+ F32 interVal1;
+ F32 interVal2;
+
+ if ( lValIn < 0.5f )
+ interVal2 = lValIn * ( 1.0f + sValIn );
+ else
+ interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+
+ interVal1 = 2.0f * lValIn - interVal2;
+
+ mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
+ mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
+ mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ }
+}
+
void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
{
F32 var_R = mV[VRED];
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index e2a8274839..327e452bf7 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -2,30 +2,25 @@
* @file v3color.h
* @brief LLColor3 class header file.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -56,7 +51,7 @@ public:
LLColor3(); // Initializes LLColor3 to (0, 0, 0)
LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b)
LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2])
- LLColor3(char *color_string); // html format color ie "#FFDDEE"
+ LLColor3(const char *color_string); // html format color ie "#FFDDEE"
explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion
explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion
LLColor3(const LLSD& sd);
@@ -78,17 +73,28 @@ public:
mV[2] = (F32) sd[2].asReal();;
}
+ void setHSL(F32 hue, F32 saturation, F32 luminance);
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0)
- const LLColor3& setVec(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
- const LLColor3& setVec(const LLColor3 &vec); // Sets LLColor3 to vec
- const LLColor3& setVec(const F32 *vec); // Sets LLColor3 to vec
+
+ const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated
+ const LLColor3& setVec(const LLColor3 &vec); // deprecated
+ const LLColor3& setVec(const F32 *vec); // deprecated
+
+ const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
+ const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec
+ const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec
+
+ F32 magVec() const; // deprecated
+ F32 magVecSquared() const; // deprecated
+ F32 normVec(); // deprecated
+
+ F32 length() const; // Returns magnitude of LLColor3
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor3
+ F32 normalize(); // Normalizes and returns the magnitude of LLColor3
- F32 magVec() const; // Returns magnitude of LLColor3
- F32 magVecSquared() const; // Returns magnitude squared of LLColor3
- F32 normVec(); // Normalizes and returns the magnitude of LLColor3
F32 brightness() const; // Returns brightness of LLColor3
const LLColor3& operator=(const LLColor4 &a);
@@ -150,7 +156,7 @@ void LLColor3::clamp()
// Non-member functions
F32 distVec(const LLColor3 &a, const LLColor3 &b); // Returns distance between a and b
-F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance sqaured between a and b
+F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance squared between a and b
inline LLColor3::LLColor3(void)
{
@@ -178,7 +184,7 @@ inline LLColor3::LLColor3(const F32 *vec)
# pragma warning( disable : 4996 ) // strncpy teh sux0r
#endif
-inline LLColor3::LLColor3(char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF
+inline LLColor3::LLColor3(const char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF
{
if (strlen(color_string) < 6) /* Flawfinder: ignore */
{
@@ -188,7 +194,7 @@ inline LLColor3::LLColor3(char* color_string) // takes a string of format "RRGGB
return;
}
- static char tempstr[7]; /* Flawfinder: ignore */
+ char tempstr[7];
strncpy(tempstr,color_string,6); /* Flawfinder: ignore */
tempstr[6] = '\0';
mV[VZ] = (F32)strtol(&tempstr[4],NULL,16)/255.f;
@@ -214,6 +220,31 @@ inline const LLColor3& LLColor3::setToWhite(void)
return (*this);
}
+inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b)
+{
+ mV[0] = r;
+ mV[1] = g;
+ mV[2] = b;
+ return (*this);
+}
+
+inline const LLColor3& LLColor3::set(const LLColor3 &vec)
+{
+ mV[0] = vec.mV[0];
+ mV[1] = vec.mV[1];
+ mV[2] = vec.mV[2];
+ return (*this);
+}
+
+inline const LLColor3& LLColor3::set(const F32 *vec)
+{
+ mV[0] = vec[0];
+ mV[1] = vec[1];
+ mV[2] = vec[2];
+ return (*this);
+}
+
+// deprecated
inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b)
{
mV[0] = r;
@@ -222,6 +253,7 @@ inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b)
return (*this);
}
+// deprecated
inline const LLColor3& LLColor3::setVec(const LLColor3 &vec)
{
mV[0] = vec.mV[0];
@@ -230,6 +262,7 @@ inline const LLColor3& LLColor3::setVec(const LLColor3 &vec)
return (*this);
}
+// deprecated
inline const LLColor3& LLColor3::setVec(const F32 *vec)
{
mV[0] = vec[0];
@@ -243,16 +276,44 @@ inline F32 LLColor3::brightness(void) const
return (mV[0] + mV[1] + mV[2]) / 3.0f;
}
+inline F32 LLColor3::length(void) const
+{
+ return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+}
+
+inline F32 LLColor3::lengthSquared(void) const
+{
+ return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+}
+
+inline F32 LLColor3::normalize(void)
+{
+ F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ F32 oomag;
+
+ if (mag)
+ {
+ oomag = 1.f/mag;
+ mV[0] *= oomag;
+ mV[1] *= oomag;
+ mV[2] *= oomag;
+ }
+ return (mag);
+}
+
+// deprecated
inline F32 LLColor3::magVec(void) const
{
return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
}
+// deprecated
inline F32 LLColor3::magVecSquared(void) const
{
return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
}
+// deprecated
inline F32 LLColor3::normVec(void)
{
F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
diff --git a/indra/llmath/v3dmath.cpp b/indra/llmath/v3dmath.cpp
index efe1274cbe..a50cb3c6ca 100644
--- a/indra/llmath/v3dmath.cpp
+++ b/indra/llmath/v3dmath.cpp
@@ -2,30 +2,25 @@
* @file v3dmath.cpp
* @brief LLVector3d class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -132,15 +127,15 @@ const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
}
-BOOL LLVector3d::parseVector3d(const char* buf, LLVector3d* value)
+BOOL LLVector3d::parseVector3d(const std::string& buf, LLVector3d* value)
{
- if( buf == NULL || buf[0] == '\0' || value == NULL)
+ if( buf.empty() || value == NULL)
{
return FALSE;
}
LLVector3d v;
- S32 count = sscanf( buf, "%lf %lf %lf", v.mdV + 0, v.mdV + 1, v.mdV + 2 );
+ S32 count = sscanf( buf.c_str(), "%lf %lf %lf", v.mdV + 0, v.mdV + 1, v.mdV + 2 );
if( 3 == count )
{
value->setVec( v );
diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h
index 667c335f51..664c986ad0 100644
--- a/indra/llmath/v3dmath.h
+++ b/indra/llmath/v3dmath.h
@@ -2,30 +2,25 @@
* @file v3dmath.h
* @brief High precision 3 dimensional vector.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -52,7 +47,7 @@ class LLVector3d
inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
inline explicit LLVector3d(const LLVector3 &vec);
- LLVector3d(const LLSD& sd)
+ explicit LLVector3d(const LLSD& sd)
{
setValue(sd);
}
@@ -64,12 +59,6 @@ class LLVector3d
mdV[2] = sd[2].asReal();
}
- const LLVector3d& operator=(const LLSD& sd)
- {
- setValue(sd);
- return *this;
- }
-
LLSD getValue() const
{
LLSD ret;
@@ -95,6 +84,10 @@ class LLVector3d
F64 magVecSquared() const; // Returns magnitude squared of LLVector3d
inline F64 normVec(); // Normalizes and returns the magnitude of LLVector3d
+ F64 length() const; // Returns magnitude of LLVector3d
+ F64 lengthSquared() const; // Returns magnitude squared of LLVector3d
+ inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d
+
const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians
const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians
const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
@@ -128,7 +121,7 @@ class LLVector3d
friend std::ostream& operator<<(std::ostream& s, const LLVector3d &a); // Stream a
- static BOOL parseVector3d(const char* buf, LLVector3d* value);
+ static BOOL parseVector3d(const std::string& buf, LLVector3d* value);
};
@@ -261,6 +254,28 @@ inline F64 LLVector3d::normVec(void)
return (mag);
}
+inline F64 LLVector3d::normalize(void)
+{
+ F64 mag = fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ F64 oomag;
+
+ if (mag > FP_MAG_THRESHOLD)
+ {
+ oomag = 1.f/mag;
+ mdV[0] *= oomag;
+ mdV[1] *= oomag;
+ mdV[2] *= oomag;
+ }
+ else
+ {
+ mdV[0] = 0.f;
+ mdV[1] = 0.f;
+ mdV[2] = 0.f;
+ mag = 0;
+ }
+ return (mag);
+}
+
// LLVector3d Magnitude and Normalization Functions
inline F64 LLVector3d::magVec(void) const
@@ -273,6 +288,16 @@ inline F64 LLVector3d::magVecSquared(void) const
return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2];
}
+inline F64 LLVector3d::length(void) const
+{
+ return fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+}
+
+inline F64 LLVector3d::lengthSquared(void) const
+{
+ return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2];
+}
+
inline LLVector3d operator+(const LLVector3d &a, const LLVector3d &b)
{
LLVector3d c(a);
@@ -416,8 +441,8 @@ inline F64 angle_between(const LLVector3d& a, const LLVector3d& b)
{
LLVector3d an = a;
LLVector3d bn = b;
- an.normVec();
- bn.normVec();
+ an.normalize();
+ bn.normalize();
F64 cosine = an * bn;
F64 angle = (cosine >= 1.0f) ? 0.0f :
(cosine <= -1.0f) ? F_PI :
@@ -429,8 +454,8 @@ inline BOOL are_parallel(const LLVector3d &a, const LLVector3d &b, const F64 eps
{
LLVector3d an = a;
LLVector3d bn = b;
- an.normVec();
- bn.normVec();
+ an.normalize();
+ bn.normalize();
F64 dot = an * bn;
if ( (1.0f - fabs(dot)) < epsilon)
{
@@ -443,7 +468,7 @@ inline BOOL are_parallel(const LLVector3d &a, const LLVector3d &b, const F64 eps
inline LLVector3d projected_vec(const LLVector3d &a, const LLVector3d &b)
{
LLVector3d project_axis = b;
- project_axis.normVec();
+ project_axis.normalize();
return project_axis * (a * project_axis);
}
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index f1fe1a780e..fd08df02d8 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -2,30 +2,25 @@
* @file v3math.cpp
* @brief LLVector3 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,6 +29,7 @@
#include "v3math.h"
//#include "vmath.h"
+#include "v2math.h"
#include "v4math.h"
#include "m4math.h"
#include "m3math.h"
@@ -73,6 +69,72 @@ BOOL LLVector3::clamp(F32 min, F32 max)
return ret;
}
+// Clamps length to an upper limit.
+// Returns TRUE if the data changed
+BOOL LLVector3::clampLength( F32 length_limit )
+{
+ BOOL changed = FALSE;
+
+ F32 len = length();
+ if (llfinite(len))
+ {
+ if ( len > length_limit)
+ {
+ normalize();
+ if (length_limit < 0.f)
+ {
+ length_limit = 0.f;
+ }
+ mV[0] *= length_limit;
+ mV[1] *= length_limit;
+ mV[2] *= length_limit;
+ changed = TRUE;
+ }
+ }
+ else
+ { // this vector may still be salvagable
+ F32 max_abs_component = 0.f;
+ for (S32 i = 0; i < 3; ++i)
+ {
+ F32 abs_component = fabs(mV[i]);
+ if (llfinite(abs_component))
+ {
+ if (abs_component > max_abs_component)
+ {
+ max_abs_component = abs_component;
+ }
+ }
+ else
+ {
+ // no it can't be salvaged --> clear it
+ clear();
+ changed = TRUE;
+ break;
+ }
+ }
+ if (!changed)
+ {
+ // yes it can be salvaged -->
+ // bring the components down before we normalize
+ mV[0] /= max_abs_component;
+ mV[1] /= max_abs_component;
+ mV[2] /= max_abs_component;
+ normalize();
+
+ if (length_limit < 0.f)
+ {
+ length_limit = 0.f;
+ }
+ mV[0] *= length_limit;
+ mV[1] *= length_limit;
+ mV[2] *= length_limit;
+ }
+ }
+
+ return changed;
+}
+
+
// Sets all values to absolute value of their original values
// Returns TRUE if data changed
BOOL LLVector3::abs()
@@ -117,14 +179,6 @@ void LLVector3::snap(S32 sig_digits)
mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
}
-
-std::ostream& operator<<(std::ostream& s, const LLVector3 &a)
-{
- s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
- return s;
-}
-
-
const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat)
{
*this = *this * mat;
@@ -204,6 +258,13 @@ const LLVector3& LLVector3::setVec(const LLVector4 &vec)
return (*this);
}
+LLVector3::LLVector3(const LLVector2 &vec)
+{
+ mV[VX] = (F32)vec.mV[VX];
+ mV[VY] = (F32)vec.mV[VY];
+ mV[VZ] = 0;
+}
+
LLVector3::LLVector3(const LLVector3d &vec)
{
mV[VX] = (F32)vec.mdV[VX];
@@ -239,12 +300,6 @@ void LLVector3::setValue(const LLSD& sd)
mV[2] = (F32) sd[2].asReal();
}
-const LLVector3& LLVector3::operator=(const LLSD& sd)
-{
- setValue(sd);
- return *this;
-}
-
const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
{
const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
@@ -260,15 +315,15 @@ const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
}
// static
-BOOL LLVector3::parseVector3(const char* buf, LLVector3* value)
+BOOL LLVector3::parseVector3(const std::string& buf, LLVector3* value)
{
- if( buf == NULL || buf[0] == '\0' || value == NULL)
+ if( buf.empty() || value == NULL)
{
return FALSE;
}
LLVector3 v;
- S32 count = sscanf( buf, "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 );
+ S32 count = sscanf( buf.c_str(), "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 );
if( 3 == count )
{
value->setVec( v );
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index 03c780a1f4..dbd38c1c3f 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -2,30 +2,25 @@
* @file v3math.h
* @brief LLVector3 class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,6 +31,7 @@
#include "llmath.h"
#include "llsd.h"
+class LLVector2;
class LLVector4;
class LLMatrix3;
class LLVector3d;
@@ -62,18 +58,18 @@ class LLVector3
inline LLVector3(); // Initializes LLVector3 to (0, 0, 0)
inline LLVector3(const F32 x, const F32 y, const F32 z); // Initializes LLVector3 to (x. y, z)
inline explicit LLVector3(const F32 *vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2])
+ explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0)
explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2])
explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2])
- LLVector3(const LLSD& sd);
+ explicit LLVector3(const LLSD& sd);
LLSD getValue() const;
void setValue(const LLSD& sd);
- const LLVector3& operator=(const LLSD& sd);
-
inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite
BOOL clamp(F32 min, F32 max); // Clamps all values to (min,max), returns TRUE if data changed
+ BOOL clampLength( F32 length_limit ); // Scales vector to limit length to a value
void quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization
void quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization
@@ -147,7 +143,7 @@ class LLVector3
friend std::ostream& operator<<(std::ostream& s, const LLVector3 &a); // Stream a
- static BOOL parseVector3(const char* buf, LLVector3* value);
+ static BOOL parseVector3(const std::string& buf, LLVector3* value);
};
typedef LLVector3 LLSimLocalVec;
@@ -157,8 +153,8 @@ typedef LLVector3 LLSimLocalVec;
F32 angle_between(const LLVector3 &a, const LLVector3 &b); // Returns angle (radians) between a and b
BOOL are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns TRUE if a and b are very close to parallel
F32 dist_vec(const LLVector3 &a, const LLVector3 &b); // Returns distance between a and b
-F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b);// Returns distance sqaured between a and b
-F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b);// Returns distance sqaured between a and b ignoring Z component
+F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b
+F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b ignoring Z component
LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b
LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vector that is a linear interpolation between a and b
@@ -407,8 +403,8 @@ inline bool operator<(const LLVector3 &a, const LLVector3 &b)
return (a.mV[0] < b.mV[0]
|| (a.mV[0] == b.mV[0]
&& (a.mV[1] < b.mV[1]
- || (a.mV[1] == b.mV[1])
- && a.mV[2] < b.mV[2])));
+ || ((a.mV[1] == b.mV[1])
+ && a.mV[2] < b.mV[2]))));
}
inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b)
@@ -554,4 +550,10 @@ inline BOOL are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
return FALSE;
}
+inline std::ostream& operator<<(std::ostream& s, const LLVector3 &a)
+{
+ s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
+ return s;
+}
+
#endif
diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp
index 21166472e4..81ac62be56 100644
--- a/indra/llmath/v4color.cpp
+++ b/indra/llmath/v4color.cpp
@@ -2,30 +2,25 @@
* @file v4color.cpp
* @brief LLColor4 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -161,6 +156,38 @@ LLColor4::LLColor4(const LLVector4& vector4)
mV[VW] = vector4.mV[VW];
}
+const LLColor4& LLColor4::set(const LLColor4U& color4u)
+{
+ const F32 SCALE = 1.f/255.f;
+ mV[VX] = color4u.mV[VX] * SCALE;
+ mV[VY] = color4u.mV[VY] * SCALE;
+ mV[VZ] = color4u.mV[VZ] * SCALE;
+ mV[VW] = color4u.mV[VW] * SCALE;
+ return (*this);
+}
+
+const LLColor4& LLColor4::set(const LLColor3 &vec)
+{
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
+
+// no change to alpha!
+// mV[VW] = 1.f;
+
+ return (*this);
+}
+
+const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a)
+{
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
+ mV[VW] = a;
+ return (*this);
+}
+
+// deprecated -- use set()
const LLColor4& LLColor4::setVec(const LLColor4U& color4u)
{
const F32 SCALE = 1.f/255.f;
@@ -171,6 +198,7 @@ const LLColor4& LLColor4::setVec(const LLColor4U& color4u)
return (*this);
}
+// deprecated -- use set()
const LLColor4& LLColor4::setVec(const LLColor3 &vec)
{
mV[VX] = vec.mV[VX];
@@ -183,6 +211,7 @@ const LLColor4& LLColor4::setVec(const LLColor3 &vec)
return (*this);
}
+// deprecated -- use set()
const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a)
{
mV[VX] = vec.mV[VX];
@@ -192,6 +221,40 @@ const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a)
return (*this);
}
+void LLColor4::setValue(const LLSD& sd)
+{
+#if 0
+ // Clamping on setValue from LLSD is inconsistent with other set behavior
+ F32 val;
+ bool out_of_range = false;
+ val = sd[0].asReal();
+ mV[0] = llclamp(val, 0.f, 1.f);
+ out_of_range = mV[0] != val;
+
+ val = sd[1].asReal();
+ mV[1] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[1] != val;
+
+ val = sd[2].asReal();
+ mV[2] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[2] != val;
+
+ val = sd[3].asReal();
+ mV[3] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[3] != val;
+
+ if (out_of_range)
+ {
+ llwarns << "LLSD color value out of range!" << llendl;
+ }
+#else
+ mV[0] = (F32) sd[0].asReal();
+ mV[1] = (F32) sd[1].asReal();
+ mV[2] = (F32) sd[2].asReal();
+ mV[3] = (F32) sd[3].asReal();
+#endif
+}
+
const LLColor4& LLColor4::operator=(const LLColor3 &a)
{
mV[VX] = a.mV[VX];
@@ -236,6 +299,42 @@ LLColor4 vec3to4(const LLColor3 &vec)
return temp;
}
+static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+{
+ if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
+ if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
+ if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
+ if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
+ if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
+ return ( val1In );
+}
+
+void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+{
+ if ( sValIn < 0.00001f )
+ {
+ mV[VRED] = lValIn;
+ mV[VGREEN] = lValIn;
+ mV[VBLUE] = lValIn;
+ }
+ else
+ {
+ F32 interVal1;
+ F32 interVal2;
+
+ if ( lValIn < 0.5f )
+ interVal2 = lValIn * ( 1.0f + sValIn );
+ else
+ interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+
+ interVal1 = 2.0f * lValIn - interVal2;
+
+ mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
+ mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
+ mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ }
+}
+
void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
{
F32 var_R = mV[VRED];
@@ -286,16 +385,14 @@ void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
}
// static
-BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
+BOOL LLColor4::parseColor(const std::string& buf, LLColor4* color)
{
- if( buf == NULL || buf[0] == '\0' || color == NULL)
+ if( buf.empty() || color == NULL)
{
return FALSE;
}
- LLString full_string(buf);
-
- boost_tokenizer tokens(full_string, boost::char_separator<char>(", "));
+ boost_tokenizer tokens(buf, boost::char_separator<char>(", "));
boost_tokenizer::iterator token_iter = tokens.begin();
if (token_iter == tokens.end())
{
@@ -304,15 +401,15 @@ BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
// Grab the first token into a string, since we don't know
// if this is a float or a color name.
- LLString color_name( (*token_iter) );
+ std::string color_name( (*token_iter) );
++token_iter;
if (token_iter != tokens.end())
{
// There are more tokens to read. This must be a vector.
LLColor4 v;
- LLString::convertToF32( color_name, v.mV[VX] );
- LLString::convertToF32( *token_iter, v.mV[VY] );
+ LLStringUtil::convertToF32( color_name, v.mV[VX] );
+ LLStringUtil::convertToF32( *token_iter, v.mV[VY] );
v.mV[VZ] = 0.0f;
v.mV[VW] = 1.0f;
@@ -320,18 +417,18 @@ BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
if (token_iter == tokens.end())
{
// This is a malformed vector.
- llwarns << "LLColor4::parseColor() malformed color " << full_string << llendl;
+ llwarns << "LLColor4::parseColor() malformed color " << buf << llendl;
}
else
{
// There is a z-component.
- LLString::convertToF32( *token_iter, v.mV[VZ] );
+ LLStringUtil::convertToF32( *token_iter, v.mV[VZ] );
++token_iter;
if (token_iter != tokens.end())
{
// There is an alpha component.
- LLString::convertToF32( *token_iter, v.mV[VW] );
+ LLStringUtil::convertToF32( *token_iter, v.mV[VW] );
}
}
@@ -340,270 +437,270 @@ BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
{
v = v * (1.f / 255.f);
}
- color->setVec( v );
+ color->set( v );
}
else // Single value. Read as a named color.
{
// We have a color name
if ( "red" == color_name )
{
- color->setVec(LLColor4::red);
+ color->set(LLColor4::red);
}
else if ( "red1" == color_name )
{
- color->setVec(LLColor4::red1);
+ color->set(LLColor4::red1);
}
else if ( "red2" == color_name )
{
- color->setVec(LLColor4::red2);
+ color->set(LLColor4::red2);
}
else if ( "red3" == color_name )
{
- color->setVec(LLColor4::red3);
+ color->set(LLColor4::red3);
}
else if ( "red4" == color_name )
{
- color->setVec(LLColor4::red4);
+ color->set(LLColor4::red4);
}
else if ( "red5" == color_name )
{
- color->setVec(LLColor4::red5);
+ color->set(LLColor4::red5);
}
else if( "green" == color_name )
{
- color->setVec(LLColor4::green);
+ color->set(LLColor4::green);
}
else if( "green1" == color_name )
{
- color->setVec(LLColor4::green1);
+ color->set(LLColor4::green1);
}
else if( "green2" == color_name )
{
- color->setVec(LLColor4::green2);
+ color->set(LLColor4::green2);
}
else if( "green3" == color_name )
{
- color->setVec(LLColor4::green3);
+ color->set(LLColor4::green3);
}
else if( "green4" == color_name )
{
- color->setVec(LLColor4::green4);
+ color->set(LLColor4::green4);
}
else if( "green5" == color_name )
{
- color->setVec(LLColor4::green5);
+ color->set(LLColor4::green5);
}
else if( "green6" == color_name )
{
- color->setVec(LLColor4::green6);
+ color->set(LLColor4::green6);
}
else if( "blue" == color_name )
{
- color->setVec(LLColor4::blue);
+ color->set(LLColor4::blue);
}
else if( "blue1" == color_name )
{
- color->setVec(LLColor4::blue1);
+ color->set(LLColor4::blue1);
}
else if( "blue2" == color_name )
{
- color->setVec(LLColor4::blue2);
+ color->set(LLColor4::blue2);
}
else if( "blue3" == color_name )
{
- color->setVec(LLColor4::blue3);
+ color->set(LLColor4::blue3);
}
else if( "blue4" == color_name )
{
- color->setVec(LLColor4::blue4);
+ color->set(LLColor4::blue4);
}
else if( "blue5" == color_name )
{
- color->setVec(LLColor4::blue5);
+ color->set(LLColor4::blue5);
}
else if( "blue6" == color_name )
{
- color->setVec(LLColor4::blue6);
+ color->set(LLColor4::blue6);
}
else if( "black" == color_name )
{
- color->setVec(LLColor4::black);
+ color->set(LLColor4::black);
}
else if( "white" == color_name )
{
- color->setVec(LLColor4::white);
+ color->set(LLColor4::white);
}
else if( "yellow" == color_name )
{
- color->setVec(LLColor4::yellow);
+ color->set(LLColor4::yellow);
}
else if( "yellow1" == color_name )
{
- color->setVec(LLColor4::yellow1);
+ color->set(LLColor4::yellow1);
}
else if( "yellow2" == color_name )
{
- color->setVec(LLColor4::yellow2);
+ color->set(LLColor4::yellow2);
}
else if( "yellow3" == color_name )
{
- color->setVec(LLColor4::yellow3);
+ color->set(LLColor4::yellow3);
}
else if( "yellow4" == color_name )
{
- color->setVec(LLColor4::yellow4);
+ color->set(LLColor4::yellow4);
}
else if( "yellow5" == color_name )
{
- color->setVec(LLColor4::yellow5);
+ color->set(LLColor4::yellow5);
}
else if( "yellow6" == color_name )
{
- color->setVec(LLColor4::yellow6);
+ color->set(LLColor4::yellow6);
}
else if( "magenta" == color_name )
{
- color->setVec(LLColor4::magenta);
+ color->set(LLColor4::magenta);
}
else if( "magenta1" == color_name )
{
- color->setVec(LLColor4::magenta1);
+ color->set(LLColor4::magenta1);
}
else if( "magenta2" == color_name )
{
- color->setVec(LLColor4::magenta2);
+ color->set(LLColor4::magenta2);
}
else if( "magenta3" == color_name )
{
- color->setVec(LLColor4::magenta3);
+ color->set(LLColor4::magenta3);
}
else if( "magenta4" == color_name )
{
- color->setVec(LLColor4::magenta4);
+ color->set(LLColor4::magenta4);
}
else if( "purple" == color_name )
{
- color->setVec(LLColor4::purple);
+ color->set(LLColor4::purple);
}
else if( "purple1" == color_name )
{
- color->setVec(LLColor4::purple1);
+ color->set(LLColor4::purple1);
}
else if( "purple2" == color_name )
{
- color->setVec(LLColor4::purple2);
+ color->set(LLColor4::purple2);
}
else if( "purple3" == color_name )
{
- color->setVec(LLColor4::purple3);
+ color->set(LLColor4::purple3);
}
else if( "purple4" == color_name )
{
- color->setVec(LLColor4::purple4);
+ color->set(LLColor4::purple4);
}
else if( "purple5" == color_name )
{
- color->setVec(LLColor4::purple5);
+ color->set(LLColor4::purple5);
}
else if( "purple6" == color_name )
{
- color->setVec(LLColor4::purple6);
+ color->set(LLColor4::purple6);
}
else if( "pink" == color_name )
{
- color->setVec(LLColor4::pink);
+ color->set(LLColor4::pink);
}
else if( "pink1" == color_name )
{
- color->setVec(LLColor4::pink1);
+ color->set(LLColor4::pink1);
}
else if( "pink2" == color_name )
{
- color->setVec(LLColor4::pink2);
+ color->set(LLColor4::pink2);
}
else if( "cyan" == color_name )
{
- color->setVec(LLColor4::cyan);
+ color->set(LLColor4::cyan);
}
else if( "cyan1" == color_name )
{
- color->setVec(LLColor4::cyan1);
+ color->set(LLColor4::cyan1);
}
else if( "cyan2" == color_name )
{
- color->setVec(LLColor4::cyan2);
+ color->set(LLColor4::cyan2);
}
else if( "cyan3" == color_name )
{
- color->setVec(LLColor4::cyan3);
+ color->set(LLColor4::cyan3);
}
else if( "cyan4" == color_name )
{
- color->setVec(LLColor4::cyan4);
+ color->set(LLColor4::cyan4);
}
else if( "cyan5" == color_name )
{
- color->setVec(LLColor4::cyan5);
+ color->set(LLColor4::cyan5);
}
else if( "cyan6" == color_name )
{
- color->setVec(LLColor4::cyan6);
+ color->set(LLColor4::cyan6);
}
else if( "smoke" == color_name )
{
- color->setVec(LLColor4::smoke);
+ color->set(LLColor4::smoke);
}
else if( "grey" == color_name )
{
- color->setVec(LLColor4::grey);
+ color->set(LLColor4::grey);
}
else if( "grey1" == color_name )
{
- color->setVec(LLColor4::grey1);
+ color->set(LLColor4::grey1);
}
else if( "grey2" == color_name )
{
- color->setVec(LLColor4::grey2);
+ color->set(LLColor4::grey2);
}
else if( "grey3" == color_name )
{
- color->setVec(LLColor4::grey3);
+ color->set(LLColor4::grey3);
}
else if( "grey4" == color_name )
{
- color->setVec(LLColor4::grey4);
+ color->set(LLColor4::grey4);
}
else if( "orange" == color_name )
{
- color->setVec(LLColor4::orange);
+ color->set(LLColor4::orange);
}
else if( "orange1" == color_name )
{
- color->setVec(LLColor4::orange1);
+ color->set(LLColor4::orange1);
}
else if( "orange2" == color_name )
{
- color->setVec(LLColor4::orange2);
+ color->set(LLColor4::orange2);
}
else if( "orange3" == color_name )
{
- color->setVec(LLColor4::orange3);
+ color->set(LLColor4::orange3);
}
else if( "orange4" == color_name )
{
- color->setVec(LLColor4::orange4);
+ color->set(LLColor4::orange4);
}
else if( "orange5" == color_name )
{
- color->setVec(LLColor4::orange5);
+ color->set(LLColor4::orange5);
}
else if( "orange6" == color_name )
{
- color->setVec(LLColor4::orange6);
+ color->set(LLColor4::orange6);
}
else if ( "clear" == color_name )
{
- color->setVec(0.f, 0.f, 0.f, 0.f);
+ color->set(0.f, 0.f, 0.f, 0.f);
}
else
{
@@ -615,19 +712,19 @@ BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
}
// static
-BOOL LLColor4::parseColor4(const char* buf, LLColor4* value)
+BOOL LLColor4::parseColor4(const std::string& buf, LLColor4* value)
{
- if( buf == NULL || buf[0] == '\0' || value == NULL)
+ if( buf.empty() || value == NULL)
{
return FALSE;
}
LLColor4 v;
- S32 count = sscanf( buf, "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
+ S32 count = sscanf( buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
if (1 == count )
{
// try this format
- count = sscanf( buf, "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
+ count = sscanf( buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
}
if( 4 == count )
{
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index bd990444b5..60d24e2e11 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -2,30 +2,25 @@
* @file v4color.h
* @brief LLColor4 class header file.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -57,7 +52,7 @@ class LLColor4
LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
- LLColor4(const LLSD& sd);
+ explicit LLColor4(const LLSD& sd);
explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
@@ -71,40 +66,47 @@ class LLColor4
return ret;
}
- void setValue(const LLSD& sd)
- {
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
- mV[3] = (F32) sd[3].asReal();
- }
+ void setValue(const LLSD& sd);
+ void setHSL(F32 hue, F32 saturation, F32 luminance);
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1)
- const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a)
- const LLColor4& setVec(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a)
- const LLColor4& setVec(const LLColor4 &vec); // Sets LLColor4 to vec
- const LLColor4& setVec(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
- const LLColor4& setVec(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
- const LLColor4& setVec(const F32 *vec); // Sets LLColor4 to vec
- const LLColor4& setVec(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set()
+ const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor4 &vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor3 &vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor3 &vec, F32 a); // deprecated -- use set()
+ const LLColor4& setVec(const F32 *vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set()
+
+ const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a)
+ const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a)
+ const LLColor4& set(const LLColor4 &vec); // Sets LLColor4 to vec
+ const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
+ const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
+ const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec
+ const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
const LLColor4& setAlpha(F32 a);
- F32 magVec() const; // Returns magnitude of LLColor4
- F32 magVecSquared() const; // Returns magnitude squared of LLColor4
- F32 normVec(); // Normalizes and returns the magnitude of LLColor4
+ F32 magVec() const; // deprecated -- use length()
+ F32 magVecSquared() const; // deprecated -- use lengthSquared()
+ F32 normVec(); // deprecated -- use normalize()
+
+ F32 length() const; // Returns magnitude of LLColor4
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor4
+ F32 normalize(); // deprecated -- use normalize()
+
BOOL isOpaque() { return mV[VALPHA] == 1.f; }
F32 operator[](int idx) const { return mV[idx]; }
F32 &operator[](int idx) { return mV[idx]; }
const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4
- const LLColor4& operator=(const LLSD& sd);
friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
@@ -211,8 +213,8 @@ class LLColor4
static LLColor4 cyan5;
static LLColor4 cyan6;
- static BOOL parseColor(const char* buf, LLColor4* color);
- static BOOL parseColor4(const char* buf, LLColor4* color);
+ static BOOL parseColor(const std::string& buf, LLColor4* color);
+ static BOOL parseColor4(const std::string& buf, LLColor4* color);
inline void clamp();
};
@@ -235,7 +237,7 @@ inline LLColor4::LLColor4(void)
inline LLColor4::LLColor4(const LLSD& sd)
{
- *this = sd;
+ this->setValue(sd);
}
inline LLColor4::LLColor4(F32 r, F32 g, F32 b)
@@ -289,6 +291,47 @@ inline const LLColor4& LLColor4::setToWhite(void)
return (*this);
}
+inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z)
+{
+ mV[VX] = x;
+ mV[VY] = y;
+ mV[VZ] = z;
+
+// no change to alpha!
+// mV[VW] = 1.f;
+
+ return (*this);
+}
+
+inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a)
+{
+ mV[VX] = x;
+ mV[VY] = y;
+ mV[VZ] = z;
+ mV[VW] = a;
+ return (*this);
+}
+
+inline const LLColor4& LLColor4::set(const LLColor4 &vec)
+{
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
+ mV[VW] = vec.mV[VW];
+ return (*this);
+}
+
+
+inline const LLColor4& LLColor4::set(const F32 *vec)
+{
+ mV[VX] = vec[VX];
+ mV[VY] = vec[VY];
+ mV[VZ] = vec[VZ];
+ mV[VW] = vec[VW];
+ return (*this);
+}
+
+// deprecated
inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
{
mV[VX] = x;
@@ -301,6 +344,7 @@ inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
return (*this);
}
+// deprecated
inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z, F32 a)
{
mV[VX] = x;
@@ -310,6 +354,7 @@ inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z, F32 a)
return (*this);
}
+// deprecated
inline const LLColor4& LLColor4::setVec(const LLColor4 &vec)
{
mV[VX] = vec.mV[VX];
@@ -320,6 +365,7 @@ inline const LLColor4& LLColor4::setVec(const LLColor4 &vec)
}
+// deprecated
inline const LLColor4& LLColor4::setVec(const F32 *vec)
{
mV[VX] = vec[VX];
@@ -337,16 +383,44 @@ inline const LLColor4& LLColor4::setAlpha(F32 a)
// LLColor4 Magnitude and Normalization Functions
+inline F32 LLColor4::length(void) const
+{
+ return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
+}
+
+inline F32 LLColor4::lengthSquared(void) const
+{
+ return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
+}
+
+inline F32 LLColor4::normalize(void)
+{
+ F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
+ F32 oomag;
+
+ if (mag)
+ {
+ oomag = 1.f/mag;
+ mV[VX] *= oomag;
+ mV[VY] *= oomag;
+ mV[VZ] *= oomag;
+ }
+ return (mag);
+}
+
+// deprecated
inline F32 LLColor4::magVec(void) const
{
return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
}
+// deprecated
inline F32 LLColor4::magVecSquared(void) const
{
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
+// deprecated
inline F32 LLColor4::normVec(void)
{
F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
@@ -497,13 +571,13 @@ inline const LLColor4& operator%=(LLColor4 &a, F32 k)
inline F32 distVec(const LLColor4 &a, const LLColor4 &b)
{
LLColor4 vec = a - b;
- return (vec.magVec());
+ return (vec.length());
}
inline F32 distVec_squared(const LLColor4 &a, const LLColor4 &b)
{
LLColor4 vec = a - b;
- return (vec.magVecSquared());
+ return (vec.lengthSquared());
}
inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u)
@@ -553,15 +627,5 @@ void LLColor4::clamp()
}
}
-inline const LLColor4& LLColor4::operator=(const LLSD& sd)
-{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
- mV[3] = (F32) sd[3].asReal();
-
- return *this;
-}
-
#endif
diff --git a/indra/llmath/v4coloru.cpp b/indra/llmath/v4coloru.cpp
index 6f6900b6c2..f1a2518cf3 100644
--- a/indra/llmath/v4coloru.cpp
+++ b/indra/llmath/v4coloru.cpp
@@ -2,30 +2,25 @@
* @file v4coloru.cpp
* @brief LLColor4U class implementation.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -93,19 +88,19 @@ std::ostream& operator<<(std::ostream& s, const LLColor4U &a)
}
// static
-BOOL LLColor4U::parseColor4U(const char* buf, LLColor4U* value)
+BOOL LLColor4U::parseColor4U(const std::string& buf, LLColor4U* value)
{
- if( buf == NULL || buf[0] == '\0' || value == NULL)
+ if( buf.empty() || value == NULL)
{
return FALSE;
}
U32 v[4];
- S32 count = sscanf( buf, "%u, %u, %u, %u", v + 0, v + 1, v + 2, v + 3 );
+ S32 count = sscanf( buf.c_str(), "%u, %u, %u, %u", v + 0, v + 1, v + 2, v + 3 );
if (1 == count )
{
// try this format
- count = sscanf( buf, "%u %u %u %u", v + 0, v + 1, v + 2, v + 3 );
+ count = sscanf( buf.c_str(), "%u %u %u %u", v + 0, v + 1, v + 2, v + 3 );
}
if( 4 != count )
{
@@ -120,6 +115,6 @@ BOOL LLColor4U::parseColor4U(const char* buf, LLColor4U* value)
}
}
- value->setVec( U8(v[0]), U8(v[1]), U8(v[2]), U8(v[3]) );
+ value->set( U8(v[0]), U8(v[1]), U8(v[2]), U8(v[3]) );
return TRUE;
}
diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h
index fc7845ad15..7471aebe02 100644
--- a/indra/llmath/v4coloru.h
+++ b/indra/llmath/v4coloru.h
@@ -2,30 +2,25 @@
* @file v4coloru.h
* @brief The LLColor4U class.
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -65,7 +60,7 @@ public:
LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1)
LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a)
LLColor4U(const U8 *vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1)
- LLColor4U(const LLSD& sd)
+ explicit LLColor4U(const LLSD& sd)
{
setValue(sd);
}
@@ -78,12 +73,6 @@ public:
mV[3] = sd[3].asInteger();
}
- const LLColor4U& operator=(const LLSD& sd)
- {
- setValue(sd);
- return *this;
- }
-
LLSD getValue() const
{
LLSD ret;
@@ -97,15 +86,23 @@ public:
const LLColor4U& setToBlack(); // zero LLColor4U to (0, 0, 0, 1)
const LLColor4U& setToWhite(); // zero LLColor4U to (0, 0, 0, 1)
- const LLColor4U& setVec(U8 r, U8 g, U8 b, U8 a); // Sets LLColor4U to (r, g, b, a)
- const LLColor4U& setVec(U8 r, U8 g, U8 b); // Sets LLColor4U to (r, g, b) (no change in a)
- const LLColor4U& setVec(const LLColor4U &vec); // Sets LLColor4U to vec
- const LLColor4U& setVec(const U8 *vec); // Sets LLColor4U to vec
+ const LLColor4U& set(U8 r, U8 g, U8 b, U8 a);// Sets LLColor4U to (r, g, b, a)
+ const LLColor4U& set(U8 r, U8 g, U8 b); // Sets LLColor4U to (r, g, b) (no change in a)
+ const LLColor4U& set(const LLColor4U &vec); // Sets LLColor4U to vec
+ const LLColor4U& set(const U8 *vec); // Sets LLColor4U to vec
+
+ const LLColor4U& setVec(U8 r, U8 g, U8 b, U8 a); // deprecated -- use set()
+ const LLColor4U& setVec(U8 r, U8 g, U8 b); // deprecated -- use set()
+ const LLColor4U& setVec(const LLColor4U &vec); // deprecated -- use set()
+ const LLColor4U& setVec(const U8 *vec); // deprecated -- use set()
const LLColor4U& setAlpha(U8 a);
- F32 magVec() const; // Returns magnitude of LLColor4U
- F32 magVecSquared() const; // Returns magnitude squared of LLColor4U
+ F32 magVec() const; // deprecated -- use length()
+ F32 magVecSquared() const; // deprecated -- use lengthSquared()
+
+ F32 length() const; // Returns magnitude squared of LLColor4U
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor4U
friend std::ostream& operator<<(std::ostream& s, const LLColor4U &a); // Print a
friend LLColor4U operator+(const LLColor4U &a, const LLColor4U &b); // Return vector a + b
@@ -127,7 +124,13 @@ public:
inline void setVecScaleClamp(const LLColor3 &color);
inline void setVecScaleClamp(const LLColor4 &color);
- static BOOL parseColor4U(const char* buf, LLColor4U* value);
+ static BOOL parseColor4U(const std::string& buf, LLColor4U* value);
+
+ // conversion
+ operator const LLColor4() const
+ {
+ return LLColor4(*this);
+ }
static LLColor4U white;
static LLColor4U black;
@@ -199,7 +202,7 @@ inline const LLColor4U& LLColor4U::setToWhite(void)
return (*this);
}
-inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z)
+inline const LLColor4U& LLColor4U::set(const U8 x, const U8 y, const U8 z)
{
mV[VX] = x;
mV[VY] = y;
@@ -211,7 +214,7 @@ inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z)
return (*this);
}
-inline const LLColor4U& LLColor4U::setVec(const U8 r, const U8 g, const U8 b, U8 a)
+inline const LLColor4U& LLColor4U::set(const U8 r, const U8 g, const U8 b, U8 a)
{
mV[0] = r;
mV[1] = g;
@@ -220,7 +223,7 @@ inline const LLColor4U& LLColor4U::setVec(const U8 r, const U8 g, const U8 b, U8
return (*this);
}
-inline const LLColor4U& LLColor4U::setVec(const LLColor4U &vec)
+inline const LLColor4U& LLColor4U::set(const LLColor4U &vec)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
@@ -229,17 +232,49 @@ inline const LLColor4U& LLColor4U::setVec(const LLColor4U &vec)
return (*this);
}
-/*
-inline const LLColor4U& LLColor4U::setVec(const LLColor4 &vec)
+inline const LLColor4U& LLColor4U::set(const U8 *vec)
{
- mV[VX] = (U8) (llmin(1.f, vec.mV[VX]) * 255.f);
- mV[VY] = (U8) (llmin(1.f, vec.mV[VY]) * 255.f);
- mV[VZ] = (U8) (llmin(1.f, vec.mV[VZ]) * 255.f);
- mV[VW] = (U8) (llmin(1.f, vec.mV[VW]) * 255.f);
+ mV[VX] = vec[VX];
+ mV[VY] = vec[VY];
+ mV[VZ] = vec[VZ];
+ mV[VW] = vec[VW];
return (*this);
}
-*/
+// deprecated
+inline const LLColor4U& LLColor4U::setVec(const U8 x, const U8 y, const U8 z)
+{
+ mV[VX] = x;
+ mV[VY] = y;
+ mV[VZ] = z;
+
+// no change to alpha!
+// mV[VW] = 255;
+
+ return (*this);
+}
+
+// deprecated
+inline const LLColor4U& LLColor4U::setVec(const U8 r, const U8 g, const U8 b, U8 a)
+{
+ mV[0] = r;
+ mV[1] = g;
+ mV[2] = b;
+ mV[3] = a;
+ return (*this);
+}
+
+// deprecated
+inline const LLColor4U& LLColor4U::setVec(const LLColor4U &vec)
+{
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
+ mV[VW] = vec.mV[VW];
+ return (*this);
+}
+
+// deprecated
inline const LLColor4U& LLColor4U::setVec(const U8 *vec)
{
mV[VX] = vec[VX];
@@ -256,13 +291,24 @@ inline const LLColor4U& LLColor4U::setAlpha(U8 a)
}
// LLColor4U Magnitude and Normalization Functions
-// bookmark
+inline F32 LLColor4U::length(void) const
+{
+ return fsqrtf( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] );
+}
+
+inline F32 LLColor4U::lengthSquared(void) const
+{
+ return ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ];
+}
+
+// deprecated
inline F32 LLColor4U::magVec(void) const
{
return fsqrtf( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] );
}
+// deprecated
inline F32 LLColor4U::magVecSquared(void) const
{
return ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ];
@@ -407,13 +453,13 @@ inline const LLColor4U& operator%=(LLColor4U &a, U8 k)
inline F32 distVec(const LLColor4U &a, const LLColor4U &b)
{
LLColor4U vec = a - b;
- return (vec.magVec());
+ return (vec.length());
}
inline F32 distVec_squared(const LLColor4U &a, const LLColor4U &b)
{
LLColor4U vec = a - b;
- return (vec.magVecSquared());
+ return (vec.lengthSquared());
}
void LLColor4U::setVecScaleClamp(const LLColor4& color)
diff --git a/indra/llmath/v4math.cpp b/indra/llmath/v4math.cpp
index 9da4b501d6..2782cf2966 100644
--- a/indra/llmath/v4math.cpp
+++ b/indra/llmath/v4math.cpp
@@ -2,30 +2,25 @@
* @file v4math.cpp
* @brief LLVector4 class implementation.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h
index 9f71d3452a..e7028626f9 100644
--- a/indra/llmath/v4math.h
+++ b/indra/llmath/v4math.h
@@ -2,30 +2,25 @@
* @file v4math.h
* @brief LLVector4 class header file.
*
- * $LicenseInfo:firstyear=2000&license=viewergpl$
- *
- * Copyright (c) 2000-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmath/xform.cpp b/indra/llmath/xform.cpp
index 8399dfb4dd..b75aec6a27 100644
--- a/indra/llmath/xform.cpp
+++ b/indra/llmath/xform.cpp
@@ -1,30 +1,25 @@
/**
* @file xform.cpp
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,6 +36,11 @@ LLXform::~LLXform()
{
}
+// Link optimization - don't inline these llwarns
+void LLXform::warn(const char* const msg)
+{
+ llwarns << msg << llendl;
+}
LLXform* LLXform::getRoot() const
{
diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h
index feca790820..5159c1cbfe 100644
--- a/indra/llmath/xform.h
+++ b/indra/llmath/xform.h
@@ -1,30 +1,25 @@
/**
* @file xform.h
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -106,6 +101,12 @@ public:
inline void setRotation(const LLQuaternion& rot);
inline void setRotation(const F32 x, const F32 y, const F32 z);
inline void setRotation(const F32 x, const F32 y, const F32 z, const F32 s);
+
+ // Above functions must be inline for speed, but also
+ // need to emit warnings. llwarns causes inline LLError::CallSite
+ // static objects that make more work for the linker.
+ // Avoid inline llwarns by calling this function.
+ void warn(const char* const msg);
void setChanged(const U32 bits) { mChanged |= bits; }
BOOL isChanged() const { return mChanged; }
@@ -172,7 +173,7 @@ BOOL LLXform::setParent(LLXform* parent)
{
if (cur_par == this)
{
- llwarns << "LLXform::setParent Creating loop when setting parent!" << llendl;
+ //warn("LLXform::setParent Creating loop when setting parent!");
return FALSE;
}
cur_par = cur_par->mParent;
@@ -190,7 +191,7 @@ void LLXform::setPosition(const LLVector3& pos)
else
{
mPosition.clearVec();
- llwarns << "Non Finite in LLXform::setPosition(LLVector3)" << llendl;
+ warn("Non Finite in LLXform::setPosition(LLVector3)");
}
}
@@ -202,7 +203,7 @@ void LLXform::setPosition(const F32 x, const F32 y, const F32 z)
else
{
mPosition.clearVec();
- llwarns << "Non Finite in LLXform::setPosition(F32,F32,F32)" << llendl;
+ warn("Non Finite in LLXform::setPosition(F32,F32,F32)");
}
}
@@ -214,7 +215,7 @@ void LLXform::setPositionX(const F32 x)
else
{
mPosition.mV[VX] = 0.f;
- llwarns << "Non Finite in LLXform::setPositionX" << llendl;
+ warn("Non Finite in LLXform::setPositionX");
}
}
@@ -226,7 +227,7 @@ void LLXform::setPositionY(const F32 y)
else
{
mPosition.mV[VY] = 0.f;
- llwarns << "Non Finite in LLXform::setPositionY" << llendl;
+ warn("Non Finite in LLXform::setPositionY");
}
}
@@ -238,7 +239,7 @@ void LLXform::setPositionZ(const F32 z)
else
{
mPosition.mV[VZ] = 0.f;
- llwarns << "Non Finite in LLXform::setPositionZ" << llendl;
+ warn("Non Finite in LLXform::setPositionZ");
}
}
@@ -248,7 +249,7 @@ void LLXform::addPosition(const LLVector3& pos)
if (pos.isFinite())
mPosition += pos;
else
- llwarns << "Non Finite in LLXform::addPosition" << llendl;
+ warn("Non Finite in LLXform::addPosition");
}
void LLXform::setScale(const LLVector3& scale)
@@ -259,7 +260,7 @@ void LLXform::setScale(const LLVector3& scale)
else
{
mScale.setVec(1.f, 1.f, 1.f);
- llwarns << "Non Finite in LLXform::setScale" << llendl;
+ warn("Non Finite in LLXform::setScale");
}
}
void LLXform::setScale(const F32 x, const F32 y, const F32 z)
@@ -270,7 +271,7 @@ void LLXform::setScale(const F32 x, const F32 y, const F32 z)
else
{
mScale.setVec(1.f, 1.f, 1.f);
- llwarns << "Non Finite in LLXform::setScale" << llendl;
+ warn("Non Finite in LLXform::setScale");
}
}
void LLXform::setRotation(const LLQuaternion& rot)
@@ -281,7 +282,7 @@ void LLXform::setRotation(const LLQuaternion& rot)
else
{
mRotation.loadIdentity();
- llwarns << "Non Finite in LLXform::setRotation" << llendl;
+ warn("Non Finite in LLXform::setRotation");
}
}
void LLXform::setRotation(const F32 x, const F32 y, const F32 z)
@@ -294,7 +295,7 @@ void LLXform::setRotation(const F32 x, const F32 y, const F32 z)
else
{
mRotation.loadIdentity();
- llwarns << "Non Finite in LLXform::setRotation" << llendl;
+ warn("Non Finite in LLXform::setRotation");
}
}
void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
@@ -307,7 +308,7 @@ void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s)
else
{
mRotation.loadIdentity();
- llwarns << "Non Finite in LLXform::setRotation" << llendl;
+ warn("Non Finite in LLXform::setRotation");
}
}