Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

View File

@@ -0,0 +1,16 @@
Makefile
Makefile.in
config.h.in
config.h
config.log
config.status
configure
libtool
stamp-h
aclocal.m4
OpenEXR.pc
autom4te.cache
ltmain.sh
stamp-h.in
depcomp
.deps

View File

@@ -0,0 +1,31 @@
# yue.nicholas@gmail.com
ADD_EXECUTABLE ( ImathTest
main.cpp
testBox.cpp
testBoxAlgo.cpp
testColor.cpp
testExtractEuler.cpp
testExtractSHRT.cpp
testFrustum.cpp
testFrustumTest.cpp
testFun.cpp
testInvert.cpp
testJacobiEigenSolver.cpp
testLineAlgo.cpp
testMatrix.cpp
testMiscMatrixAlgo.cpp
testProcrustes.cpp
testQuat.cpp
testQuatSetRotation.cpp
testQuatSlerp.cpp
testRandom.cpp
testRoots.cpp
testShear.cpp
testTinySVD.cpp
testVec.cpp
)
ADD_TEST ( TestImath ImathTest )
TARGET_LINK_LIBRARIES ( ImathTest Imath Iex )

View File

@@ -0,0 +1,31 @@
## Process this file with automake to produce Makefile.in
check_PROGRAMS = ImathTest
ImathTest_SOURCES = main.cpp testExtractEuler.cpp testExtractSHRT.cpp \
testFrustum.cpp testFun.cpp testInvert.cpp \
testMatrix.cpp testRandom.cpp testRoots.cpp \
testShear.cpp testColor.cpp testColor.h \
testExtractEuler.h testExtractSHRT.h testFrustum.h \
testFun.h testInvert.h testMatrix.h testRandom.h \
testRoots.h testShear.h testQuatSetRotation.cpp \
testQuatSetRotation.h testLineAlgo.cpp testLineAlgo.h \
testQuatSlerp.cpp testQuatSlerp.h testQuat.cpp \
testQuat.h testBoxAlgo.cpp testBoxAlgo.h \
testVec.cpp testVec.h testBox.cpp testBox.h \
testMiscMatrixAlgo.cpp testMiscMatrixAlgo.h \
testProcrustes.cpp testProcrustes.h \
testTinySVD.cpp testTinySVD.h \
testJacobiEigenSolver.cpp testJacobiEigenSolver.h \
testFrustumTest.cpp testFrustumTest.h
INCLUDES = -I$(top_builddir) -I$(top_srcdir)/Imath -I$(top_srcdir)/Iex -I$(top_srcdir)/Half \
-I$(top_srcdir)/config
LDADD = -L$(top_builddir)/Imath -L$(top_builddir)/Iex -L$(top_builddir)/Half \
-lImath -lIex -lHalf
TESTS = ImathTest
EXTRA_DIST = CMakeLists.txt

View File

@@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testVec.h>
#include <testRoots.h>
#include <testFun.h>
#include <testInvert.h>
#include <testFrustum.h>
#include <testRandom.h>
#include <testColor.h>
#include <testShear.h>
#include <testMatrix.h>
#include <testMiscMatrixAlgo.h>
#include <testExtractEuler.h>
#include <testExtractSHRT.h>
#include <testQuat.h>
#include <testQuatSetRotation.h>
#include <testQuatSlerp.h>
#include <testLineAlgo.h>
#include <testBoxAlgo.h>
#include <testBox.h>
#include <testProcrustes.h>
#include <testTinySVD.h>
#include <testJacobiEigenSolver.h>
#include <testFrustumTest.h>
#include <string.h>
#define TEST(x) if (argc < 2 || !strcmp (argv[1], #x)) x();
int
main (int argc, char *argv[])
{
TEST (testVec);
TEST (testColor);
TEST (testShear);
TEST (testMatrix);
TEST (testMiscMatrixAlgo);
TEST (testRoots);
TEST (testFun);
TEST (testInvert);
TEST (testFrustum);
TEST (testRandom);
TEST (testExtractEuler);
TEST (testExtractSHRT);
TEST (testQuat);
TEST (testQuatSetRotation);
TEST (testQuatSlerp);
TEST (testLineAlgo);
TEST (testBoxAlgo);
TEST (testBox);
TEST (testProcrustes);
TEST (testTinySVD);
TEST (testJacobiEigenSolver);
TEST (testFrustumTest);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testBox();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testBoxAlgo ();

View File

@@ -0,0 +1,192 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testColor.h>
#include "ImathColor.h"
#include "ImathColorAlgo.h"
#include "ImathLimits.h"
#include "ImathMath.h"
#include <iostream>
#include <assert.h>
using namespace std;
void
testColor ()
{
cout << "Testing functions in ImathColor.h & ImathColorAlgo.h" << endl;
cout << "rgb2packed -> packed2rgb" << endl;
const float epsilon = IMATH_INTERNAL_NAMESPACE::limits< float >::epsilon();
IMATH_INTERNAL_NAMESPACE::PackedColor packed;
IMATH_INTERNAL_NAMESPACE::C3c in3( 52, 128, 254 );
IMATH_INTERNAL_NAMESPACE::C3c out3;
packed = IMATH_INTERNAL_NAMESPACE::rgb2packed( in3 );
IMATH_INTERNAL_NAMESPACE::packed2rgb( packed, out3 );
assert ( in3 == out3 );
IMATH_INTERNAL_NAMESPACE::C4c testConstructor1;
IMATH_INTERNAL_NAMESPACE::C4c testConstructor2( testConstructor1 );
testConstructor1 = testConstructor2; // use these so the compiler doesn't emit a warning
IMATH_INTERNAL_NAMESPACE::C4c testConstructor3( 52, 128, 254, 127 );
IMATH_INTERNAL_NAMESPACE::C4c A( testConstructor3 );
IMATH_INTERNAL_NAMESPACE::C4c B;
IMATH_INTERNAL_NAMESPACE::C4f X, Y, tmp;
packed = IMATH_INTERNAL_NAMESPACE::rgb2packed( A );
IMATH_INTERNAL_NAMESPACE::packed2rgb( packed, B );
assert ( A == B );
cout << "Imath::Color4 * f" << endl;
assert ( ( IMATH_INTERNAL_NAMESPACE::C4f( 0.330f, 0.710f, 0.010f, 0.999f ) * 0.999f ) ==
IMATH_INTERNAL_NAMESPACE::C4f( 0.330f * 0.999f,
0.710f * 0.999f,
0.010f * 0.999f,
0.999f * 0.999f ) );
cout << "Imath::Color4 / f" << endl;
assert ( ( IMATH_INTERNAL_NAMESPACE::C4f( 0.330f, 0.710f, 0.010f, 0.999f ) / 0.999f ) ==
IMATH_INTERNAL_NAMESPACE::C4f( 0.330f / 0.999f,
0.710f / 0.999f,
0.010f / 0.999f,
0.999f / 0.999f ) );
cout << "Assignment and comparison" << endl;
B = A;
assert( B == A );
assert( !( B != A ) );
X = Y = IMATH_INTERNAL_NAMESPACE::C4f( 0.123f, -0.420f, 0.501f, 0.998f );
X *= 0.001f;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.r * 0.001f ) - X.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.g * 0.001f ) - X.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.b * 0.001f ) - X.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.a * 0.001f ) - X.a ) <= epsilon );
X = Y = IMATH_INTERNAL_NAMESPACE::C4f( 0.123f, -0.420f, 0.501f, 0.998f );
X /= -1.001f;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.r / -1.001f ) - X.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.g / -1.001f ) - X.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.b / -1.001f ) - X.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.a / -1.001f ) - X.a ) <= epsilon );
Y = IMATH_INTERNAL_NAMESPACE::C4f( 0.998f, -0.001f, 0.501f, 1.001f );
X = IMATH_INTERNAL_NAMESPACE::C4f( 0.011f, -0.420f, -0.501f, 0.998f );
tmp = X + Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r + Y.r ) - tmp.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g + Y.g ) - tmp.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b + Y.b ) - tmp.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a + Y.a ) - tmp.a ) <= epsilon );
tmp = X - Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r - Y.r ) - tmp.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g - Y.g ) - tmp.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b - Y.b ) - tmp.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a - Y.a ) - tmp.a ) <= epsilon );
tmp = X * Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r * Y.r ) - tmp.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g * Y.g ) - tmp.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b * Y.b ) - tmp.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a * Y.a ) - tmp.a ) <= epsilon );
tmp = X / Y;
//
// epsilon doesn't work here.
//
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r / Y.r ) - tmp.r ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g / Y.g ) - tmp.g ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b / Y.b ) - tmp.b ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a / Y.a ) - tmp.a ) <= 1e-5f );
tmp = X;
tmp += Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r + Y.r ) - tmp.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g + Y.g ) - tmp.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b + Y.b ) - tmp.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a + Y.a ) - tmp.a ) <= epsilon );
tmp = X;
tmp -= Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r - Y.r ) - tmp.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g - Y.g ) - tmp.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b - Y.b ) - tmp.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a - Y.a ) - tmp.a ) <= epsilon );
tmp = X;
tmp *= Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r * Y.r ) - tmp.r ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g * Y.g ) - tmp.g ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b * Y.b ) - tmp.b ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a * Y.a ) - tmp.a ) <= epsilon );
tmp = X;
tmp /= Y;
//
// epsilon doesn't work here.
//
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.r / Y.r ) - tmp.r ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.g / Y.g ) - tmp.g ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.b / Y.b ) - tmp.b ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.a / Y.a ) - tmp.a ) <= 1e-5f );
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testColor ();

View File

@@ -0,0 +1,281 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testExtractEuler.h>
#include "ImathMatrixAlgo.h"
#include "ImathEuler.h"
#include "ImathRandom.h"
#include "ImathFun.h"
#include <iostream>
#include <assert.h>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
float rad (float deg) {return deg * (M_PI / 180);}
float deg (float rad) {return rad * (180 / M_PI);}
M44f
matrixEulerMatrix_1 (const M44f &M, Eulerf::Order order)
{
V3f f;
if (order == Eulerf::XYZ)
extractEulerXYZ (M, f);
else
extractEulerZYX (M, f);
return Eulerf(f, order).toMatrix44();
}
M44f
matrixEulerMatrix_2 (const M44f &M, Eulerf::Order order)
{
Eulerf f (order);
f.extract (M);
return f.toMatrix44();
}
void
testMatrix (const M44f M,
M44f (*matrixEulerMatrix)(const M44f &, Eulerf::Order),
Eulerf::Order order)
{
//
// Extract Euler angles from M, and convert the
// Euler angles back to a matrix, N.
//
M44f N = matrixEulerMatrix (M, order);
//
// Verify that the entries in M and N do not
// differ too much.
//
M44f D (M - N);
for (int j = 0; j < 3; ++j)
{
for (int k = 0; k < 3; ++k)
{
if (abs (D[j][k]) > 0.000002)
{
cout << "unexpectedly large matrix to "
"euler angles conversion error: " <<
D[j][k] << endl;
cout << j << " " << k << endl;
cout << "M\n" << M << endl;
cout << "N\n" << N << endl;
cout << "D\n" << D << endl;
assert (false);
}
}
}
}
void
testRandomAngles (M44f (*matrixEulerMatrix)(const M44f &, Eulerf::Order),
Eulerf::Order order)
{
Rand48 r(0);
for (int i = 0; i < 100000; ++i)
{
//
// Create a rotation matrix, M
//
Eulerf e (rad (r.nextf (-180, 180)),
rad (r.nextf (-180, 180)),
rad (r.nextf (-180, 180)),
Eulerf::XYZ);
M44f M (e.toMatrix44());
//
// Add a small random error to the elements of M
//
for (int j = 0; j < 3; ++j)
for (int k = 0; k < 3; ++k)
M[j][k] += r.nextf (-1e-7, 1e-7);
//
// Extract Euler angles from M, convert the Euler angles
// back to a matrix, N, and verify that the entries in M
// and N do not differ too much.
//
testMatrix (M, matrixEulerMatrix, order);
}
}
void
testAngles (V3f angles,
M44f (*matrixEulerMatrix)(const M44f &, Eulerf::Order),
Eulerf::Order order)
{
Eulerf e (rad (angles.x),
rad (angles.y),
rad (angles.z),
order);
M44f M (e.toMatrix44());
//
// With rounding errors from e.toMatrix.
//
testMatrix (M, matrixEulerMatrix, order);
//
// Without rounding errors (assuming that
// all angles are multiples of 90 degrees).
//
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
if (M[i][j] < -0.5)
M[i][j] = -1;
else if (M[i][j] > 0.5)
M[i][j] = 1;
else
M[i][j] = 0;
testMatrix (M, matrixEulerMatrix, order);
}
void
test (M44f (*matrixEulerMatrix)(const M44f &, Eulerf::Order),
Eulerf::Order order)
{
cout << "order = " << setbase (16) << int (order) << setbase (10) << endl;
// cout << "random angles" << endl;
testRandomAngles (matrixEulerMatrix, order);
// cout << "special angles" << endl;
for (int i = 0; i < 360; i += 90)
for (int j = 0; j < 360; j += 90)
for (int k = 0; k < 360; k += 90)
testAngles (V3f (i, j, k), matrixEulerMatrix, order);
}
void
testRandomAngles33 ()
{
Rand48 r(0);
float eps = 8.0 * limits<float>::epsilon();
for (int i = 0; i < 100000; ++i)
{
float angle = rad (r.nextf (-180, 180));
M33f M;
M.setRotation (angle);
float angleEx;
extractEuler (M, angleEx);
assert (IMATH_INTERNAL_NAMESPACE::equal (angle, angleEx, eps));
}
}
} // namespace
void
testExtractEuler ()
{
cout << "Testing extraction of rotation angle from 3x3 matrices" << endl;
testRandomAngles33 ();
cout << "Testing extraction of Euler angles from matrices" << endl;
cout << "extractEulerXYZ()" << endl;
test (matrixEulerMatrix_1, Eulerf::XYZ);
cout << "extractEulerZYX()" << endl;
test (matrixEulerMatrix_1, Eulerf::ZYX);
cout << "Eulerf::extract()" << endl;
test (matrixEulerMatrix_2, Eulerf::XYZ);
test (matrixEulerMatrix_2, Eulerf::XZY);
test (matrixEulerMatrix_2, Eulerf::YZX);
test (matrixEulerMatrix_2, Eulerf::YXZ);
test (matrixEulerMatrix_2, Eulerf::ZXY);
test (matrixEulerMatrix_2, Eulerf::ZYX);
test (matrixEulerMatrix_2, Eulerf::XZX);
test (matrixEulerMatrix_2, Eulerf::XYX);
test (matrixEulerMatrix_2, Eulerf::YXY);
test (matrixEulerMatrix_2, Eulerf::YZY);
test (matrixEulerMatrix_2, Eulerf::ZYZ);
test (matrixEulerMatrix_2, Eulerf::ZXZ);
test (matrixEulerMatrix_2, Eulerf::XYZr);
test (matrixEulerMatrix_2, Eulerf::XZYr);
test (matrixEulerMatrix_2, Eulerf::YZXr);
test (matrixEulerMatrix_2, Eulerf::YXZr);
test (matrixEulerMatrix_2, Eulerf::ZXYr);
test (matrixEulerMatrix_2, Eulerf::ZYXr);
test (matrixEulerMatrix_2, Eulerf::XZXr);
test (matrixEulerMatrix_2, Eulerf::XYXr);
test (matrixEulerMatrix_2, Eulerf::YXYr);
test (matrixEulerMatrix_2, Eulerf::YZYr);
test (matrixEulerMatrix_2, Eulerf::ZYZr);
test (matrixEulerMatrix_2, Eulerf::ZXZr);
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testExtractEuler ();

View File

@@ -0,0 +1,447 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testExtractSHRT.h>
#include "ImathMatrixAlgo.h"
#include "ImathEuler.h"
#include "ImathRandom.h"
#include "ImathFun.h"
#include <iostream>
#include <exception>
#include <stdio.h>
#include <assert.h>
#if 0
#define debug(x) (printf x, fflush (stdout))
#else
#define debug(x)
#endif
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
float rad (float deg) {return deg * (M_PI / 180);}
float deg (float rad) {return rad * (180 / M_PI);}
void
testMatrix (const M33f M)
{
//
// Extract the rotation angle from M, and convert the
// angle back to a matrix, N.
//
V2f s, t;
float h, r;
extractSHRT (M, s, h, r, t, true);
M33f N;
N *= M33f().setScale (s);
N *= M33f().setShear (h);
N *= M33f().setRotation (r);
N *= M33f().setTranslation (t);
debug (("Re-scale: %f %f\n", s[0], s[1]));
debug (("Re-shear: %f\n", h));
debug (("Re-rot : %f\n", r));
debug (("Re-trans: %f %f\n", t[0], t[1]));
//
// Verify that the entries in M and N do not
// differ too much.
//
M33f D (M - N);
for (int j = 0; j < 3; ++j)
{
for (int k = 0; k < 3; ++k)
{
if (abs (D[j][k]) > 0.00001)
{
cout << "unexpectedly large matrix to "
"euler angles conversion error: " <<
D[j][k] << endl;
cout << j << " " << k << endl;
cout << "M\n" << M << endl;
cout << "N\n" << N << endl;
cout << "D\n" << D << endl;
assert (false);
}
}
}
}
void
testRandomAngles33 ()
{
Rand48 random(0);
for (int i = 0; i < 100000; ++i)
{
debug (("iteration: %d\n", i));
M33f M;
//
// Scale M.
//
V2f s (random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0));
for (int j=0; j < 2; j++)
if (random.nextf (0.0, 1.0) >= 0.5)
s[j] *= -1;
M *= M33f().setScale (s);
//
// Shear M.
//
float h = random.nextf (0.000001, 2.);
if (random.nextf (0.0, 1.0) >= 0.5)
h *= -1;
M *= M33f().setShear (h);
//
// Rotate M.
//
float r = rad (random.nextf (-180, 180));
M *= M33f().setRotation (r);
//
// Translate M.
//
V2f t (random.nextf (-10, 10),
random.nextf (-10, 10));
M *= M33f().setTranslation (t);
//
// Add a small random error to the elements of M
//
for (int j = 0; j < 3; ++j)
for (int k = 0; k < 2; ++k)
M[j][k] += random.nextf (-1e-7, 1e-7);
debug (("Scale : %f %f\n", s[0], s[1]));
debug (("Shear : %f\n", h));
debug (("Rot : %f\n", r));
debug (("Trans : %f %f\n", t[0], t[1]));
//
// Extract Euler angles from M, convert the Euler angles
// back to a matrix, N, and verify that the entries in M
// and N do not differ too much.
//
testMatrix (M);
debug (("\n"));
}
}
void
testAngles33 (float angle)
{
M33f M;
M.setRotation (rad (angle));
//
// With rounding errors from e.toMatrix.
//
testMatrix (M);
//
// Without rounding errors (assuming that
// all angles are multiples of 90 degrees).
//
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
if (M[i][j] < -0.5)
M[i][j] = -1;
else if (M[i][j] > 0.5)
M[i][j] = 1;
else
M[i][j] = 0;
testMatrix (M);
}
void
testMatrix (const M44f M)
{
//
// Extract Euler angles from M, and convert the
// Euler angles back to a matrix, N.
//
V3f s, h, r, t;
extractSHRT (M, s, h, r, t, true);
M44f N;
N.translate (t); // ... matrix compositions
N.rotate (r);
N.shear (h);
N.scale (s);
debug (("Re-scale: %f %f %f\n", s[0], s[1], s[2]));
debug (("Re-shear: %f %f %f\n", h[0], h[1], h[2]));
debug (("Re-rot : %f %f %f\n", r[0], r[1], r[2]));
debug (("Re-trans: %f %f %f\n", t[0], t[1], t[2]));
//
// Verify that the entries in M and N do not
// differ too much.
//
M44f D (M - N);
for (int j = 0; j < 4; ++j)
{
for (int k = 0; k < 4; ++k)
{
if (abs (D[j][k]) > 0.00001)
{
cout << "unexpectedly large matrix to "
"euler angles conversion error: " <<
D[j][k] << endl;
cout << j << " " << k << endl;
cout << "M\n" << M << endl;
cout << "N\n" << N << endl;
cout << "D\n" << D << endl;
assert (false);
}
}
}
}
void
testRandomAngles44 ()
{
Rand48 random(0);
for (int i = 0; i < 100000; ++i)
{
debug (("iteration: %d\n", i));
M44f M;
//
// Translate M.
//
V3f t (random.nextf (-10, 10),
random.nextf (-10, 10),
random.nextf (-10, 10));
M.translate (t);
//
// Rotate M.
//
V3f r (rad (random.nextf (-180, 180)),
rad (random.nextf (-180, 180)),
rad (random.nextf (-180, 180)));
M.rotate (r);
//
// Shear M.
//
V3f h (random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0));
for (int j=0; j < 3; j++)
if (random.nextf (0.0, 1.0) >= 0.5)
h[j] *= -1;
M.shear (h);
//
// Scale M.
//
V3f s (random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0));
for (int j=0; j < 3; j++)
if (random.nextf (0.0, 1.0) >= 0.5)
s[j] *= -1;
M.scale (s);
//
// Add a small random error to the elements of M
//
for (int j = 0; j < 4; ++j)
for (int k = 0; k < 3; ++k)
M[j][k] += random.nextf (-1e-7, 1e-7);
debug (("Scale : %f %f %f\n", s[0], s[1], s[2]));
debug (("Shear : %f %f %f\n", h[0], h[1], h[2]));
debug (("Rot : %f %f %f\n", r[0], r[1], r[2]));
debug (("Trans : %f %f %f\n", t[0], t[1], t[2]));
//
// Extract Euler angles from M, convert the Euler angles
// back to a matrix, N, and verify that the entries in M
// and N do not differ too much.
//
testMatrix (M);
debug (("\n"));
}
}
void
testAngles44 (V3f angles)
{
Eulerf e (rad (angles.x),
rad (angles.y),
rad (angles.z));
M44f M (e.toMatrix44());
//
// With rounding errors from e.toMatrix.
//
testMatrix (M);
//
// Without rounding errors (assuming that
// all angles are multiples of 90 degrees).
//
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
if (M[i][j] < -0.5)
M[i][j] = -1;
else if (M[i][j] > 0.5)
M[i][j] = 1;
else
M[i][j] = 0;
testMatrix (M);
}
void
test ()
{
cout << " random angles" << endl;
cout << " 3x3" << endl;
testRandomAngles33 ();
cout << " 4x4" << endl;
testRandomAngles44 ();
cout << " special angles" << endl;
cout << " 3x3" << endl;
for (int i = 0; i < 360; i += 90)
testAngles33 (float (i));
cout << " 4x4" << endl;
for (int i = 0; i < 360; i += 90)
for (int j = 0; j < 360; j += 90)
for (int k = 0; k < 360; k += 90)
testAngles44 (V3f (i, j, k));
}
} // namespace
void
testExtractSHRT ()
{
try
{
cout << "Testing extraction of scale, shear, rotation, translation "
<< "from matrices" << endl;
cout << "Imath::extractSHRT()" << endl;
test ();
cout << "ok\n" << endl;
}
catch (std::exception &e)
{
cerr << " Caught exception: " << e.what () << endl;
}
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testExtractSHRT ();

View File

@@ -0,0 +1,298 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testFrustum.h>
#include "ImathFrustum.h"
#include "ImathEuler.h"
#include "ImathFun.h"
#include <iostream>
#include <assert.h>
using namespace std;
namespace
{
void
testFrustumPlanes (IMATH_INTERNAL_NAMESPACE::Frustumf &frustum)
{
bool ortho = frustum.orthographic();
IMATH_INTERNAL_NAMESPACE::V3f o (0.0f, 0.0f, 0.0f);
float eps = 5.0e-4;
for (float xRo = 0.0f; xRo < 360.0f; xRo += 100.0f)
{
for (float yRo = 0.0f; yRo < 360.0f; yRo += 105.0f)
{
for (float zRo = 0.0f; zRo < 360.0f; zRo += 110.0f)
{
for (float xTr = -10.0f; xTr < 10.0f; xTr += 2)
{
for (float yTr = -10.0f; yTr < 10.0f; yTr += 3)
{
for (float zTr = -10.0f; zTr < 10.0f; zTr += 4)
{
float xRoRad = xRo * (2.0f * float(M_PI) / 360.0f);
float yRoRad = yRo * (2.0f * float(M_PI) / 360.0f);
float zRoRad = zRo * (2.0f * float(M_PI) / 360.0f);
IMATH_INTERNAL_NAMESPACE::Eulerf e(xRoRad, yRoRad, zRoRad);
IMATH_INTERNAL_NAMESPACE::M44f mView = e.toMatrix44();
mView.translate (IMATH_INTERNAL_NAMESPACE::V3f(xTr, yTr, zTr));
IMATH_INTERNAL_NAMESPACE::Plane3f planes0[6];
frustum.planes (planes0);
IMATH_INTERNAL_NAMESPACE::Plane3f planes[6];
frustum.planes (planes, mView);
IMATH_INTERNAL_NAMESPACE::V3f up = IMATH_INTERNAL_NAMESPACE::V3f(0, 1, 0);
assert ((up ^ planes0[0].normal) > 0.0);
mView.multDirMatrix (up, up);
assert ((up ^ planes[0].normal) > 0.0);
IMATH_INTERNAL_NAMESPACE::V3f pt = (! ortho) ? o :
IMATH_INTERNAL_NAMESPACE::V3f (0.0f, frustum.top(), 0.0f);
float d = planes0[0].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
pt = pt * mView;
d = planes[0].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
IMATH_INTERNAL_NAMESPACE::V3f right = IMATH_INTERNAL_NAMESPACE::V3f(1, 0, 0);
assert ((right ^ planes0[1].normal) > 0.0);
mView.multDirMatrix (right, right);
assert ((right ^ planes[1].normal) > 0.0);
pt = (! ortho) ? o :
IMATH_INTERNAL_NAMESPACE::V3f (frustum.right(), 0.0f, 0.0f);
d = planes0[1].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
pt = pt * mView;
d = planes[1].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
IMATH_INTERNAL_NAMESPACE::V3f down = IMATH_INTERNAL_NAMESPACE::V3f(0, -1, 0);
assert ((down ^ planes0[2].normal) > 0.0);
mView.multDirMatrix (down, down);
assert ((down ^ planes[2].normal) > 0.0);
pt = (! ortho) ? o :
IMATH_INTERNAL_NAMESPACE::V3f (0.0f, frustum.bottom(), 0.0f);
d = planes0[2].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
pt = pt * mView;
d = planes[2].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
IMATH_INTERNAL_NAMESPACE::V3f left = IMATH_INTERNAL_NAMESPACE::V3f(-1, 0, 0);
assert ((left ^ planes0[3].normal) > 0.0);
mView.multDirMatrix (left, left);
assert ((left ^ planes[3].normal) > 0.0);
pt = (! ortho) ? o :
IMATH_INTERNAL_NAMESPACE::V3f (frustum.left(), 0.0f, 0.0f);
d = planes0[3].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
pt = pt * mView;
d = planes[3].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
IMATH_INTERNAL_NAMESPACE::V3f front = IMATH_INTERNAL_NAMESPACE::V3f(0, 0, 1);
assert ((front ^ planes0[4].normal) > 0.0);
mView.multDirMatrix (front, front);
assert ((front ^ planes[4].normal) > 0.0);
pt = IMATH_INTERNAL_NAMESPACE::V3f (0.0f, 0.0f, -frustum.nearPlane());
d = planes0[4].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
pt = pt * mView;
d = planes[4].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
IMATH_INTERNAL_NAMESPACE::V3f back = IMATH_INTERNAL_NAMESPACE::V3f(0, 0, -1);
assert ((back ^ planes0[5].normal) > 0.0);
mView.multDirMatrix (back, back);
assert ((back ^ planes[5].normal) > 0.0);
pt = IMATH_INTERNAL_NAMESPACE::V3f (0.0f, 0.0f, -frustum.farPlane());
d = planes0[5].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
pt = pt * mView;
d = planes[5].distanceTo (pt);
assert (IMATH_INTERNAL_NAMESPACE::iszero (d, eps));
}
}
}
}
}
}
}
}
void
testFrustum ()
{
cout << "Testing functions in ImathFrustum.h";
cout << "\nperspective ";
float n = 1.7;
float f = 567.0;
float l = -3.5;
float r = 2.0;
float b = -1.3;
float t = 0.9;
IMATH_INTERNAL_NAMESPACE::Frustum<float> frustum (n, f, l, r, t, b, false);
assert (IMATH_INTERNAL_NAMESPACE::abs<float> (frustum.fovx() -
(atan2(r,n) - atan2(l,n))) < 1e-6);
assert (IMATH_INTERNAL_NAMESPACE::abs<float> (frustum.fovy() -
(atan2(t,n) - atan2(b,n))) < 1e-6);
cout << "1";
assert (IMATH_INTERNAL_NAMESPACE::abs<float> (frustum.aspect() - ((r-l)/(t-b))) < 1e-6);
cout << "2";
IMATH_INTERNAL_NAMESPACE::M44f m = frustum.projectionMatrix();
assert (IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][0] - ((2*n)/(r-l))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][1]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][2]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][3]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][0]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][1] - ((2*n)/(t-b))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][2]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][3]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][0] - ((r+l)/(r-l))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][1] - ((t+b)/(t-b))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][2] - (-(f+n)/(f-n))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][3] - -1.0) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][0]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][1]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][2] - ((-2*f*n)/(f-n))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][3]) < 1e-6);
cout << "3";
cout << "\nplanes ";
testFrustumPlanes (frustum);
cout << "\nexceptions ";
IMATH_INTERNAL_NAMESPACE::Frustum<float> badFrustum;
badFrustum.set (n, n, l, r, t, b, false);
try
{
(void)badFrustum.projectionMatrix();
assert (!"near == far didn't throw an exception");
}
catch (IEX_NAMESPACE::DivzeroExc) {}
cout << "1";
badFrustum.set (n, f, l, l, t, b, false);
try
{
(void)badFrustum.projectionMatrix();
assert (!"left == right didn't throw an exception");
}
catch (IEX_NAMESPACE::DivzeroExc) {}
cout << "2";
badFrustum.set (n, f, l, r, t, t, false);
try
{
(void)badFrustum.projectionMatrix();
assert (!"top == bottom didn't throw an exception");
}
catch (IEX_NAMESPACE::DivzeroExc) {}
cout << "3";
cout << "\northographic ";
frustum.setOrthographic (true);
m = frustum.projectionMatrix();
assert (IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][0] - (2/(r-l))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][1]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][2]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[0][3]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][0]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][1] - (2/(t-b))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][2]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[1][3]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][0]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][1]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][2] - (-2/(f-n))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[2][3]) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][0] - (-(r+l)/(r-l))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][1] - (-(t+b)/(t-b))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][2] - (-(f+n)/(f-n))) < 1e-6 &&
IMATH_INTERNAL_NAMESPACE::abs<float> (m[3][3] - 1.0) < 1e-6);
cout << "1";
cout << "\nplanes ";
testFrustumPlanes (frustum);
// TODO - There are many little functions in IMATH_INTERNAL_NAMESPACE::Frustum which
// aren't tested here. Those test should be added. But this is
// a start.
IMATH_INTERNAL_NAMESPACE::Frustum<float> f1 (n, f, l, r, t, b, false);
IMATH_INTERNAL_NAMESPACE::Frustum<float> f2 (n, f, l, r, t, b, true);
assert (f1 != f2);
f2.set(n + 0.1, f, l, r, t, b, false);
assert (f1 != f2);
f2.set(n, f + 0.1, l, r, t, b, false);
assert (f1 != f2);
f2.set(n, f, l + 0.1, r, t, b, false);
assert (f1 != f2);
f2.set(n, f, l, r + 0.1, t, b, false);
assert (f1 != f2);
f2.set(n, f, l, r, t + 0.1, b, false);
assert (f1 != f2);
f2.set(n, f, l, r, t, b + 0.1, false);
assert (f1 != f2);
cout << "\npassed inequality test";
f1 = f2;
assert (f1 == f2);
cout << "\npassed equality test";
cout << "\nok\n\n";
}

View File

@@ -0,0 +1,37 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testFrustum ();

View File

@@ -0,0 +1,159 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testFrustumTest.h>
#include "ImathFrustum.h"
#include "ImathFrustumTest.h"
#include "ImathBox.h"
#include "ImathSphere.h"
#include <iostream>
#include <assert.h>
using namespace std;
void
testFrustumTest ()
{
cout << "Testing functions in ImathFrustumTest.h";
cout << "\nisVisible(Vec3) ";
float n = 1.7;
float f = 567.0;
float l = -3.5;
float r = 2.0;
float b = -1.3;
float t = 0.9;
IMATH_INTERNAL_NAMESPACE::Frustum<float> frustum (n, f, l, r, t, b, false);
IMATH_INTERNAL_NAMESPACE::Matrix44<float> cameraMat;
IMATH_INTERNAL_NAMESPACE::Vec3<float> cameraPos(100.0f, 200.0f, 300.0f);
cameraMat.makeIdentity();
cameraMat.translate(cameraPos);
IMATH_INTERNAL_NAMESPACE::FrustumTest<float> frustumTest(frustum, cameraMat);
/////////////////////////////////////////////////////
// Test Vec3's
IMATH_INTERNAL_NAMESPACE::Vec3<float> insideVec (100.0f, 200.0f, 300 - 2.0f);
IMATH_INTERNAL_NAMESPACE::Vec3<float> outsideVec_near(100.0f, 200.0f, 300 - 1.5f);
IMATH_INTERNAL_NAMESPACE::Vec3<float> outsideVec_far (100.0f, 200.0f, 300 - 568.0f);
IMATH_INTERNAL_NAMESPACE::Vec3<float> outsideVec_side(100.0f, 200.0f + 100.0f, 300 - 2.0f);
IMATH_INTERNAL_NAMESPACE::Vec3<float> outsideVec_up (100.0f + 100.0f, 200.0f, 300 - 2.0f);
assert ( frustumTest.isVisible(insideVec));
assert (! frustumTest.isVisible(outsideVec_near));
assert (! frustumTest.isVisible(outsideVec_far));
assert (! frustumTest.isVisible(outsideVec_side));
assert (! frustumTest.isVisible(outsideVec_up));
cout << "passed Vec3\n";
/////////////////////////////////////////////////////
// Test Boxes
IMATH_INTERNAL_NAMESPACE::Vec3<float> tinySize(0.0001f, 0.0001f, 0.0001f);
IMATH_INTERNAL_NAMESPACE::Vec3<float> hugeSize(1000.0f, 1000.0f, 1000.0f);
// Empty box should NOT be visible
assert (!frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >()));
// Tiny box inside the frust should be visible
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(insideVec + tinySize, insideVec + tinySize)));
// Huge boxes inside and outside should be visible
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(insideVec - hugeSize, insideVec + hugeSize)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_near - hugeSize, outsideVec_near + hugeSize)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_far - hugeSize, outsideVec_far + hugeSize)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_side - hugeSize, outsideVec_side + hugeSize)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_up - hugeSize, outsideVec_up + hugeSize)));
// Tiny boxes outside should NOT be visible
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_near - tinySize, outsideVec_near + tinySize)));
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_far - tinySize, outsideVec_far + tinySize)));
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_side - tinySize, outsideVec_side + tinySize)));
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Box<IMATH_INTERNAL_NAMESPACE::Vec3<float> >
(outsideVec_up - tinySize, outsideVec_up + tinySize)));
cout << "passed Box\n";
/////////////////////////////////////////////////////
// Test Spheres
float tinyRadius = 0.0001f;
float hugeRadius = 1000.0f;
// Tiny sphere inside the frust should be visible
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(insideVec, tinyRadius)));
// Huge spheres inside and outside should be visible
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(insideVec, hugeRadius)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_near, hugeRadius)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_far, hugeRadius)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_side, hugeRadius)));
assert (frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_up, hugeRadius)));
// Tiny spheres outside should NOT be visible
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_near, tinyRadius)));
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_far, tinyRadius)));
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_side, tinyRadius)));
assert (! frustumTest.isVisible(IMATH_INTERNAL_NAMESPACE::Sphere3<float>
(outsideVec_up, tinyRadius)));
cout << "passed Sphere\n";
cout << "\nok\n\n";
}

View File

@@ -0,0 +1,37 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testFrustumTest ();

View File

@@ -0,0 +1,215 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testFun.h>
#include "ImathFun.h"
#include <iostream>
#include <assert.h>
#include <stdio.h>
using namespace std;
#if ULONG_MAX == 18446744073709551615LU
typedef long unsigned int Int64;
#else
typedef long long unsigned int Int64;
#endif
void
testf (float f)
{
printf ("\n");
float sf = IMATH_INTERNAL_NAMESPACE::succf (f);
float pf = IMATH_INTERNAL_NAMESPACE::predf (f);
float spf = IMATH_INTERNAL_NAMESPACE::succf (IMATH_INTERNAL_NAMESPACE::predf (f));
float psf = IMATH_INTERNAL_NAMESPACE::predf (IMATH_INTERNAL_NAMESPACE::succf (f));
printf ("f %.9g\n", f);
printf ("sf %.9g\n", sf);
printf ("pf %.9g\n", pf);
printf ("spf %.9g\n", spf);
printf ("psf %.9g\n", psf);
}
void
testd (double d)
{
printf ("\n");
double sd = IMATH_INTERNAL_NAMESPACE::succd (d);
double pd = IMATH_INTERNAL_NAMESPACE::predd (d);
double spd = IMATH_INTERNAL_NAMESPACE::succd (IMATH_INTERNAL_NAMESPACE::predd (d));
double psd = IMATH_INTERNAL_NAMESPACE::predd (IMATH_INTERNAL_NAMESPACE::succd (d));
printf ("d %.18lg\n", d);
printf ("sd %.18lg\n", sd);
printf ("pd %.18lg\n", pd);
printf ("spd %.18lg\n", spd);
printf ("psd %.18lg\n", psd);
}
void
testFun ()
{
cout << "Testing functions in ImathFun.h" << endl;
cout << "floor" << endl;
assert (IMATH_INTERNAL_NAMESPACE::floor ( 0.0f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::floor ( 0.5f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::floor (-0.5f) == -1);
assert (IMATH_INTERNAL_NAMESPACE::floor ( 1.0f) == 1);
assert (IMATH_INTERNAL_NAMESPACE::floor (-1.0f) == -1);
assert (IMATH_INTERNAL_NAMESPACE::floor ( 1.5f) == 1);
assert (IMATH_INTERNAL_NAMESPACE::floor (-1.5f) == -2);
cout << "ceil" << endl;
assert (IMATH_INTERNAL_NAMESPACE::ceil ( 0.0f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::ceil ( 0.5f) == 1);
assert (IMATH_INTERNAL_NAMESPACE::ceil (-0.5f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::ceil ( 1.0f) == 1);
assert (IMATH_INTERNAL_NAMESPACE::ceil (-1.0f) == -1);
assert (IMATH_INTERNAL_NAMESPACE::ceil ( 1.5f) == 2);
assert (IMATH_INTERNAL_NAMESPACE::ceil (-1.5f) == -1);
cout << "trunc" << endl;
assert (IMATH_INTERNAL_NAMESPACE::trunc ( 0.0f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::trunc ( 0.5f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::trunc (-0.5f) == 0);
assert (IMATH_INTERNAL_NAMESPACE::trunc ( 1.0f) == 1);
assert (IMATH_INTERNAL_NAMESPACE::trunc (-1.0f) == -1);
assert (IMATH_INTERNAL_NAMESPACE::trunc ( 1.5f) == 1);
assert (IMATH_INTERNAL_NAMESPACE::trunc (-1.5f) == -1);
cout << "divs / mods" << endl;
assert (IMATH_INTERNAL_NAMESPACE::divs ( 5, 2) == 2 && IMATH_INTERNAL_NAMESPACE::mods ( 5, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 4, 2) == 2 && IMATH_INTERNAL_NAMESPACE::mods ( 4, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 3, 2) == 1 && IMATH_INTERNAL_NAMESPACE::mods ( 3, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 2, 2) == 1 && IMATH_INTERNAL_NAMESPACE::mods ( 2, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 1, 2) == 0 && IMATH_INTERNAL_NAMESPACE::mods ( 1, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 0, 2) == 0 && IMATH_INTERNAL_NAMESPACE::mods ( 0, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs (-1, 2) == 0 && IMATH_INTERNAL_NAMESPACE::mods (-1, 2) == -1);
assert (IMATH_INTERNAL_NAMESPACE::divs (-2, 2) == -1 && IMATH_INTERNAL_NAMESPACE::mods (-2, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs (-3, 2) == -1 && IMATH_INTERNAL_NAMESPACE::mods (-3, 2) == -1);
assert (IMATH_INTERNAL_NAMESPACE::divs (-4, 2) == -2 && IMATH_INTERNAL_NAMESPACE::mods (-4, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs (-5, 2) == -2 && IMATH_INTERNAL_NAMESPACE::mods (-5, 2) == -1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 5, -2) == -2 && IMATH_INTERNAL_NAMESPACE::mods ( 5, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 4, -2) == -2 && IMATH_INTERNAL_NAMESPACE::mods ( 4, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 3, -2) == -1 && IMATH_INTERNAL_NAMESPACE::mods ( 3, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 2, -2) == -1 && IMATH_INTERNAL_NAMESPACE::mods ( 2, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 1, -2) == 0 && IMATH_INTERNAL_NAMESPACE::mods ( 1, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divs ( 0, -2) == 0 && IMATH_INTERNAL_NAMESPACE::mods ( 0, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs (-1, -2) == 0 && IMATH_INTERNAL_NAMESPACE::mods (-1, -2) == -1);
assert (IMATH_INTERNAL_NAMESPACE::divs (-2, -2) == 1 && IMATH_INTERNAL_NAMESPACE::mods (-2, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs (-3, -2) == 1 && IMATH_INTERNAL_NAMESPACE::mods (-3, -2) == -1);
assert (IMATH_INTERNAL_NAMESPACE::divs (-4, -2) == 2 && IMATH_INTERNAL_NAMESPACE::mods (-4, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divs (-5, -2) == 2 && IMATH_INTERNAL_NAMESPACE::mods (-5, -2) == -1);
cout << "divp / modp" << endl;
assert (IMATH_INTERNAL_NAMESPACE::divp ( 5, 2) == 2 && IMATH_INTERNAL_NAMESPACE::modp ( 5, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 4, 2) == 2 && IMATH_INTERNAL_NAMESPACE::modp ( 4, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 3, 2) == 1 && IMATH_INTERNAL_NAMESPACE::modp ( 3, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 2, 2) == 1 && IMATH_INTERNAL_NAMESPACE::modp ( 2, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 1, 2) == 0 && IMATH_INTERNAL_NAMESPACE::modp ( 1, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 0, 2) == 0 && IMATH_INTERNAL_NAMESPACE::modp ( 0, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp (-1, 2) == -1 && IMATH_INTERNAL_NAMESPACE::modp (-1, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp (-2, 2) == -1 && IMATH_INTERNAL_NAMESPACE::modp (-2, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp (-3, 2) == -2 && IMATH_INTERNAL_NAMESPACE::modp (-3, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp (-4, 2) == -2 && IMATH_INTERNAL_NAMESPACE::modp (-4, 2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp (-5, 2) == -3 && IMATH_INTERNAL_NAMESPACE::modp (-5, 2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 5, -2) == -2 && IMATH_INTERNAL_NAMESPACE::modp ( 5, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 4, -2) == -2 && IMATH_INTERNAL_NAMESPACE::modp ( 4, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 3, -2) == -1 && IMATH_INTERNAL_NAMESPACE::modp ( 3, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 2, -2) == -1 && IMATH_INTERNAL_NAMESPACE::modp ( 2, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 1, -2) == 0 && IMATH_INTERNAL_NAMESPACE::modp ( 1, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp ( 0, -2) == 0 && IMATH_INTERNAL_NAMESPACE::modp ( 0, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp (-1, -2) == 1 && IMATH_INTERNAL_NAMESPACE::modp (-1, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp (-2, -2) == 1 && IMATH_INTERNAL_NAMESPACE::modp (-2, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp (-3, -2) == 2 && IMATH_INTERNAL_NAMESPACE::modp (-3, -2) == 1);
assert (IMATH_INTERNAL_NAMESPACE::divp (-4, -2) == 2 && IMATH_INTERNAL_NAMESPACE::modp (-4, -2) == 0);
assert (IMATH_INTERNAL_NAMESPACE::divp (-5, -2) == 3 && IMATH_INTERNAL_NAMESPACE::modp (-5, -2) == 1);
cout << "successor, predecessor" << endl;
testf (0);
testf (0.0 * -1.0);
testf (1);
testf (-1);
testf (16);
testf (7);
testf (0.7);
union {float f; int i;} u;
u.i = 0x7f800000; // inf
testf (u.f);
u.i = 0x7f800001; // nan
testf (u.f);
u.i = 0x7f7fffff; // FLT_MAX
testf (u.f);
u.i = 0xff7fffff; // -FLT_MAX
testf (u.f);
testd (0);
testd (0.0 * -1.0);
testd (1);
testd (-1);
testd (16);
testd (7);
testd (0.7);
union {double d; Int64 i;} v;
v.i = 0x7ff0000000000000ULL; // inf
testd (v.d);
v.i = 0x7ff0000000000001ULL; // NAN
testd (v.d);
v.i = 0x7fefffffffffffffULL; // FLT_MAX
testd (v.d);
v.i = 0xffefffffffffffffULL; // -FLT_MAX
testd (v.d);
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testFun ();

View File

@@ -0,0 +1,157 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testInvert.h>
#include "ImathMatrix.h"
#include "ImathMatrixAlgo.h"
#include <iostream>
#include <assert.h>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
void
invertM44f (const M44f &m, float e)
{
M44f inv1 = m.inverse();
M44f inv2 = m.gjInverse();
M44f ident1 = m * inv1;
M44f ident2 = m * inv2;
//cout << "m\n" << m << endl;
//cout << "inv1\n" << inv1 << "ident1\n" << ident1 << endl;
//cout << "inv2\n" << inv2 << "ident2\n" << ident2 << endl;
assert (ident1.equalWithAbsError (identity44f, e));
assert (ident2.equalWithAbsError (identity44f, e));
}
void
invertM33f (const M33f &m, float e)
{
M33f inv1 = m.inverse();
M33f inv2 = m.gjInverse();
M33f ident1 = m * inv1;
M33f ident2 = m * inv2;
//cout << "m\n" << m << endl;
//cout << "inv1\n" << inv1 << "ident1\n" << ident1 << endl;
//cout << "inv2\n" << inv2 << "ident2\n" << ident2 << endl;
assert (ident1.equalWithAbsError (identity33f, e));
assert (ident2.equalWithAbsError (identity33f, e));
}
} // namespace
void
testInvert ()
{
cout << "Testing 4x4 and 3x3 matrix inversion:" << endl;
{
cout << "M44f" << endl;
M44f m1 ( 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
M44f m2 ( 0, 1, 0, 0,
-1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
M44f m3 ( 1, 0, 0, 0,
0, 2, 0, 0,
0, 0, 0, -1,
0, 0, 1, 0);
M44f m4 ( 4.683281e-01, -8.749647e-01, 1.229049e-01, 0.000000e+00,
1.251189e-02, 1.456563e-01, 9.892561e-01, 0.000000e+00,
-8.834660e-01, -4.617587e-01, 7.916244e-02, 0.000000e+00,
-4.726541e+00, 3.044795e+00, -6.737138e+00, 1.000000e+00);
M44f m5 ( 4.683281e-01, -8.749647e-01, 1.229049e-01, 1.000000e+00,
1.251189e-02, 1.456563e-01, 9.892561e-01, 2.000000e+00,
-8.834660e-01, -4.617587e-01, 7.916244e-02, 3.000000e+00,
-4.726541e+00, 3.044795e+00, -6.737138e+00, 4.000000e+00);
invertM44f (m1, 0);
invertM44f (m2, 0);
invertM44f (m3, 0);
invertM44f (m4, 1e-6);
invertM44f (m5, 1e-6);
}
{
cout << "M33f" << endl;
M33f m1 ( 1, 0, 0,
0, 1, 0,
0, 0, 1);
M33f m2 ( 0, 1, 0,
-1, 0, 0,
0, 0, 1);
M33f m3 ( 2, 0, 0,
0, 0, -1,
0, 1, 0);
M33f m4 ( 4.683281e-01, -8.749647e-01, 0.000000e+00,
1.251189e-02, 1.456563e-01, 0.000000e+00,
0.000000e+00, 0.000000e+00, 1.000000e+00);
M33f m5 ( 4.683281e-01, -8.749647e-01, 1.229049e-01,
1.251189e-02, 1.456563e-01, 9.892561e-01,
-8.834660e-01, -4.617587e-01, 7.916244e-02);
invertM33f (m1, 0);
invertM33f (m2, 0);
invertM33f (m3, 0);
invertM33f (m4, 1e-6);
invertM33f (m5, 1e-6);
}
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testInvert ();

View File

@@ -0,0 +1,313 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include "ImathMatrix.h"
#include "ImathMatrixAlgo.h"
#include <iostream>
#include <math.h>
#include <cmath>
#include <ctime>
#include <cassert>
#include <limits>
#include <algorithm>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
const Matrix33<double> A33_1 ( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
const Matrix33<double> A33_2 ( 1, 0, 0, 0,-1, 0, 0, 0, 1 );
const Matrix33<double> A33_3 ( 1, 0, 0, 0, 1, 0, 0, 0, 0 );
const Matrix33<double> A33_4 ( 1, 0, 0, 0, 0, 0, 0, 0, 0 );
const Matrix33<double> A33_5 ( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
const Matrix33<double> A33_6 ( 1, 0, 0, 0, 1e-10, 0, 0, 0, 0 );
const Matrix33<double> A33_7 ( 1, 0, 0, 0, 1e-10, 0, 0, 0, 1e+10 );
const Matrix33<double> A33_8 (
0.25058694044821, 0.49427229444416, 0.81415724537748,
0.49427229444416, 0.80192384710853, -0.61674948224910,
0.81415724537748, -0.61674948224910, -1.28486154645285);
const Matrix33<double> A33_9 (
4, -30, 60,
-30, 300, -675,
60, -675, 1620);
const Matrix44<double> A44_1 ( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
const Matrix44<double> A44_2 ( 1, 0, 0, 0, 0,-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
const Matrix44<double> A44_3 ( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
const Matrix44<double> A44_4 ( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
const Matrix44<double> A44_5 ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
const Matrix44<double> A44_6 ( 1, 0, 0, 0, 0, 1e-20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
const Matrix44<double> A44_7 ( 1, 0, 0, 0, 0, 1e-20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1e+20 );
const Matrix44<double> A44_8 (
4.05747631538951, 0.16358123075600, 0.11541756047409, -1.65369223465270,
0.16358123075600, 0.57629829390780, 3.88542912704029, 0.92016316185369,
0.11541756047409, 3.88542912704029, 0.65367032943707, -0.21971103270410,
-1.65369223465270, 0.92016316185369, -0.21971103270410, -0.28108876552761);
const Matrix44<double> A44_9 (
4, -30, 60, -35,
-30, 300, -675, 420,
60, -675, 1620, -1050,
-35, 420, -1050, 700);
template <typename TM>
void
verifyOrthonormal (const TM& A, const typename TM::BaseType threshold)
{
const TM prod = A * A.transposed();
for (int i = 0; i < TM::dimensions(); ++i)
for (int j = 0; j < TM::dimensions(); ++j)
if (i == j)
assert (std::abs (prod[i][j] - 1) < threshold);
else
assert (std::abs (prod[i][j]) < threshold);
}
template <typename TM>
typename TM::BaseType
computeThreshold(const TM& A)
{
typedef typename TM::BaseType T;
T maxAbsEntry(0);
for (int i = 0; i < TM::dimensions(); ++i)
for (int j = 0; j < TM::dimensions(); ++j)
maxAbsEntry = std::max (maxAbsEntry, std::abs(A[i][j]));
const T eps = std::numeric_limits<T>::epsilon();
maxAbsEntry = std::max(maxAbsEntry, eps);
return maxAbsEntry * T(100) * eps;
}
template<class TM>
void
testJacobiEigenSolver(const TM& A)
{
using std::abs;
typedef typename TM::BaseType T;
typedef typename TM::BaseVecType TV;
const T threshold = computeThreshold(A);
TM AA(A);
TV S;
TM V;
jacobiEigenSolver(AA, S, V);
// Orthogonality of V
verifyOrthonormal(V, threshold);
// Determinant of V
assert(abs(V.determinant()) - 1 < threshold);
// Determinant of A and S
TM MS;
for (int i = 0; i < TM::dimensions(); ++i)
for (int j = 0; j < TM::dimensions(); ++j)
if(i == j)
MS[i][j] = S[i];
else
MS[i][j] = 0;
assert(abs(A.determinant()) - abs(MS.determinant()) <
threshold);
// A = V * S * V^T
TM MA = V * MS * V.transposed();
for (int i = 0; i < TM::dimensions(); ++i)
for (int j =0; j < TM::dimensions(); ++j)
assert(abs(A[i][j]-MA[i][j]) < threshold);
}
template<class TM>
void
testMinMaxEigenValue(const TM& A)
{
typedef typename TM::BaseVecType TV;
typedef typename TM::BaseType T;
TV minV, maxV, S;
TM U, V;
const T threshold = computeThreshold(A);
{
TM A1(A);
minEigenVector(A1, minV);
TM A2(A);
maxEigenVector(A2, maxV);
}
{
TM A3(A);
jacobiSVD(A3, U, S, V);
}
const int dim = TM::dimensions();
for(int i = 0; i < dim; ++i) {
assert(abs(minV[i]-V[i][dim - 1]) < threshold);
assert(abs(maxV[i]-V[i][0]) < threshold);
}
}
template <class T>
void
testJacobiTiming()
{
int rounds(100000);
clock_t tJacobi,tSVD, t;
{
Matrix33<T> A,V,U;
Vec3<T> S;
t = clock();
for(int i = 0; i < rounds; ++i) {
A = Matrix33<T>(A33_7);
jacobiEigenSolver(A, S, V);
A = Matrix33<T>(A33_8);
jacobiEigenSolver(A, S, V);
}
tJacobi = clock() - t;
cout << "Jacobi EigenSolver of 3x3 matrices took " << tJacobi << " clocks." << endl;
t = clock();
for(int i = 0; i < rounds; ++i) {
A = Matrix33<T>(A33_7);
jacobiSVD(A, U, S, V);
A = Matrix33<T>(A33_8);
jacobiSVD(A, U, S, V);
}
tSVD = clock() - t;
cout << "TinySVD of 3x3 matrices took " << tSVD << " clocks." << endl;
cout << (float)(tSVD-tJacobi)*100.0f/(float)(tSVD) << "% speed up." << endl;
}
{
Matrix44<T> A,V,U;
Vec4<T> S;
t = clock();
for(int i = 0; i < rounds; ++i) {
A = Matrix44<T>(A44_7);
jacobiEigenSolver(A, S, V);
A = Matrix44<T>(A44_8);
jacobiEigenSolver(A, S, V);
}
tJacobi = clock() - t;
cout << "Jacobi EigenSolver of 4x4 matrices took " << tJacobi << " clocks" << endl;
t = clock();
for(int i = 0; i < rounds; ++i) {
A = Matrix44<T>(A44_7);
jacobiSVD(A, U, S, V);
A = Matrix44<T>(A44_8);
jacobiSVD(A, U, S, V);
}
tSVD = clock() - t;
cout << "TinySVD of 4x4 matrices took " << tSVD << " clocks" << endl;
cout << (float)(tSVD-tJacobi)*100.0f/(float)(tSVD) << "% speed up." << endl;
}
}
template <class T>
void
testJacobiEigenSolverImp()
{
testJacobiEigenSolver(Matrix33<T>(A33_1));
testJacobiEigenSolver(Matrix33<T>(A33_2));
testJacobiEigenSolver(Matrix33<T>(A33_3));
testJacobiEigenSolver(Matrix33<T>(A33_4));
testJacobiEigenSolver(Matrix33<T>(A33_5));
testJacobiEigenSolver(Matrix33<T>(A33_6));
testJacobiEigenSolver(Matrix33<T>(A33_7));
testJacobiEigenSolver(Matrix33<T>(A33_8));
testJacobiEigenSolver(Matrix44<T>(A44_1));
testJacobiEigenSolver(Matrix44<T>(A44_2));
testJacobiEigenSolver(Matrix44<T>(A44_3));
testJacobiEigenSolver(Matrix44<T>(A44_4));
testJacobiEigenSolver(Matrix44<T>(A44_5));
testJacobiEigenSolver(Matrix44<T>(A44_6));
testJacobiEigenSolver(Matrix44<T>(A44_7));
testJacobiEigenSolver(Matrix44<T>(A44_8));
}
template <class T>
void
testMinMaxEigenValueImp()
{
testMinMaxEigenValue(Matrix33<T>(A33_7));
testMinMaxEigenValue(Matrix33<T>(A33_8));
testMinMaxEigenValue(Matrix44<T>(A44_7));
testMinMaxEigenValue(Matrix44<T>(A44_8));
}
void
testJacobiEigenSolver()
{
cout << endl;
cout << "************ Testing IMATH_INTERNAL_NAMESPACE::ImathJacobiEigenSolver ************" << endl;
cout << "Jacobi EigenSolver in single precision...";
testJacobiEigenSolverImp<float>();
cout << "PASS" << endl;
cout << "Jacobi EigenSolver in double precision...";
testJacobiEigenSolverImp<double>();
cout << "PASS" << endl;
cout << "Min/Max EigenValue in single precision...";
testMinMaxEigenValueImp<float>();
cout << "PASS" << endl;
cout << "Min/Max EigenValue in double precision...";
testMinMaxEigenValueImp<double>();
cout << "PASS" << endl;
cout << "Timing Jacobi EigenSolver in single precision...\n";
testJacobiTiming<float>();
cout << "Timing Jacobi EigenSolver in double precision...\n";
testJacobiTiming<double>();
cout << "************ ALL PASS ************" << endl;
}

View File

@@ -0,0 +1,35 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testJacobiEigenSolver();

View File

@@ -0,0 +1,440 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testLineAlgo.h>
#include "ImathLineAlgo.h"
#include "ImathRandom.h"
#include <iostream>
#include <assert.h>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
void
testClosestPoints
(const Line3f &line1,
const Line3f &line2,
bool returnValue,
const V3f &point1,
const V3f &point2)
{
V3f p1;
V3f p2;
bool rv = closestPoints (line1, line2, p1, p2);
assert (rv == returnValue);
if (rv)
{
float e = 10 * limits<float>::epsilon();
assert (point1.equalWithAbsError (p1, e));
assert (point2.equalWithAbsError (p2, e));
}
}
void
testClosestPoints ()
{
cout << "closest points on two lines" << endl;
cout << " non-intersecting, non-parallel lines" << endl;
testClosestPoints
(Line3f (V3f ( 0, -1, -1), V3f ( 0, 1, -1)),
Line3f (V3f (-1, 0, 1), V3f ( 1, 0, 1)),
true,
V3f ( 0, 0, -1),
V3f ( 0, 0, 1));
testClosestPoints
(Line3f (V3f ( 2, -1, -1), V3f ( 2, 1, -1)),
Line3f (V3f (-1, 3, 1), V3f ( 1, 3, 1)),
true,
V3f ( 2, 3, -1),
V3f ( 2, 3, 1));
cout << " intersecting, non-parallel lines" << endl;
testClosestPoints
(Line3f (V3f ( 2, -1, 0), V3f ( 2, 1, 0)),
Line3f (V3f (-1, 3, 0), V3f ( 1, 3, 0)),
true,
V3f ( 2, 3, 0),
V3f ( 2, 3, 0));
cout << " parallel lines" << endl;
testClosestPoints
(Line3f (V3f ( 2, -1, 0), V3f ( 2, 1, 0)),
Line3f (V3f ( 2, -1, 1), V3f ( 2, 1, 1)),
false,
V3f ( 0, 0, 0),
V3f ( 0, 0, 0));
testClosestPoints
(Line3f (V3f ( 2, -1, 0), V3f ( 2, 1, 0)),
Line3f (V3f ( 2, 1, 1), V3f ( 2, -1, 1)),
false,
V3f ( 0, 0, 0),
V3f ( 0, 0, 0));
cout << " coincident lines" << endl;
testClosestPoints
(Line3f (V3f ( 2, -1, 0), V3f ( 2, -1, 1)),
Line3f (V3f ( 2, -1, 0), V3f ( 2, -1, 1)),
false,
V3f ( 0, 0, 0),
V3f ( 0, 0, 0));
cout << " random lines" << endl;
Rand48 rand (7);
for (int i = 0; i < 10000; ++i)
{
Line3f line1 (solidSphereRand<V3f> (rand) * 100.f,
solidSphereRand<V3f> (rand) * 100.f);
Line3f line2 (solidSphereRand<V3f> (rand) * 100.f,
solidSphereRand<V3f> (rand) * 100.f);
V3f point1;
V3f point2;
bool rv = closestPoints (line1, line2, point1, point2);
if (rv)
{
//
// We test if the line that connects point1 and point2
// is perpendicular to line1 and line2. The numerical
// accuracy of point1 and point2 depends strongly on
// the relative directions of line1 and line2; accuracy
// degrades rather quickly if line1 and line2 become
// close to parallel.
//
float e = 2000 * limits<float>::epsilon();
float d = 1 - (line1.dir ^ line2.dir) * (line1.dir ^ line2.dir);
V3f n = point1 - point2;
assert (equalWithAbsError (0.0f, (line1.dir ^ n) * d, e));
assert (equalWithAbsError (0.0f, (line2.dir ^ n) * d, e));
}
}
}
void
testIntersect
(const Line3f &line,
const V3f &v0,
const V3f &v1,
const V3f &v2,
const V3f &point,
bool front,
bool returnValue)
{
V3f pt;
V3f bary;
bool fr;
bool rv = intersect (line, v0, v1, v2, pt, bary, fr);
assert (rv == returnValue);
float e = 10 * limits<float>::epsilon();
if (rv)
{
assert (front == fr);
assert (pt.equalWithAbsError (point, e));
V3f pt2 = v0 * bary.x + v1 * bary.y + v2 * bary.z;
assert (pt.equalWithAbsError (pt2, e));
}
}
void
testIntersect ()
{
cout << "line-triangle intersection" << endl;
cout << " line-plane intersection inside triangle" << endl;
testIntersect (Line3f (V3f (0, 0, -1), V3f (0, 0, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 7),
true,
true);
testIntersect (Line3f (V3f (0, 0, -1), V3f (-1, -2, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (-1, -2, 7),
true,
true);
testIntersect (Line3f (V3f (0, 0, -1), V3f (-1, 1, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (-1, 1, 7),
true,
true);
testIntersect (Line3f (V3f (0, 0, -1), V3f (-1, 1, 7)),
V3f (4, -4, 7), V3f (-4, -4, 7), V3f (0, 6, 7),
V3f (-1, 1, 7),
false,
true);
testIntersect (Line3f (V3f (1, 1, 2), V3f (0, 0, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 7),
true,
true);
testIntersect (Line3f (V3f (2, 3, -5), V3f (-1, -2, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (-1, -2, 7),
true,
true);
testIntersect (Line3f (V3f (2, 8, -10), V3f (-1, 1, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (-1, 1, 7),
true,
true);
testIntersect (Line3f (V3f (-10, 2, -1), V3f (-1, 1, 7)),
V3f (4, -4, 7), V3f (-4, -4, 7), V3f (0, 6, 7),
V3f (-1, 1, 7),
false,
true);
cout << " line-plane intersection outside triangle" << endl;
testIntersect (Line3f (V3f (0, 0, -1), V3f (4, 0, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (0, 0, -1), V3f (-4, 1, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (0, 0, -1), V3f (0, -5, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (0, 0, -1), V3f (0, -7, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
cout << " line parallel to triangle" << endl;
testIntersect (Line3f (V3f (0, 0, -1), V3f (4, 0, -1)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (0, 4, 7), V3f (4, 0, 7)),
V3f (-4, -4, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
cout << " zero-area triangle" << endl;
testIntersect (Line3f (V3f (2, 3, -5), V3f (-1, -2, 7)),
V3f (0, 6, 7), V3f (4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (2, 3, -5), V3f (-1, -2, 7)),
V3f (-4, -4, 7), V3f (-4, -4, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (2, 3, -5), V3f (-1, -2, 7)),
V3f (-4, -4, 7), V3f (0, 6, 7), V3f (0, 6, 7),
V3f (0, 0, 0),
false,
false);
testIntersect (Line3f (V3f (2, 3, -5), V3f (-1, -2, 7)),
V3f (-4, -4, 7), V3f (-4, -4, 7), V3f (-4, -4, 7),
V3f (0, 0, 0),
false,
false);
cout << " random lines and triangles" << endl;
Rand48 rand (8);
for (int i = 0; i < 10000; ++i)
{
//
// Generate a random triangle with non-zero area
//
V3f v0, v1, v2;
V3f normal;
do
{
v0 = solidSphereRand<V3f> (rand);
v1 = solidSphereRand<V3f> (rand);
v2 = solidSphereRand<V3f> (rand);
normal = (v2 - v1) % (v1 - v0);
}
while (normal.length() < 0.01);
{
//
// Generate a line that intersects inside the triangle
//
V3f b;
do
{
b.x = rand.nextf (0.001, 0.999);
b.y = rand.nextf (0.001, 0.999);
b.z = 1 - b.x - b.y;
}
while (b.x + b.y > 0.999);
V3f p1 = v0 * b.x + v1 * b.y + v2 * b.z;
V3f p0;
do
{
p0 = solidSphereRand<V3f> (rand);
}
while (abs (normal.normalized() ^ (p1 - p0).normalized()) < 0.1);
//
// Test for intersection
//
V3f point;
V3f bary;
bool front;
bool rv = intersect (Line3f (p0, p1),
v0, v1, v2, point,
bary, front);
assert (rv == true);
float nd = abs (normal.normalized() ^ (p1 - p0).normalized());
float ep = 20 * limits<float>::epsilon() / nd;
assert (point.equalWithAbsError (p1, ep));
}
{
//
// Generate a line that intersects the triangle's plane
// but outside the triangle
//
V3f b;
do
{
b.x = rand.nextf (-3, 3);
b.y = rand.nextf (-3, 3);
b.z = 1 - b.x - b.y;
}
while (b.x > -0.001 && b.y > -0.001 && b.z > -0.001);
V3f p1 = v0 * b.x + v1 * b.y + v2 * b.z;
V3f p0;
int j = 0;
do
{
p0 = solidSphereRand<V3f> (rand) * 10;
}
while (abs (normal.normalized() ^ (p1 - p0).normalized()) < 0.1);
//
// Test for intersection
//
V3f point;
V3f bary;
bool front;
bool rv = intersect (Line3f (p0, p1),
v0, v1, v2, point,
bary, front);
assert (rv == false);
}
}
}
} // namespace
void
testLineAlgo ()
{
cout << "Testing line algorithms" << endl;
testClosestPoints();
testIntersect();
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testLineAlgo ();

View File

@@ -0,0 +1,457 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testMatrix.h>
#include "ImathMatrix.h"
#include "ImathMatrixAlgo.h"
#include "ImathVec.h"
#include "ImathLimits.h"
#include "ImathMath.h"
#include "ImathInt64.h"
#include "ImathRandom.h"
#include <iostream>
#include <assert.h>
using namespace std;
using IMATH_INTERNAL_NAMESPACE::Int64;
//
// This file is not currently intended to exhaustively test
// the Imath Matrix33<T> and Matrix44<T> classes. We leave
// that to PyImathTest.
//
// Instead, in this file we test only those aspects of the
// Imath Matrix33<T> and Matrix44<T> classes that must be
// or are more convenient to test from C++.
//
void
testMatrix ()
{
cout << "Testing functions in ImathMatrix.h" << endl;
union {float f; int i;} nanf;
nanf.i = 0x7f800001; // NAN
union {double d; Int64 i;} nand;
nand.i = 0x7ff0000000000001ULL; // NAN
{
cout << "Imath::M33f shear functions" << endl;
IMATH_INTERNAL_NAMESPACE::M33f m1, m2;
m1.setShear (2.0f);
assert
(m1[0][0] == 1.0f && m1[0][1] == 0.0f && m1[0][2] == 0.0f &&
m1[1][0] == 2.0f && m1[1][1] == 1.0f && m1[1][2] == 0.0f &&
m1[2][0] == 0.0f && m1[2][1] == 0.0f && m1[2][2] == 1.0f);
m2.setShear (IMATH_INTERNAL_NAMESPACE::V2f (3.0f, 4.0f));
assert
(m2[0][0] == 1.0f && m2[0][1] == 4.0f && m2[0][2] == 0.0f &&
m2[1][0] == 3.0f && m2[1][1] == 1.0f && m2[1][2] == 0.0f &&
m2[2][0] == 0.0f && m2[2][1] == 0.0f && m2[2][2] == 1.0f);
m1.shear (IMATH_INTERNAL_NAMESPACE::V2f (5.0f, 6.0f));
assert
(m1[0][0] == 13.0f && m1[0][1] == 6.0f && m1[0][2] == 0.0f &&
m1[1][0] == 7.0f && m1[1][1] == 1.0f && m1[1][2] == 0.0f &&
m1[2][0] == 0.0f && m1[2][1] == 0.0f && m1[2][2] == 1.0f);
m2.shear (7.0f);
assert
(m2[0][0] == 1.0f && m2[0][1] == 4.0f && m2[0][2] == 0.0f &&
m2[1][0] == 10.0f && m2[1][1] == 29.0f && m2[1][2] == 0.0f &&
m2[2][0] == 0.0f && m2[2][1] == 0.0f && m2[2][2] == 1.0f);
cout << "M33f constructors and equality operators" << endl;
IMATH_INTERNAL_NAMESPACE::M33f test(m2);
assert(test == m2);
IMATH_INTERNAL_NAMESPACE::M33f test2;
assert(test != test2);
IMATH_INTERNAL_NAMESPACE::M33f test3;
test3.makeIdentity();
assert(test2 == test3);
}
{
cout << "M33d constructors and equality operators" << endl;
IMATH_INTERNAL_NAMESPACE::M33d m2;
m2[0][0] = 99.0f;
m2[1][2] = 101.0f;
IMATH_INTERNAL_NAMESPACE::M33d test(m2);
assert(test == m2);
IMATH_INTERNAL_NAMESPACE::M33d test2;
assert(test != test2);
IMATH_INTERNAL_NAMESPACE::M33d test3;
test3.makeIdentity();
assert(test2 == test3);
IMATH_INTERNAL_NAMESPACE::M33f test4 (1.0f, 2.0f, 3.0f,
4.0f, 5.0f, 6.0f,
7.0f, 8.0f, 9.0f);
IMATH_INTERNAL_NAMESPACE::M33d test5 = IMATH_INTERNAL_NAMESPACE::M33d (test4);
assert (test5[0][0] == 1.0);
assert (test5[0][1] == 2.0);
assert (test5[0][2] == 3.0);
assert (test5[1][0] == 4.0);
assert (test5[1][1] == 5.0);
assert (test5[1][2] == 6.0);
assert (test5[2][0] == 7.0);
assert (test5[2][1] == 8.0);
assert (test5[2][2] == 9.0);
}
{
IMATH_INTERNAL_NAMESPACE::M44f m2;
m2[0][0] = 99.0f;
m2[1][2] = 101.0f;
cout << "M44f constructors and equality operators" << endl;
IMATH_INTERNAL_NAMESPACE::M44f test(m2);
assert(test == m2);
IMATH_INTERNAL_NAMESPACE::M44f test2;
assert(test != test2);
IMATH_INTERNAL_NAMESPACE::M44f test3;
test3.makeIdentity();
assert(test2 == test3);
//
// Test non-equality when a NAN is in the same
// place in two identical matrices
//
test2[0][0] = nanf.f;
test3 = test2;
assert(test2 != test3);
}
{
IMATH_INTERNAL_NAMESPACE::M44d m2;
m2[0][0] = 99.0f;
m2[1][2] = 101.0f;
cout << "M44d constructors and equality operators" << endl;
IMATH_INTERNAL_NAMESPACE::M44d test(m2);
assert(test == m2);
IMATH_INTERNAL_NAMESPACE::M44d test2;
assert(test != test2);
IMATH_INTERNAL_NAMESPACE::M44d test3;
test3.makeIdentity();
assert(test2 == test3);
//
// Test non-equality when a NAN is in the same
// place in two identical matrices
//
test2[0][0] = nand.d;
test3 = test2;
assert(test2 != test3);
IMATH_INTERNAL_NAMESPACE::M44f test4 ( 1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f);
IMATH_INTERNAL_NAMESPACE::M44d test5 = IMATH_INTERNAL_NAMESPACE::M44d (test4);
assert (test5[0][0] == 1.0);
assert (test5[0][1] == 2.0);
assert (test5[0][2] == 3.0);
assert (test5[0][3] == 4.0);
assert (test5[1][0] == 5.0);
assert (test5[1][1] == 6.0);
assert (test5[1][2] == 7.0);
assert (test5[1][3] == 8.0);
assert (test5[2][0] == 9.0);
assert (test5[2][1] == 10.0);
assert (test5[2][2] == 11.0);
assert (test5[2][3] == 12.0);
assert (test5[3][0] == 13.0);
assert (test5[3][1] == 14.0);
assert (test5[3][2] == 15.0);
assert (test5[3][3] == 16.0);
}
{
cout << "Converting between M33 and M44" << endl;
IMATH_INTERNAL_NAMESPACE::M44d m1;
m1[0][0] = 99;
IMATH_INTERNAL_NAMESPACE::M44f m2;
m2.setValue(m1);
assert(m2[0][0] == (float)m1[0][0]);
m1[0][0] = 101;
m1.setValue(m2);
assert(m2[0][0] == (float)m1[0][0]);
}
// Matrix minors
{
cout << "3x3 Matrix minors" << endl;
IMATH_INTERNAL_NAMESPACE::M33f a(1,2,3,4,5,6,7,8,9);
assert (a.minorOf(0,0) == a.fastMinor(1,2,1,2));
assert (a.minorOf(0,1) == a.fastMinor(1,2,0,2));
assert (a.minorOf(0,2) == a.fastMinor(1,2,0,1));
assert (a.minorOf(1,0) == a.fastMinor(0,2,1,2));
assert (a.minorOf(1,1) == a.fastMinor(0,2,0,2));
assert (a.minorOf(1,2) == a.fastMinor(0,2,0,1));
assert (a.minorOf(2,0) == a.fastMinor(0,1,1,2));
assert (a.minorOf(2,1) == a.fastMinor(0,1,0,2));
assert (a.minorOf(2,2) == a.fastMinor(0,1,0,1));
}
{
IMATH_INTERNAL_NAMESPACE::M33d a(1,2,3,4,5,6,7,8,9);
assert (a.minorOf(0,0) == a.fastMinor(1,2,1,2));
assert (a.minorOf(0,1) == a.fastMinor(1,2,0,2));
assert (a.minorOf(0,2) == a.fastMinor(1,2,0,1));
assert (a.minorOf(1,0) == a.fastMinor(0,2,1,2));
assert (a.minorOf(1,1) == a.fastMinor(0,2,0,2));
assert (a.minorOf(1,2) == a.fastMinor(0,2,0,1));
assert (a.minorOf(2,0) == a.fastMinor(0,1,1,2));
assert (a.minorOf(2,1) == a.fastMinor(0,1,0,2));
assert (a.minorOf(2,2) == a.fastMinor(0,1,0,1));
}
// Determinants (by building a random singular value decomposition)
{
cout << "3x3 determinant" << endl;
IMATH_INTERNAL_NAMESPACE::Rand32 random;
IMATH_INTERNAL_NAMESPACE::M33f u;
IMATH_INTERNAL_NAMESPACE::M33f v;
IMATH_INTERNAL_NAMESPACE::M33f s;
u.setRotation( random.nextf() );
v.setRotation( random.nextf() );
s[0][0] = random.nextf();
s[1][1] = random.nextf();
s[2][2] = random.nextf();
IMATH_INTERNAL_NAMESPACE::M33f c = u * s * v.transpose();
assert (fabsf(c.determinant() - s[0][0]*s[1][1]*s[2][2]) <= u.baseTypeEpsilon());
}
{
IMATH_INTERNAL_NAMESPACE::Rand32 random;
IMATH_INTERNAL_NAMESPACE::M33d u;
IMATH_INTERNAL_NAMESPACE::M33d v;
IMATH_INTERNAL_NAMESPACE::M33d s;
u.setRotation( (double)random.nextf() );
v.setRotation( (double)random.nextf() );
s[0][0] = (double)random.nextf();
s[1][1] = (double)random.nextf();
s[2][2] = (double)random.nextf();
IMATH_INTERNAL_NAMESPACE::M33d c = u * s * v.transpose();
assert (fabs(c.determinant() - s[0][0]*s[1][1]*s[2][2]) <= u.baseTypeEpsilon());
}
// Outer product of two 3D vectors
{
cout << "Outer product of two 3D vectors" << endl;
IMATH_INTERNAL_NAMESPACE::V3f a(1,2,3);
IMATH_INTERNAL_NAMESPACE::V3f b(4,5,6);
IMATH_INTERNAL_NAMESPACE::M33f p = IMATH_INTERNAL_NAMESPACE::outerProduct(a,b);
for (int i=0; i<3; i++ )
{
for (int j=0; j<3; j++)
{
assert (p[i][j] == a[i]*b[j]);
}
}
}
{
IMATH_INTERNAL_NAMESPACE::V3d a(1,2,3);
IMATH_INTERNAL_NAMESPACE::V3d b(4,5,6);
IMATH_INTERNAL_NAMESPACE::M33d p = IMATH_INTERNAL_NAMESPACE::outerProduct(a,b);
for (int i=0; i<3; i++ )
{
for (int j=0; j<3; j++)
{
assert (p[i][j] == a[i]*b[j]);
}
}
}
// Determinants (by building a random singular value decomposition)
{
cout << "4x4 determinants" << endl;
IMATH_INTERNAL_NAMESPACE::Rand32 random;
IMATH_INTERNAL_NAMESPACE::M44f u = IMATH_INTERNAL_NAMESPACE::rotationMatrix
( IMATH_INTERNAL_NAMESPACE::V3f(random.nextf(),random.nextf(),random.nextf()).normalize(),
IMATH_INTERNAL_NAMESPACE::V3f(random.nextf(),random.nextf(),random.nextf()).normalize() );
IMATH_INTERNAL_NAMESPACE::M44f v = IMATH_INTERNAL_NAMESPACE::rotationMatrix
( IMATH_INTERNAL_NAMESPACE::V3f(random.nextf(),random.nextf(),random.nextf()).normalize(),
IMATH_INTERNAL_NAMESPACE::V3f(random.nextf(),random.nextf(),random.nextf()).normalize() );
IMATH_INTERNAL_NAMESPACE::M44f s;
s[0][0] = random.nextf();
s[1][1] = random.nextf();
s[2][2] = random.nextf();
s[3][3] = random.nextf();
IMATH_INTERNAL_NAMESPACE::M44f c = u * s * v.transpose();
assert (fabsf(c.determinant() - s[0][0]*s[1][1]*s[2][2]*s[3][3]) <= u.baseTypeEpsilon());
}
{
IMATH_INTERNAL_NAMESPACE::Rand32 random;
IMATH_INTERNAL_NAMESPACE::M44d u = IMATH_INTERNAL_NAMESPACE::rotationMatrix
( IMATH_INTERNAL_NAMESPACE::V3d(random.nextf(),random.nextf(),random.nextf()).normalize(),
IMATH_INTERNAL_NAMESPACE::V3d(random.nextf(),random.nextf(),random.nextf()).normalize() );
IMATH_INTERNAL_NAMESPACE::M44d v = IMATH_INTERNAL_NAMESPACE::rotationMatrix
( IMATH_INTERNAL_NAMESPACE::V3d(random.nextf(),random.nextf(),random.nextf()).normalize(),
IMATH_INTERNAL_NAMESPACE::V3d(random.nextf(),random.nextf(),random.nextf()).normalize() );
IMATH_INTERNAL_NAMESPACE::M44d s;
s[0][0] = random.nextf();
s[1][1] = random.nextf();
s[2][2] = random.nextf();
s[3][3] = random.nextf();
IMATH_INTERNAL_NAMESPACE::M44d c = u * s * v.transpose();
assert (fabs(c.determinant() - s[0][0]*s[1][1]*s[2][2]*s[3][3]) <= u.baseTypeEpsilon());
}
// Matrix minors
{
cout << "4x4 matrix minors" << endl;
IMATH_INTERNAL_NAMESPACE::M44d a(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
assert (a.minorOf(0,0) == a.fastMinor(1,2,3,1,2,3));
assert (a.minorOf(0,1) == a.fastMinor(1,2,3,0,2,3));
assert (a.minorOf(0,2) == a.fastMinor(1,2,3,0,1,3));
assert (a.minorOf(0,3) == a.fastMinor(1,2,3,0,1,2));
assert (a.minorOf(1,0) == a.fastMinor(0,2,3,1,2,3));
assert (a.minorOf(1,1) == a.fastMinor(0,2,3,0,2,3));
assert (a.minorOf(1,2) == a.fastMinor(0,2,3,0,1,3));
assert (a.minorOf(1,3) == a.fastMinor(0,2,3,0,1,2));
assert (a.minorOf(2,0) == a.fastMinor(0,1,3,1,2,3));
assert (a.minorOf(2,1) == a.fastMinor(0,1,3,0,2,3));
assert (a.minorOf(2,2) == a.fastMinor(0,1,3,0,1,3));
assert (a.minorOf(2,3) == a.fastMinor(0,1,3,0,1,2));
assert (a.minorOf(3,0) == a.fastMinor(0,1,2,1,2,3));
assert (a.minorOf(3,1) == a.fastMinor(0,1,2,0,2,3));
assert (a.minorOf(3,2) == a.fastMinor(0,1,2,0,1,3));
assert (a.minorOf(3,3) == a.fastMinor(0,1,2,0,1,2));
}
{
IMATH_INTERNAL_NAMESPACE::M44f a(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
assert (a.minorOf(0,0) == a.fastMinor(1,2,3,1,2,3));
assert (a.minorOf(0,1) == a.fastMinor(1,2,3,0,2,3));
assert (a.minorOf(0,2) == a.fastMinor(1,2,3,0,1,3));
assert (a.minorOf(0,3) == a.fastMinor(1,2,3,0,1,2));
assert (a.minorOf(1,0) == a.fastMinor(0,2,3,1,2,3));
assert (a.minorOf(1,1) == a.fastMinor(0,2,3,0,2,3));
assert (a.minorOf(1,2) == a.fastMinor(0,2,3,0,1,3));
assert (a.minorOf(1,3) == a.fastMinor(0,2,3,0,1,2));
assert (a.minorOf(2,0) == a.fastMinor(0,1,3,1,2,3));
assert (a.minorOf(2,1) == a.fastMinor(0,1,3,0,2,3));
assert (a.minorOf(2,2) == a.fastMinor(0,1,3,0,1,3));
assert (a.minorOf(2,3) == a.fastMinor(0,1,3,0,1,2));
assert (a.minorOf(3,0) == a.fastMinor(0,1,2,1,2,3));
assert (a.minorOf(3,1) == a.fastMinor(0,1,2,0,2,3));
assert (a.minorOf(3,2) == a.fastMinor(0,1,2,0,1,3));
assert (a.minorOf(3,3) == a.fastMinor(0,1,2,0,1,2));
}
// VC 2005 64 bits compiler has a bug with __restrict keword.
// Pointers with __restrict should not alias the same symbol.
// But, with optimization on, VC removes intermediate temp variable
// and ignores __restrict.
{
cout << "M44 multiplicaftion test" << endl;
IMATH_INTERNAL_NAMESPACE::M44f M ( 1.0f, 2.0f, 3.0f, 4.0f,
5.0f, 6.0f, 7.0f, 8.0f,
9.0f, 10.0f, 11.0f, 12.0f,
13.0f, 14.0f, 15.0f, 16.0f);
IMATH_INTERNAL_NAMESPACE::M44f N; N.makeIdentity();
// N should be equal to M
// This typical test fails
// when __restrict is used for pointers in "multiply" function.
N = N * M;
assert(N == M);
if (N != M) {
cout << "M44 multiplication test has failed, error." << endl
<< "M" << endl << M << endl
<< "N" << endl << N << endl;
}
}
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testMatrix ();

View File

@@ -0,0 +1,341 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testMiscMatrixAlgo.h>
#include "ImathMatrixAlgo.h"
#include "ImathRandom.h"
#include <iostream>
#include <exception>
#include <stdio.h>
#include <assert.h>
#if 0
#define debug(x) (printf x, fflush (stdout))
#else
#define debug(x)
#endif
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
float rad (float deg) {return deg * (M_PI / 180);}
void
testComputeLocalFrame ()
{
float eps = 0.00005;
Rand48 random(0);
for (int i = 0; i < 100000; ++i)
{
debug (("iteration: %d\n", i));
// Random pos
V3f p (random.nextf (-10, 10),
random.nextf (-10, 10),
random.nextf (-10, 10));
// Random xDir
V3f xDir (random.nextf (-10, 10),
random.nextf (-10, 10),
random.nextf (-10, 10));
// Random normalDir
V3f normalDir (random.nextf (-10, 10),
random.nextf (-10, 10),
random.nextf (-10, 10));
// Run computeLocalFrame we want to test
M44f L = computeLocalFrame(p, xDir, normalDir);
// test position
for (int j=0; j<3; j++)
{
if ( abs(L[3][j] - p[j])>eps )
assert(false);
}
if (abs (L[3][3] - 1.0)>eps)
assert(false );
// check that xAxis has the same dir as xDir and that is is normalized
V3f x( L[0][0], L[0][1], L[0][2]);
assert( (x%xDir).length() < eps );
if (abs (L[0][3])>eps)
assert(false);
assert((abs(x.length()-1.f)<eps));
// Check that y is normal to x and to normalDir, and is normalized
V3f y( L[1][0], L[1][1], L[1][2]);
if (abs (L[1][3])>eps)
assert(false );
assert(abs(x^y)<eps);
/*std::cout<<y<<"\n";
std::cout<<normalDir<<"\n";
std::cout<<(y^normalDir)<<"\n";*/
assert(abs(y^normalDir)<eps);
assert((abs(y.length()-1.f)<eps));
// check that z is normalized, normal to x and y, and direct
V3f z( L[2][0], L[2][1], L[2][2]);
if (abs (L[2][3])>eps)
assert(false );
assert((abs(z.length()-1.f)<eps));
assert(abs(x^z)<eps);
assert(abs(y^z)<eps);
assert(((x%y)^z)>0);
}
}
void
getRandTRS(Rand48& random, V3f& trans, V3f& rot, V3f& scale)
{
// Translate
trans = V3f (random.nextf (-10, 10),
random.nextf (-10, 10),
random.nextf (-10, 10));
// Rotate
rot = V3f (rad (random.nextf (-180, 180)),
rad (random.nextf (-180, 180)),
rad (random.nextf (-180, 180)));
// Scale
V3f s(random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0));
for (int j=0; j < 3; j++)
if (random.nextf (0.0, 1.0) >= 0.5)
s[j] *= -1;
scale = s;
}
M44f
createRandomMat(Rand48& random, V3f& trans, V3f& rot, V3f& scale)
{
M44f M;
V3f t, r, s;
getRandTRS(random, t, r, s);
M.translate (t);
M.rotate (r);
// Shear M.
V3f h (random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0),
random.nextf (0.000001, 2.0));
for (int j=0; j < 3; j++)
if (random.nextf (0.0, 1.0) >= 0.5)
h[j] *= -1;
M.shear (h);
M.scale (s);
//
// Add a small random error to the elements of M
//
for (int j = 0; j < 4; ++j)
for (int k = 0; k < 3; ++k)
M[j][k] += random.nextf (-1e-7, 1e-7);
V3f sh;
extractSHRT (M, scale, sh, rot, trans);
debug (("Scale : %f %f %f\n", s[0], s[1], s[2]));
debug (("Shear : %f %f %f\n", h[0], h[1], h[2]));
debug (("Rot : %f %f %f\n", r[0], r[1], r[2]));
debug (("Trans : %f %f %f\n", t[0], t[1], t[2]));
return M;
}
void
compareMat(M44f& M, M44f& N)
{
float eps = 0.0001;
/// Verify that the entries in M and N do not
// differ too much.
M44f D (M - N);
for (int j = 0; j < 4; ++j)
{
for (int k = 0; k < 4; ++k)
{
//cout << "diff="<<D[j][k] << endl;
if (abs (D[j][k]) > eps)
{
cout << "unexpectedly diff "<<
D[j][k] << endl;
cout << j << " " << k << endl;
cout << "M\n" << M << endl;
cout << "N\n" << N << endl;
cout << "D\n" << D << endl;
assert (false);
}
}
}
}
void
testAddOffset()
{
Rand48 random(0);
for (int i = 0; i < 100000; ++i)
{
debug (("iteration: %d\n", i));
V3f transA, transB, rotA, rotB, scaleA, scaleB;
V3f tOffset, rOffset, sOffset;
M44f inMat = createRandomMat(random, transA, rotA, scaleA);
M44f refMat = createRandomMat(random, transB, rotB, scaleB);
getRandTRS(random, tOffset, rOffset, sOffset);
// addOffset : function to test
M44f outMat = addOffset( inMat, tOffset, rOffset, sOffset, refMat);
// add the inverse offset
M44f invO;
invO.rotate (V3f(rad(rOffset[0]), rad(rOffset[1]), rad(rOffset[2])));
invO[3][0] = tOffset[0];
invO[3][1] = tOffset[1];
invO[3][2] = tOffset[2];
invO.invert();
M44f invS;
invS.scale (sOffset);
invS.invert(); // zero scale is avoided in getRandTRS
// in ref mat from the function result
M44f outInRefMat = invO*invS*outMat;
// in ref mat from the inputs
M44f inRefMat = inMat*refMat;
// compare the mat
compareMat(outInRefMat, inRefMat);
}
}
void
testRSMatrix(M44f& M, V3f& t, V3f& r, V3f& s)
{
M44f N;
N.makeIdentity();
N.translate (t); // ... matrix compositions
N.rotate (r);
N.scale (s);
compareMat(M, N);
}
void
testComputeRSMatrix ()
{
Rand48 random(0);
for (int i = 0; i < 100000; ++i)
{
debug (("iteration: %d\n", i));
V3f transA, transB, rotA, rotB, scaleA, scaleB;
M44f A = createRandomMat(random, transA, rotA, scaleA);
M44f B = createRandomMat(random, transB, rotB, scaleB);
M44f ArAsA = computeRSMatrix( true, true, A, B);
M44f ArBsB = computeRSMatrix( false, false, A, B);
M44f ArAsB = computeRSMatrix( true, false, A, B);
M44f ArBsA = computeRSMatrix( false, true, A, B);
testRSMatrix(ArAsA, transA, rotA, scaleA);
testRSMatrix(ArBsB, transA, rotB, scaleB);
testRSMatrix(ArAsB, transA, rotA, scaleB);
testRSMatrix(ArBsA, transA, rotB, scaleA);
debug (("\n"));
}
}
} // namespace
void
testMiscMatrixAlgo ()
{
try
{
cout << "Testing misc functions in ImathMatrixAlgo.h" << endl;
cout << "Testing the building of an orthonormal direct frame from : a position, "
<< "an x axis direction and a normal to the y axis" << endl;
cout << "IMATH_INTERNAL_NAMESPACE::computeLocalFrame()" << endl;
testComputeLocalFrame ();
cout << "ok\n" << endl;
cout << "Add a translate/rotate/scale offset to an input frame "
<< "and put it in another frame of reference" << endl;
cout << "IMATH_INTERNAL_NAMESPACE::addOffset()" << endl;
testAddOffset ();
cout << "ok\n" << endl;
cout << "Compute Translate/Rotate/Scale matrix from matrix A "<<endl;
cout << "with the Rotate/Scale of Matrix B"<< endl;
cout << "IMATH_INTERNAL_NAMESPACE::computeRSMatrix()" << endl;
testComputeRSMatrix ();
cout << "ok\n" << endl;
}
catch (std::exception &e)
{
cerr << " Caught exception: " << e.what () << endl;
}
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2009, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testMiscMatrixAlgo ();

View File

@@ -0,0 +1,404 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include "ImathMatrixAlgo.h"
#include "ImathRandom.h"
#include "ImathEuler.h"
#include <iostream>
#include <assert.h>
#include <cmath>
#include <vector>
#include <limits>
// Verify that if our transformation is already orthogonal, procrustes doesn't
// change that:
template <typename T>
void
testTranslationRotationMatrix (const IMATH_INTERNAL_NAMESPACE::M44d& mat)
{
std::cout << "Testing known translate/rotate matrix:\n " << mat;
typedef IMATH_INTERNAL_NAMESPACE::Vec3<T> Vec;
static IMATH_INTERNAL_NAMESPACE::Rand48 rand (2047);
size_t numPoints = 7;
std::vector<Vec> from; from.reserve (numPoints);
std::vector<Vec> to; to.reserve (numPoints);
for (size_t i = 0; i < numPoints; ++i)
{
IMATH_INTERNAL_NAMESPACE::V3d a (rand.nextf(), rand.nextf(), rand.nextf());
IMATH_INTERNAL_NAMESPACE::V3d b = a * mat;
from.push_back (Vec(a));
to.push_back (Vec(b));
}
std::vector<T> weights (numPoints, T(1));
const IMATH_INTERNAL_NAMESPACE::M44d m1 = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], numPoints);
const IMATH_INTERNAL_NAMESPACE::M44d m2 = procrustesRotationAndTranslation (&from[0], &to[0], numPoints);
const T eps = sizeof(T) == 8 ? 1e-8 : 1e-4;
for (size_t i = 0; i < numPoints; ++i)
{
const IMATH_INTERNAL_NAMESPACE::V3d a = from[i];
const IMATH_INTERNAL_NAMESPACE::V3d b = to[i];
const IMATH_INTERNAL_NAMESPACE::V3d b1 = a * m1;
const IMATH_INTERNAL_NAMESPACE::V3d b2 = a * m2;
assert ((b - b1).length() < eps);
assert ((b - b2).length() < eps);
}
std::cout << " OK\n";
}
// Test that if we pass in a matrix that we know consists only of translates,
// rotates, and uniform scale that we get an exact match.
template <typename T>
void testWithTranslateRotateAndScale (const IMATH_INTERNAL_NAMESPACE::M44d& m)
{
std::cout << "Testing with known translate/rotate/scale matrix\n" << m;
IMATH_INTERNAL_NAMESPACE::Rand48 rand(5376);
typedef IMATH_INTERNAL_NAMESPACE::Vec3<T> V3;
std::vector<V3> from;
std::vector<T> weights;
const float eps = 1e-4;
std::cout << "numPoints: " << std::flush;
for (size_t numPoints = 1; numPoints < 10; ++numPoints)
{
from.push_back (V3(rand.nextf(), rand.nextf(), rand.nextf()));
weights.push_back (rand.nextf());
std::cout << from.size() << " ";
std::vector<V3> to;
for (size_t i = 0; i < from.size(); ++i)
to.push_back (from[i] * m);
// weighted:
IMATH_INTERNAL_NAMESPACE::M44d res = IMATH_INTERNAL_NAMESPACE::procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], from.size(), true);
for (size_t i = 0; i < from.size(); ++i)
assert ((from[i] * res - to[i]).length() < eps);
// unweighted:
res = IMATH_INTERNAL_NAMESPACE::procrustesRotationAndTranslation (&from[0], &to[0], from.size(), true);
for (size_t i = 0; i < from.size(); ++i)
assert ((from[i] * res - to[i]).length() < eps);
}
std::cout << " OK\n";
}
template <typename T>
double
procrustesError (const IMATH_INTERNAL_NAMESPACE::Vec3<T>* from,
const IMATH_INTERNAL_NAMESPACE::Vec3<T>* to,
const T* weights,
const size_t n,
const IMATH_INTERNAL_NAMESPACE::M44d& xform)
{
double result = 0.0;
double residual = 0.0;
for (size_t i = 0; i < n; ++i)
{
IMATH_INTERNAL_NAMESPACE::V3d xformed = IMATH_INTERNAL_NAMESPACE::V3d(from[i]) * xform;
IMATH_INTERNAL_NAMESPACE::V3d diff = xformed - IMATH_INTERNAL_NAMESPACE::V3d(to[i]);
const double w = weights[i];
const double mag = w * diff.length2();
// Use Kahan summation for the heck of it:
const double y = mag - residual;
const double t = result + y;
residual = (t - result) - y;
result = t;
}
return result;
}
template <typename T>
void
verifyProcrustes (const std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> >& from,
const std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> >& to)
{
typedef IMATH_INTERNAL_NAMESPACE::Vec3<T> V3;
const T eps = std::sqrt(std::numeric_limits<T>::epsilon());
const size_t n = from.size();
// Validate that passing in uniform weights gives the same answer as
// passing in no weights:
std::vector<T> weights (from.size());
for (size_t i = 0; i < weights.size(); ++i)
weights[i] = 1;
IMATH_INTERNAL_NAMESPACE::M44d m1 = procrustesRotationAndTranslation (&from[0], &to[0], n);
IMATH_INTERNAL_NAMESPACE::M44d m2 = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], n);
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
assert (std::abs(m1[i][j] - m2[i][j]) < eps);
// Now try the weighted version:
for (size_t i = 0; i < weights.size(); ++i)
weights[i] = i+1;
IMATH_INTERNAL_NAMESPACE::M44d m = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], n);
// with scale:
IMATH_INTERNAL_NAMESPACE::M44d ms = procrustesRotationAndTranslation (&from[0], &to[0], &weights[0], n, true);
// Verify that it's orthonormal w/ positive determinant.
const T det = m.determinant();
assert (std::abs(det - T(1)) < eps);
// Verify orthonormal:
IMATH_INTERNAL_NAMESPACE::M33d upperLeft;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
upperLeft[i][j] = m[i][j];
IMATH_INTERNAL_NAMESPACE::M33d product = upperLeft * upperLeft.transposed();
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
const double expected = (i == j ? 1.0 : 0.0);
assert (std::abs(product[i][j] - expected) < eps);
}
}
// Verify that nearby transforms are worse:
const size_t numTries = 10;
IMATH_INTERNAL_NAMESPACE::Rand48 rand (1056);
const double delta = 1e-3;
for (size_t i = 0; i < numTries; ++i)
{
// Construct an orthogonal rotation matrix using Euler angles:
IMATH_INTERNAL_NAMESPACE::Eulerd diffRot (delta * rand.nextf(), delta * rand.nextf(), delta * rand.nextf());
assert (procrustesError (&from[0], &to[0], &weights[0], n, m * diffRot.toMatrix44()) >
procrustesError (&from[0], &to[0], &weights[0], n, m));
// Try a small translation:
IMATH_INTERNAL_NAMESPACE::V3d diffTrans (delta * rand.nextf(), delta * rand.nextf(), delta * rand.nextf());
IMATH_INTERNAL_NAMESPACE::M44d translateMatrix;
translateMatrix.translate (diffTrans);
assert (procrustesError (&from[0], &to[0], &weights[0], n, m * translateMatrix) >
procrustesError (&from[0], &to[0], &weights[0], n, m));
}
// Try a small scale:
IMATH_INTERNAL_NAMESPACE::M44d newMat = ms;
const double scaleDiff = delta;
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
newMat[i][j] = ms[i][j] * (1.0 + scaleDiff);
assert (procrustesError (&from[0], &to[0], &weights[0], n, newMat) >
procrustesError (&from[0], &to[0], &weights[0], n, ms));
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
newMat[i][j] = ms[i][j] * (1.0 - scaleDiff);
assert (procrustesError (&from[0], &to[0], &weights[0], n, newMat) >
procrustesError (&from[0], &to[0], &weights[0], n, ms));
//
// Verify the magical property that makes shape springs work:
// when the displacements Q*A-B, times the weights,
// are applied as forces at B,
// there is zero net force and zero net torque.
//
{
IMATH_INTERNAL_NAMESPACE::V3d center (0, 0, 0);
IMATH_INTERNAL_NAMESPACE::V3d netForce(0);
IMATH_INTERNAL_NAMESPACE::V3d netTorque(0);
for (int iPoint = 0; iPoint < n; ++iPoint)
{
const IMATH_INTERNAL_NAMESPACE::V3d force = weights[iPoint] * (from[iPoint]*m - to[iPoint]);
netForce += force;
netTorque += to[iPoint].cross (force);
}
assert (netForce.length2() < eps);
assert (netTorque.length2() < eps);
}
}
template <typename T>
void
testProcrustesWithMatrix (const IMATH_INTERNAL_NAMESPACE::M44d& m)
{
std::cout << "Testing Procrustes algorithm with arbitrary matrix: \n" << m;
std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > fromPoints;
std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > toPoints;
IMATH_INTERNAL_NAMESPACE::Rand48 random (1209);
std::cout << " numPoints: ";
for (size_t numPoints = 1; numPoints < 10; ++numPoints)
{
std::cout << numPoints << " " << std::flush;
fromPoints.clear(); toPoints.clear();
for (size_t i = 0; i < numPoints; ++i)
{
const IMATH_INTERNAL_NAMESPACE::V3d fromPt (random.nextf(), random.nextf(), random.nextf());
const IMATH_INTERNAL_NAMESPACE::V3d toPt = fromPt * m;
fromPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(fromPt));
toPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(toPt));
}
verifyProcrustes (fromPoints, toPoints);
}
std::cout << "OK\n";
}
template <typename T>
void
testProcrustesImp ()
{
// Test the empty case:
IMATH_INTERNAL_NAMESPACE::M44d id =
procrustesRotationAndTranslation ((IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0,
(IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0,
(T*) 0,
0);
assert (id == IMATH_INTERNAL_NAMESPACE::M44d());
id = procrustesRotationAndTranslation ((IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0,
(IMATH_INTERNAL_NAMESPACE::Vec3<T>*) 0,
0);
assert (id == IMATH_INTERNAL_NAMESPACE::M44d());
// First we'll test with a bunch of known translation/rotation matrices
// to make sure we get back exactly the same points:
IMATH_INTERNAL_NAMESPACE::M44d m;
m.makeIdentity();
testTranslationRotationMatrix<T> (m);
m.translate (IMATH_INTERNAL_NAMESPACE::V3d(3.0, 5.0, -0.2));
testTranslationRotationMatrix<T> (m);
m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(M_PI, 0, 0));
testTranslationRotationMatrix<T> (m);
m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, M_PI/4.0, 0));
testTranslationRotationMatrix<T> (m);
m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, 0, -3.0/4.0 * M_PI));
testTranslationRotationMatrix<T> (m);
m.makeIdentity();
testWithTranslateRotateAndScale<T> (m);
m.translate (IMATH_INTERNAL_NAMESPACE::V3d(0.4, 6.0, 10.0));
testWithTranslateRotateAndScale<T> (m);
m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(M_PI, 0, 0));
testWithTranslateRotateAndScale<T> (m);
m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, M_PI/4.0, 0));
testWithTranslateRotateAndScale<T> (m);
m.rotate (IMATH_INTERNAL_NAMESPACE::V3d(0, 0, -3.0/4.0 * M_PI));
testWithTranslateRotateAndScale<T> (m);
m.scale (IMATH_INTERNAL_NAMESPACE::V3d(2.0, 2.0, 2.0));
testWithTranslateRotateAndScale<T> (m);
m.scale (IMATH_INTERNAL_NAMESPACE::V3d(0.01, 0.01, 0.01));
testWithTranslateRotateAndScale<T> (m);
// Now we'll test with some random point sets and verify
// the various Procrustes properties:
std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > fromPoints;
std::vector<IMATH_INTERNAL_NAMESPACE::Vec3<T> > toPoints;
fromPoints.clear(); toPoints.clear();
for (size_t i = 0; i < 4; ++i)
{
const T theta = T(2*i) / T(M_PI);
fromPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(cos(theta), sin(theta), 0));
toPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(cos(theta + M_PI/3.0), sin(theta + M_PI/3.0), 0));
}
verifyProcrustes (fromPoints, toPoints);
IMATH_INTERNAL_NAMESPACE::Rand48 random (1209);
for (size_t numPoints = 1; numPoints < 10; ++numPoints)
{
fromPoints.clear(); toPoints.clear();
for (size_t i = 0; i < numPoints; ++i)
{
fromPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(random.nextf(), random.nextf(), random.nextf()));
toPoints.push_back (IMATH_INTERNAL_NAMESPACE::Vec3<T>(random.nextf(), random.nextf(), random.nextf()));
}
}
verifyProcrustes (fromPoints, toPoints);
// Test with some known matrices of varying degrees of quality:
testProcrustesWithMatrix<T> (m);
m.translate (IMATH_INTERNAL_NAMESPACE::Vec3<T>(3, 4, 1));
testProcrustesWithMatrix<T> (m);
m.translate (IMATH_INTERNAL_NAMESPACE::Vec3<T>(-10, 2, 1));
testProcrustesWithMatrix<T> (m);
IMATH_INTERNAL_NAMESPACE::Eulerd rot (M_PI/3.0, 3.0*M_PI/4.0, 0);
m = m * rot.toMatrix44();
testProcrustesWithMatrix<T> (m);
m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(1.5, 6.4, 2.0));
testProcrustesWithMatrix<T> (m);
IMATH_INTERNAL_NAMESPACE::Eulerd rot2 (1.0, M_PI, M_PI/3.0);
m = m * rot.toMatrix44();
m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(-1, 1, 1));
testProcrustesWithMatrix<T> (m);
m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(1, 0.001, 1));
testProcrustesWithMatrix<T> (m);
m.scale (IMATH_INTERNAL_NAMESPACE::Vec3<T>(1, 1, 0));
testProcrustesWithMatrix<T> (m);
}
void
testProcrustes ()
{
std::cout << "Testing Procrustes algorithms in single precision..." << std::endl;
testProcrustesImp<float>();
std::cout << "Testing Procrustes algorithms in double precision..." << std::endl;
testProcrustesImp<double>();
}

View File

@@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testProcrustes ();

View File

@@ -0,0 +1,272 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testQuat.h>
#include "ImathQuat.h"
#include "ImathMatrixAlgo.h"
#include "ImathFun.h"
#include "ImathLimits.h"
#include "ImathPlatform.h" /* [i_a] M_PI_2 */
#include <iostream>
#include <cassert>
#include <cmath>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
template <class T>
void
testQuatT ()
{
const T s = limits<T>::smallest();
const T e = 4 * limits<T>::epsilon();
//
// constructors, r(), v()
//
{
Quat<T> q = Quat<T>();
assert (q.r == 1 && q.v == Vec3<T> (0, 0, 0));
q = Quat<T> (2, 3, 4, 5);
assert (q.r == 2 && q.v == Vec3<T> (3, 4, 5));
q = Quat<T> (6, Vec3<T> (7, 8, 9));
assert (q.r == 6 && q.v == Vec3<T> (7, 8, 9));
Quat<T> q1 = Quat<T> (q);
assert (q1.r == 6 && q1.v == Vec3<T> (7, 8, 9));
}
//
// invert(), inverse()
//
{
Quat<T> q = Quat<T> (1, 0, 0, 1);
assert (q.inverse() == Quat<T> (0.5, 0, 0, -0.5));
q.invert();
assert (q == Quat<T> (0.5, 0, 0, -0.5));
}
//
// normalize(), normalized()
//
{
Quat<T> q = Quat<T> (2, Vec3<T> (0, 0, 0));
assert (q.normalized() == Quat<T> (1, 0, 0, 0));
q.normalize();
assert (q == Quat<T> (1, 0, 0, 0));
q = Quat<T> (0, Vec3<T> (0, 2, 0));
assert (q.normalized() == Quat<T> (0, 0, 1, 0));
q.normalize();
assert (q == Quat<T> (0, 0, 1, 0));
}
//
// length()
//
{
Quat<T> q = Quat<T> (3, 0, 4, 0);
assert (q.length() == 5);
}
//
// setAxisAngle(), angle(), axis()
//
{
Quat<T> q;
q.setAxisAngle (Vec3<T> (0, 0, 1), M_PI_2);
Vec3<T> v = q.axis();
T a = q.angle();
assert (v.equalWithAbsError (Vec3<T> (0, 0, 1), e));
assert (IMATH_INTERNAL_NAMESPACE::equal (a, T (M_PI_2), e));
}
//
// Accuracy of angle() for very small angles
// and when real part is slightly greater than 1.
//
{
T t = 10 * Math<T>::sqrt (s);
Quat<T> q;
q.setAxisAngle (Vec3<T> (0, 0, 1), t);
Vec3<T> v = q.axis();
T a = q.angle();
assert (v.equalWithAbsError (Vec3<T> (0, 0, 1), e));
assert (IMATH_INTERNAL_NAMESPACE::equal (a, t, t * e));
q.r *= 1.1;
q.v *= 1.1;
v = q.axis();
a = q.angle();
assert (v.equalWithAbsError (Vec3<T> (0, 0, 1), e));
assert (IMATH_INTERNAL_NAMESPACE::equal (a, t, t * e));
}
{
T t = 0.001 * Math<T>::sqrt (s);
Quat<T> q;
q.setAxisAngle (Vec3<T> (0, 0, 1), t);
Vec3<T> v = q.axis();
T a = q.angle();
assert (v.equalWithAbsError (Vec3<T> (0, 0, 1), e));
assert (IMATH_INTERNAL_NAMESPACE::equal (a, t, t * e));
q.r *= 1.1;
q.v *= 1.1;
v = q.axis();
a = q.angle();
assert (v.equalWithAbsError (Vec3<T> (0, 0, 1), e));
assert (IMATH_INTERNAL_NAMESPACE::equal (a, t, t * e));
}
//
// toMatrix33(), toMatrix44()
//
{
Quat<T> q;
q.setRotation (Vec3<T> (1, 0, 0), Vec3<T> (0, 1, 0));
Matrix33<T> m1 = q.toMatrix33();
assert (m1.equalWithAbsError (Matrix33<T> (0, 1, 0,
-1, 0, 0,
0, 0, 1),
e));
Matrix44<T> m2 = q.toMatrix44();
assert (m2.equalWithAbsError (Matrix44<T> (0, 1, 0, 0,
-1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1),
e));
}
//
// +, - (unary and binary), ~ *, /, ^
//
assert (Quat<T> (1, 2, 3, 4) + Quat<T> (5, 6, 7, 8) ==
Quat<T> (6, 8, 10, 12));
assert (Quat<T> (-1, -2, -3, -4) - Quat<T> (5, 6, 7, 8) ==
Quat<T> (-6, -8, -10, -12));
assert (-Quat<T> (1, 2, 3, 4) == Quat<T> (-1, -2, -3, -4));
assert (~Quat<T> (1, 2, 3, 4) == Quat<T> (1, -2, -3, -4));
assert (T (2) * Quat<T> (1, 2, 3, 4) == Quat<T> (2, 4, 6, 8));
assert (Quat<T> (1, 2, 3, 4) * T (2 )== Quat<T> (2, 4, 6, 8));
assert (Quat<T> (1, 0, 0, 1) * Quat<T> (1, 1, 0, 0) ==
Quat<T> (1, 1, 1, 1));
assert (Quat<T> (1, 1, 0, 0) * Quat<T> (1, 0, 0, 1) ==
Quat<T> (1, 1, -1, 1));
assert (Quat<T> (1, 0, 0, 1) / Quat<T> (0.5, -0.5, 0, 0) ==
Quat<T> (1, 1, 1, 1));
assert (Quat<T> (2, 4, 6, 8) / T (2) == Quat<T> (1, 2, 3, 4));
assert ((Quat<T> (1, 2, 3, 4) ^ Quat<T> (2, 2, 2, 2)) == 20);
//
// extract()
//
{
Vec3<T> vFrom (1, 0, 0);
Vec3<T> vTo (0, 1, 1);
Matrix44<T> m1 = rotationMatrix (vFrom, vTo);
Quat<T> q = extractQuat (m1);;
Matrix44<T> m2 = q.toMatrix44();
assert (m2.equalWithAbsError (m1, 2 * e));
}
}
void
testQuatConversions ()
{
{
Quatf q (1, V3f (2, 3, 4));
Quatd q1 = Quatd (q);
assert (q1.r == 1 && q1.v == V3d (2, 3, 4));
}
{
Quatd q (1, V3d (2, 3, 4));
Quatf q1 = Quatf (q);
assert (q1.r == 1 && q1.v == V3f (2, 3, 4));
}
}
} // namespace
void
testQuat ()
{
cout << "Testing basic quaternion operations" << endl;
testQuatT<float>();
testQuatT<double>();
testQuatConversions();
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testQuat ();

View File

@@ -0,0 +1,203 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testQuatSetRotation.h>
#include "ImathQuat.h"
#include "ImathRandom.h"
#include <iostream>
#include <assert.h>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
void
testRotation (const V3f &from, const V3f &to)
{
//
// Build a quaternion.
//
Quatf Q;
Q.setRotation (from, to);
M44f M = Q.toMatrix44();
//
// Verify that the quaternion rotates vector from into vector to.
//
float e = 20 * limits<float>::epsilon();
V3f fromM = from * M;
V3f fromQ = from * Q;
V3f t0 = to.normalized();
V3f fM0 = fromM.normalized();
V3f fQ0 = fromQ.normalized();
assert (t0.equalWithAbsError (fM0, e));
assert (t0.equalWithAbsError (fQ0, e));
//
// Verify that the rotation axis is the cross product of from and to.
//
V3f f0 = from.normalized();
if (abs (f0 ^ t0) < 0.9)
{
V3f n0 = (from % to).normalized();
V3f n0M = n0 * M;
assert (n0.equalWithAbsError (n0M, e));
}
}
void
specificVectors ()
{
cout << " exact 90-degree rotations" << endl;
testRotation (V3f (1, 0, 0), V3f (0, 1, 0));
testRotation (V3f (1, 0, 0), V3f (0, 0, 1));
testRotation (V3f (0, 1, 0), V3f (1, 0, 0));
testRotation (V3f (0, 1, 0), V3f (0, 0, 1));
testRotation (V3f (0, 0, 1), V3f (1, 0, 0));
testRotation (V3f (0, 0, 1), V3f (0, 1, 0));
cout << " exact zero-degree rotations" << endl;
testRotation (V3f (1, 0, 0), V3f (1, 0, 0));
testRotation (V3f (0, 1, 0), V3f (0, 1, 0));
testRotation (V3f (0, 0, 1), V3f (0, 0, 1));
testRotation (V3f (1, 2, 3), V3f (2, 4, 6));
cout << " exact 180-degree rotations" << endl;
testRotation (V3f (1, 0, 0), V3f (-1, 0, 0));
testRotation (V3f (0, 1, 0), V3f (0, -1, 0));
testRotation (V3f (0, 0, 1), V3f (0, 0, -1));
testRotation (V3f (1, 2, 3), V3f (-2, -4, -6));
testRotation (V3f (1, 3, 2), V3f (-2, -6, -4));
testRotation (V3f (2, 1, 3), V3f (-4, -2, -6));
testRotation (V3f (3, 1, 2), V3f (-6, -2, -4));
testRotation (V3f (2, 3, 1), V3f (-4, -6, -2));
testRotation (V3f (3, 2, 1), V3f (-6, -4, -2));
cout << " other angles" << endl;
testRotation (V3f (1, 2, 3), V3f (4, 5, 6));
testRotation (V3f (1, 2, 3), V3f (4, 6, 5));
testRotation (V3f (1, 2, 3), V3f (5, 4, 6));
testRotation (V3f (1, 2, 3), V3f (6, 4, 5));
testRotation (V3f (1, 2, 3), V3f (5, 6, 4));
testRotation (V3f (1, 2, 3), V3f (6, 5, 4));
testRotation (V3f (1, 2, 3), V3f (-4, -5, -6));
testRotation (V3f (1, 2, 3), V3f (-4, -6, -5));
testRotation (V3f (1, 2, 3), V3f (-5, -4, -6));
testRotation (V3f (1, 2, 3), V3f (-6, -4, -5));
testRotation (V3f (1, 2, 3), V3f (-5, -6, -4));
testRotation (V3f (1, 2, 3), V3f (-6, -5, -4));
}
void
randomVectors ()
{
cout << " random from and to vectors" << endl;
Rand48 rand (17);
for (int i = 0; i < 500000; ++i)
{
V3f from = hollowSphereRand<V3f> (rand) * rand.nextf (0.1, 10.0);
V3f to = hollowSphereRand<V3f> (rand) * rand.nextf (0.1, 10.0);
testRotation (from, to);
}
}
void
nearlyEqualVectors ()
{
cout << " nearly equal from and to vectors" << endl;
Rand48 rand (19);
float e = 100 * limits<float>::epsilon();
for (int i = 0; i < 500000; ++i)
{
V3f from = hollowSphereRand<V3f> (rand);
V3f to = from + e * hollowSphereRand<V3f> (rand);
testRotation (from, to);
}
}
void
nearlyOppositeVectors ()
{
cout << " nearly opposite from and to vectors" << endl;
Rand48 rand (19);
float e = 100 * limits<float>::epsilon();
for (int i = 0; i < 500000; ++i)
{
V3f from = hollowSphereRand<V3f> (rand);
V3f to = -from + e * hollowSphereRand<V3f> (rand);
testRotation (from, to);
}
}
} // namespace
void
testQuatSetRotation ()
{
cout << "Testing quaternion rotations" << endl;
specificVectors();
randomVectors();
nearlyEqualVectors();
nearlyOppositeVectors();
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,37 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testQuatSetRotation ();

View File

@@ -0,0 +1,200 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testQuatSlerp.h>
#include "ImathQuat.h"
#include "ImathRandom.h"
#include <iostream>
#include <math.h>
#include <assert.h>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
void
compareQuats (const Quatf &q1, const Quatf &q2, float e)
{
assert (equalWithAbsError (q1.v.x, q2.v.x, e));
assert (equalWithAbsError (q1.v.y, q2.v.y, e));
assert (equalWithAbsError (q1.v.z, q2.v.z, e));
assert (equalWithAbsError (q1.r, q2.r, e));
}
Quatd
pow (const Quatd q, int n)
{
Quatd result;
for (int i = 0; i < n; ++i)
result *= q;
return result;
}
void
testSlerp (const Quatf q1, const Quatf q2, int m, int n)
{
//
// For two quaternions, q1 and q2, and the identity quaternion, qi,
//
// slerp (q1, q2, f) == q1 * slerp (qi, q1.inverse() * q2, f); (1)
//
// In addition, for integers m and n, with m >= 0, n > 0,
//
// pow (slerp (qi, q3, m/n), n) == pow (q3, m) (2)
//
// This allows us to test if slerp (q1, q2, m/n) works correctly.
// Thanks to Dan Piponi for pointing this out.
//
// Note that e2, our upper bound for the numerical error in (2) is
// fairly large. The reason for this is that testSlerp() will be
// called with m and n up to 16. Taking quaternions to the 16th
// power amplifies any inaccuracies.
//
Quatf qi;
Quatf q3 = q1.inverse() * q2;
Quatf q1q2 = slerp (q1, q2, float (m) / float (n));
Quatf qiq3 = slerp (qi, q3, float (m) / float (n));
float e1 = 60 * limits<float>::epsilon();
float e2 = 600 * limits<float>::epsilon();
compareQuats (q1q2, q1 * qiq3, e1);
compareQuats (pow (qiq3, n), pow (q3, m), e2);
}
void
testSlerp (const Quatf q1, const Quatf q2)
{
const int n = 16;
for (int m = 0; m <= n; ++m)
testSlerp (q1, q2, m, n);
}
void
specificRotations ()
{
cout << " combinations of 90-degree rotations around x, y and z" << endl;
for (int x1 = 0; x1 < 3; ++x1)
{
V3f axis1 (0, 0, 0);
axis1[x1] = 1;
for (int n1 = 0; n1 < 4; ++n1)
{
float angle1 = n1 * M_PI / 2;
Quatf q1;
q1.setAxisAngle (axis1, angle1);
for (int x2 = 0; x2 < 3; ++x2)
{
V3f axis2 (0, 0, 0);
axis2[x2] = 1;
for (int n2 = 0; n2 < 4; ++n2)
{
float angle2 = n2 * M_PI / 2;
Quatf q2;
q2.setAxisAngle (axis2, angle2);
testSlerp (q1, q2);
testSlerp (-q1, -q2);
if ((q1 ^ q2) < 0.99)
{
testSlerp (q1, -q2);
testSlerp (-q1, q2);
}
}
}
}
}
}
void
randomRotations ()
{
cout << " random rotations" << endl;
Rand48 rand (53);
for (int i = 0; i < 10000; ++i)
{
V3f axis1 = hollowSphereRand<V3f> (rand);
V3f axis2 = hollowSphereRand<V3f> (rand);
float angle1 = rand.nextf (0, M_PI);
float angle2 = rand.nextf (0, M_PI);
Quatf q1, q2;
q1.setAxisAngle (axis1, angle1);
q2.setAxisAngle (axis2, angle2);
testSlerp (q1, q2);
testSlerp (-q1, -q2);
if ((q1 ^ q2) < 0.99)
{
testSlerp (q1, -q2);
testSlerp (-q1, q2);
}
}
}
} // namespace
void
testQuatSlerp ()
{
cout << "Testing quaternion spherical linear interpolation" << endl;
specificRotations();
randomRotations();
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testQuatSlerp ();

View File

@@ -0,0 +1,256 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testRandom.h>
#include "ImathRandom.h"
#include "ImathVec.h"
#include "ImathFun.h"
#include <iostream>
#include <iomanip>
#include <assert.h>
using namespace std;
using IMATH_INTERNAL_NAMESPACE::abs;
namespace {
void
testErand48 ()
{
//
// Our implementation of erand48(), nrand48(), etc.
// assumes that sizeof (unsigned short) == 2.
//
assert (sizeof (unsigned short) == 2);
//
// starting with a given seed, erand48() and nrand48()
// must generate the same sequence as the standard
// Unix/Linux functions.
//
unsigned short state[3];
state[0] = 0;
state[1] = 1;
state[2] = 2;
assert (abs (IMATH_INTERNAL_NAMESPACE::erand48 (state) - 0.671004) < 0.00001);
assert (abs (IMATH_INTERNAL_NAMESPACE::erand48 (state) - 0.786905) < 0.00001);
assert (abs (IMATH_INTERNAL_NAMESPACE::erand48 (state) - 0.316850) < 0.00001);
assert (abs (IMATH_INTERNAL_NAMESPACE::erand48 (state) - 0.384870) < 0.00001);
assert (abs (IMATH_INTERNAL_NAMESPACE::erand48 (state) - 0.854650) < 0.00001);
assert (IMATH_INTERNAL_NAMESPACE::nrand48 (state) == 0x4f4e8cb0);
assert (IMATH_INTERNAL_NAMESPACE::nrand48 (state) == 0x063e864b);
assert (IMATH_INTERNAL_NAMESPACE::nrand48 (state) == 0x2d10f1dd);
assert (IMATH_INTERNAL_NAMESPACE::nrand48 (state) == 0x1aadc122);
assert (IMATH_INTERNAL_NAMESPACE::nrand48 (state) == 0x1836a71f);
assert (state[0] == 0x2a42);
assert (state[1] == 0x4e3e);
assert (state[2] == 0x306d);
}
template <class Rand>
void
testGenerator ()
{
//
// Test if the values, and the differences between
// successive values, are evenly distributed.
//
const int N = 10;
const int M = 100000;
int values[N + 1];
int diffs[2 * N + 3];
int *v = &values[0];
int *d = &diffs[N + 2];
for (int i = 0; i <= N; ++i)
v[i] = 0;
for (int i = -N; i <= N; ++i)
d[i] = 0;
Rand rand (0);
float previous = 0;
for (int i = 0; i < M * N; ++i)
{
float r = rand.nextf (0.0, 1.0);
float diff = r - previous;
previous = r;
v[int (r * N)] += 1;
d[IMATH_INTERNAL_NAMESPACE::floor (diff * N + 0.5)] += 1;
}
cout << " values" << endl;
for (int i = 0; i < N; ++i)
{
// cout << setw (4) << i << ' ' << setw(6) << v[i] << ' ';
assert (abs (v[i] - M) < 0.01 * M);
// for (int j = 0; j < v[i] * 60 / M; ++j)
// cout << '*';
// cout << endl;
}
assert (v[N] == 0);
cout << " differences between successive values" << endl;
for (int i = -N; i <= N; ++i)
{
// cout << setw (4) << i << ' ' << setw (6) << d[i] << ' ';
assert (abs ((N - abs (i)) * M / N - d[i]) < 0.05 * M);
// for (int j = 0; j < d[i] * 60 / M; ++j)
// cout << '*';
// cout << endl;
}
cout << " range" << endl;
double rMin = 1.0;
double rMax = 0.0;
for (int i = 0; i <= 10000000; ++i)
{
double r = rand.nextf (0.0, 1.0);
if (rMin > r)
rMin = r;
if (rMax < r)
rMax = r;
}
assert (rMin < 0.0001 && rMax > 0.9999);
const double pow_2_60 = double (1073741824) * double (1073741824);
for (int i = 0; i <= 10000000; ++i)
{
double r0 = rand.nextf (-2.0, 3.0);
assert (r0 >= -2.0 && r0 <= 3.0);
double r1 = rand.nextf (-pow_2_60, 1);
assert (r1 >= -pow_2_60 && r1 <= 1);
double r2 = rand.nextf (-1, pow_2_60);
assert (r2 >= -1 && r2 <= pow_2_60);
}
}
template <class Rand>
void
testSolidSphere ()
{
const int N = 10;
const int M = 10000;
int v[N + 1];
for (int i = 0; i <= N; ++i)
v[i] = 0;
Rand rand (0);
for (int i = 0; i < M * N; ++i)
{
IMATH_INTERNAL_NAMESPACE::V3f p = IMATH_INTERNAL_NAMESPACE::solidSphereRand<IMATH_INTERNAL_NAMESPACE::V3f> (rand);
float l = p.length();
v[IMATH_INTERNAL_NAMESPACE::floor (l * N)] += 1;
assert (l < 1.00001);
}
for (int i = 0; i < N; ++i)
assert (v[i] > 0);
}
template <class Rand>
void
testHollowSphere ()
{
const int M = 100000;
Rand rand (0);
for (int i = 0; i < M; ++i)
{
IMATH_INTERNAL_NAMESPACE::V3f p = IMATH_INTERNAL_NAMESPACE::hollowSphereRand<IMATH_INTERNAL_NAMESPACE::V3f> (rand);
float l = p.length();
assert (abs (l - 1) < 0.00001);
}
}
} // namespace
void
testRandom ()
{
cout << "Testing random number generators" << endl;
cout << "erand48(), nrand48()" << endl;
testErand48();
cout << "Rand32" << endl;
testGenerator<IMATH_INTERNAL_NAMESPACE::Rand32>();
cout << "Rand48" << endl;
testGenerator<IMATH_INTERNAL_NAMESPACE::Rand48>();
cout << "solidSphereRand()" << endl;
testSolidSphere<IMATH_INTERNAL_NAMESPACE::Rand32>();
cout << "hollowSphereRand()" << endl;
testHollowSphere<IMATH_INTERNAL_NAMESPACE::Rand32>();
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testRandom ();

View File

@@ -0,0 +1,260 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testRoots.h>
#include "ImathRoots.h"
#include "ImathFun.h"
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <assert.h>
using namespace std;
void
sort (int nx, double &x0, double &x1, double &x2)
{
if (nx == 2)
{
if (x0 > x1)
swap (x0, x1);
}
if (nx == 3)
{
if (x0 > x1)
swap (x0, x1);
if (x1 > x2)
swap (x1, x2);
if (x0 > x1)
swap (x0, x1);
}
}
void
sort (int nx, double x[])
{
if (nx == 2)
{
if (x[0] > x[1])
swap (x[0], x[1]);
}
if (nx == 3)
{
if (x[0] > x[1])
swap (x[0], x[1]);
if (x[1] > x[2])
swap (x[1], x[2]);
if (x[0] > x[1])
swap (x[0], x[1]);
}
}
void
solve (double a, double b, double c, double d, // coefficients
int nx, // number of expected solutions
double x0, double x1, double x2) // expected solutions
{
cout << "coefficients: " <<
setw(3) << a << ' ' <<
setw(3) << b << ' ' <<
setw(3) << c << ' ' <<
setw(3) << d << ' ';
//
// Solve the equation a*x^3 + b*x^2 + c*x +d
//
double x[3];
int n = IMATH_INTERNAL_NAMESPACE::solveCubic (a, b, c, d, x);
//
// Sort the numerical solutions.
// Sorte the expected solutions.
//
sort (nx, x0, x1, x2);
sort (n, x);
//
// Compare the numerical and the expected solutions.
//
assert (n == nx);
cout << " solutions: ";
if (n == -1)
cout << "[-inf, inf]";
if (n == 0)
cout << "none";
const double e = 0.0000001; // maximum expected error for
// the test cases listed below
if (n >= 1)
{
cout << x[0];
assert (IMATH_INTERNAL_NAMESPACE::equal (x[0], x0, e));
}
if (n >= 2)
{
cout << ' ' << x[1];
assert (IMATH_INTERNAL_NAMESPACE::equal (x[1], x1, e));
}
if (n >= 3)
{
cout << ' ' << x[2];
assert (IMATH_INTERNAL_NAMESPACE::equal (x[2], x2, e));
}
cout << endl;
}
void
solve (double a, double b, double c, // coefficients
int nx, // number of expected solutions
double x0, double x1) // expected solutions
{
cout << "coefficients: " <<
setw(3) << a << ' ' <<
setw(3) << b << ' ' <<
setw(3) << c << ' ';
//
// Solve the equation a*x^2 + b*x^1 + c*x
//
double x[2];
int n = IMATH_INTERNAL_NAMESPACE::solveQuadratic (a, b, c, x);
//
// Sort the numerical solutions.
// Sort the expected solutions.
//
// Dummy variable for sort
double x2;
sort (nx, x0, x1, x2);
sort (n, x);
//
// Compare the numerical and the expected solutions.
//
assert (n == nx);
cout << " solutions: ";
if (n == -1)
cout << "[-inf, inf]";
if (n == 0)
cout << "none";
const double e = 0.0000001; // maximum expected error for
// the test cases listed below
if (n >= 1)
{
cout << x[0];
assert (IMATH_INTERNAL_NAMESPACE::equal (x[0], x0, e));
}
if (n >= 2)
{
cout << ' ' << x[1];
assert (IMATH_INTERNAL_NAMESPACE::equal (x[1], x1, e));
}
cout << endl;
}
void
testRoots ()
{
cout << "Testing functions in ImathRoots.h" << endl;
cout << endl << "solveCubic" << endl;
// Solve cubiec equations
//
// coefficients number of expected solutions
// | |
// | | expected solutions
// | | |
// +-------+--------+ | +------+-----+
// | | | | |
solve (1, 6, 11, 6, 3, -1, -2, -3); // real solutions: -1, -2, -3
solve (2, 2, -20, 16, 3, 1, -4, 2); // real solutions: 1, -4, 2
solve (3, -3, 1, -1, 1, 1, 0, 0); // real solutions: 1
solve (2, 0, -24, -32, 2, 4, -2, 0); // real solutions: 4, -2
solve (1, 0, 0, 0, 1, 0, 0, 0); // real solutions: 0
solve (8, -24, 24, -8, 1, 1, 0, 0); // real solutions: 1
solve (0, 2, -10, 12, 2, 2, 3, 0); // real solutions: 2, 3
solve (0, 1, -1, -20, 2, 5, -4, 0); // real solutions: 5, -4
solve (0, 3, -12, 12, 1, 2, 0, 0); // real solutions: 2
solve (0, 1, 0, 0, 1, 0, 0, 0); // real solutions: 0
solve (0, 1, 0, 1, 0, 0, 0, 0); // real solutions: none
solve (0, 0, 3, -6, 1, 2, 0, 0); // real solutions: 2
solve (0, 0, 5, 15, 1, -3, 0, 0); // real solutions: -3
solve (0, 0, 1, 0, 1, 0, 0, 0); // real solutions: 0
solve (0, 0, 0, 1, 0, 0, 0, 0); // real solutions: none
solve (0, 0, 0, 0, -1, 0, 0, 0); // real solutions: [-inf, inf]
cout << endl << "solveQuadratic" << endl;
// Solve quadratic equations
//
// coefficients number of expected solutions
// | |
// | | expected solutions
// | | |
// +-----+-----+ | +---+---+
// | | | | |
solve (1, 3, 2, 2, -1, -2); // real solutions: -1, -2
solve (1, 0, -9, 2, -3, 3); // real solutions: -3, 3
solve (1, -4, 0, 2, 4, 0); // real solutions: 0, 4
solve (2, -4, 2, 1, 1, 0); // real solutions: 1
solve (0, -4, 8, 1, 2, 0); // real solutions: 2
solve (0, 7, 0, 1, 0, 0); // real solutions: 0
solve (10, 0, 0, 1, 0, 0); // real solutions: 0
solve (0, 0, 0, -1, 0, 0); // real solutions: [-inf, inf]
solve (0, 0, 1, 0, 0, 0); // real solutions: none
solve (3, -6, 30, 0, 0, 0); // real solutions: none
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testRoots ();

View File

@@ -0,0 +1,208 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testShear.h>
#include "ImathShear.h"
#include "ImathLimits.h"
#include "ImathMath.h"
#include <iostream>
#include <assert.h>
using namespace std;
void
testShear ()
{
cout << "Testing functions in ImathShear.h" << endl;
cout << "Imath::Shear6 constructors" << endl;
const float epsilon = IMATH_INTERNAL_NAMESPACE::limits< float >::epsilon();
float array[6] = { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F };
IMATH_INTERNAL_NAMESPACE::Shear6f testConstructor1;
IMATH_INTERNAL_NAMESPACE::Shear6f testConstructor2( testConstructor1 );
testConstructor1 = testConstructor2;
IMATH_INTERNAL_NAMESPACE::Shear6f testConstructor3( 52, 128, 254, 127, 12, -20 );
IMATH_INTERNAL_NAMESPACE::Shear6f A( testConstructor3 );
IMATH_INTERNAL_NAMESPACE::Shear6f B = A;
IMATH_INTERNAL_NAMESPACE::Shear6f X, Y, tmp;
assert ( A == B );
cout << "Imath::Shear6 * f" << endl;
assert ( ( IMATH_INTERNAL_NAMESPACE::Shear6f( 0.330f, 0.710f, 0.010f,
0.999f, -0.531f, -0.012f ) * 0.999f ) ==
IMATH_INTERNAL_NAMESPACE::Shear6f( 0.330f * 0.999f,
0.710f * 0.999f,
0.010f * 0.999f,
0.999f * 0.999f,
-0.531f * 0.999f,
-0.012f * 0.999f ) );
cout << "Imath::Shear6 / f" << endl;
assert ( ( IMATH_INTERNAL_NAMESPACE::Shear6f( 0.330f, 0.710f, 0.010f,
0.999f, -0.531f, -0.012f ) / 0.999f ) ==
IMATH_INTERNAL_NAMESPACE::Shear6f( 0.330f / 0.999f,
0.710f / 0.999f,
0.010f / 0.999f,
0.999f / 0.999f,
-0.531f / 0.999f,
-0.012f / 0.999f ) );
cout << "Assignment and comparison" << endl;
B = A;
assert( B == A );
assert( !( B != A ) );
X = Y = IMATH_INTERNAL_NAMESPACE::Shear6f( 0.123f, -0.420f, 0.501f,
0.998f, -0.231f, -0.034f );
X *= 0.001f;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.xy * 0.001f ) - X.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.xz * 0.001f ) - X.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.yz * 0.001f ) - X.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.yx * 0.001f ) - X.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.zx * 0.001f ) - X.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.zy * 0.001f ) - X.zy ) <= epsilon );
X = Y = IMATH_INTERNAL_NAMESPACE::Shear6f( 0.123f, -0.420f, 0.501f,
0.998f, -0.231f, -0.034f );
X /= -1.001f;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.xy / -1.001f ) - X.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.xz / -1.001f ) - X.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.yz / -1.001f ) - X.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.yx / -1.001f ) - X.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.zx / -1.001f ) - X.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( Y.zy / -1.001f ) - X.zy ) <= epsilon );
Y = IMATH_INTERNAL_NAMESPACE::Shear6f( 0.998f, -0.001f, 0.501f, 1.001f, -0.231f, -0.034f );
X = IMATH_INTERNAL_NAMESPACE::Shear6f( 0.011f, -0.420f, -0.501f, 0.998f, -0.231f, -0.034f );
tmp = X + Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy + Y.xy ) - tmp.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz + Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz + Y.yz ) - tmp.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx + Y.yx ) - tmp.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx + Y.zx ) - tmp.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy + Y.zy ) - tmp.zy ) <= epsilon );
tmp = X - Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy - Y.xy ) - tmp.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz - Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz - Y.yz ) - tmp.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx - Y.yx ) - tmp.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx - Y.zx ) - tmp.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy - Y.zy ) - tmp.zy ) <= epsilon );
tmp = X * Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy * Y.xy ) - tmp.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz * Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz * Y.yz ) - tmp.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx * Y.yx ) - tmp.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx * Y.zx ) - tmp.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy * Y.zy ) - tmp.zy ) <= epsilon );
tmp = X / Y;
//
// epsilon doesn't work here.
//
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy / Y.xy ) - tmp.xy ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz / Y.xz ) - tmp.xz ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz / Y.yz ) - tmp.yz ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx / Y.yx ) - tmp.yx ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx / Y.zx ) - tmp.zx ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy / Y.zy ) - tmp.zy ) <= 1e-5f );
tmp = X;
tmp += Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy + Y.xy ) - tmp.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz + Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz + Y.yz ) - tmp.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx + Y.yx ) - tmp.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx + Y.zx ) - tmp.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy + Y.zy ) - tmp.zy ) <= epsilon );
tmp = X;
tmp -= Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy - Y.xy ) - tmp.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz - Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz - Y.yz ) - tmp.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx - Y.yx ) - tmp.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz - Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz - Y.yz ) - tmp.yz ) <= epsilon );
tmp = X;
tmp *= Y;
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy * Y.xy ) - tmp.xy ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz * Y.xz ) - tmp.xz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz * Y.yz ) - tmp.yz ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx * Y.yx ) - tmp.yx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx * Y.zx ) - tmp.zx ) <= epsilon &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy * Y.zy ) - tmp.zy ) <= epsilon );
tmp = X;
tmp /= Y;
//
// epsilon doesn't work here.
//
assert( IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xy / Y.xy ) - tmp.xy ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.xz / Y.xz ) - tmp.xz ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yz / Y.yz ) - tmp.yz ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.yx / Y.yx ) - tmp.yx ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zx / Y.zx ) - tmp.zx ) <= 1e-5f &&
IMATH_INTERNAL_NAMESPACE::Math<float>::fabs( ( X.zy / Y.zy ) - tmp.zy ) <= 1e-5f );
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testShear ();

View File

@@ -0,0 +1,360 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include "ImathMatrixAlgo.h"
#include <iostream>
#include <assert.h>
#include <cmath>
#include <limits>
#include <algorithm>
template <typename T>
void
verifyOrthonormal (const IMATH_INTERNAL_NAMESPACE::Matrix33<T>& A)
{
const T valueEps = T(100) * std::numeric_limits<T>::epsilon();
const IMATH_INTERNAL_NAMESPACE::Matrix33<T> prod = A * A.transposed();
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
if (i == j)
assert (std::abs (prod[i][j] - 1) < valueEps);
else
assert (std::abs (prod[i][j]) < valueEps);
}
}
}
template <typename T>
void
verifyOrthonormal (const IMATH_INTERNAL_NAMESPACE::Matrix44<T>& A)
{
const T valueEps = T(100) * std::numeric_limits<T>::epsilon();
const IMATH_INTERNAL_NAMESPACE::Matrix44<T> prod = A * A.transposed();
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 4; ++j)
{
if (i == j)
assert (std::abs (prod[i][j] - 1) <= valueEps);
else
assert (std::abs (prod[i][j]) <= valueEps);
}
}
}
template <typename T>
void
verifyTinySVD_3x3 (const IMATH_INTERNAL_NAMESPACE::Matrix33<T>& A)
{
T maxEntry = 0;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
maxEntry = std::max (maxEntry, std::abs (A[i][j]));
const T eps = std::numeric_limits<T>::epsilon();
const T valueEps = maxEntry * T(10) * eps;
for (int i = 0; i < 2; ++i)
{
const bool posDet = (i == 0);
IMATH_INTERNAL_NAMESPACE::Matrix33<T> U, V;
IMATH_INTERNAL_NAMESPACE::Vec3<T> S;
IMATH_INTERNAL_NAMESPACE::jacobiSVD (A, U, S, V, eps, posDet);
IMATH_INTERNAL_NAMESPACE::Matrix33<T> S_times_Vt;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
S_times_Vt[i][j] = S[j] * V[i][j];
S_times_Vt.transpose();
// Verify that the product of the matrices is A:
const IMATH_INTERNAL_NAMESPACE::Matrix33<T> product = U * S_times_Vt;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
assert (std::abs (product[i][j] - A[i][j]) <= valueEps);
// Verify that U and V are orthogonal:
if (posDet)
{
assert (U.determinant() > 0.9);
assert (V.determinant() > 0.9);
}
// Verify that the singular values are sorted:
for (int i = 0; i < 2; ++i)
assert (S[i] >= S[i+1]);
// Verify that all the SVs except maybe the last one are positive:
for (int i = 0; i < 2; ++i)
assert (S[i] >= T(0));
if (!posDet)
assert (S[2] >= T(0));
verifyOrthonormal (U);
verifyOrthonormal (V);
}
}
template <typename T>
void
verifyTinySVD_4x4 (const IMATH_INTERNAL_NAMESPACE::Matrix44<T>& A)
{
T maxEntry = 0;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
maxEntry = std::max (maxEntry, std::abs (A[i][j]));
const T eps = std::numeric_limits<T>::epsilon();
const T valueEps = maxEntry * T(100) * eps;
for (int i = 0; i < 2; ++i)
{
const bool posDet = (i == 0);
IMATH_INTERNAL_NAMESPACE::Matrix44<T> U, V;
IMATH_INTERNAL_NAMESPACE::Vec4<T> S;
IMATH_INTERNAL_NAMESPACE::jacobiSVD (A, U, S, V, eps, posDet);
IMATH_INTERNAL_NAMESPACE::Matrix44<T> S_times_Vt;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
S_times_Vt[i][j] = S[j] * V[i][j];
S_times_Vt.transpose();
// Verify that the product of the matrices is A:
const IMATH_INTERNAL_NAMESPACE::Matrix44<T> product = U * S_times_Vt;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
assert (std::abs (product[i][j] - A[i][j]) <= valueEps);
// Verify that U and V have positive determinant if requested:
if (posDet)
{
assert (U.determinant() > 0.99);
assert (V.determinant() > 0.99);
}
// Verify that the singular values are sorted:
for (int i = 0; i < 3; ++i)
assert (S[i] >= S[i+1]);
// Verify that all the SVs except maybe the last one are positive:
for (int i = 0; i < 3; ++i)
assert (S[i] >= T(0));
if (!posDet)
assert (S[3] >= T(0));
verifyOrthonormal (U);
verifyOrthonormal (V);
}
}
template <typename T>
void
testTinySVD_3x3 (const IMATH_INTERNAL_NAMESPACE::Matrix33<T>& A)
{
std::cout << "Verifying SVD for [[" << A[0][0] << ", " << A[0][1] << ", " << A[0][2] << "], "
<< "[" << A[1][0] << ", " << A[1][1] << ", " << A[1][2] << "], "
<< "[" << A[2][0] << ", " << A[2][1] << ", " << A[2][2] << "]]\n";
verifyTinySVD_3x3 (A);
verifyTinySVD_3x3 (A.transposed());
// Try all different orderings of the columns of A:
int cols[3] = { 0, 1, 2 };
do
{
IMATH_INTERNAL_NAMESPACE::Matrix33<T> B;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
B[i][j] = A[i][cols[j]];
verifyTinySVD_3x3 (B);
} while (std::next_permutation (cols, cols + 3));
}
template <typename T>
void
testTinySVD_3x3 (const T a, const T b, const T c,
const T d, const T e, const T f,
const T g, const T h, const T i)
{
const IMATH_INTERNAL_NAMESPACE::Matrix33<T> A (a, b, c, d, e, f, g, h, i);
testTinySVD_3x3 (A);
}
template <typename T>
void
testTinySVD_4x4 (const IMATH_INTERNAL_NAMESPACE::Matrix44<T>& A)
{
std::cout << "Verifying SVD for [[" << A[0][0] << ", " << A[0][1] << ", " << A[0][2] << ", " << A[0][3] << "], "
<< "[" << A[1][0] << ", " << A[1][1] << ", " << A[1][2] << ", " << A[1][3] << "], "
<< "[" << A[2][0] << ", " << A[2][1] << ", " << A[2][2] << ", " << A[2][3] << "], "
<< "[" << A[3][0] << ", " << A[3][1] << ", " << A[3][2] << ", " << A[3][3] << "]]\n";
verifyTinySVD_4x4 (A);
verifyTinySVD_4x4 (A.transposed());
// Try all different orderings of the columns of A:
int cols[4] = { 0, 1, 2, 3 };
do
{
IMATH_INTERNAL_NAMESPACE::Matrix44<T> B;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
B[i][j] = A[i][cols[j]];
verifyTinySVD_4x4 (B);
} while (std::next_permutation (cols, cols + 4));
}
template <typename T>
void
testTinySVD_4x4 (const T a, const T b, const T c, const T d,
const T e, const T f, const T g, const T h,
const T i, const T j, const T k, const T l,
const T m, const T n, const T o, const T p)
{
const IMATH_INTERNAL_NAMESPACE::Matrix44<T> A (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
testTinySVD_4x4 (A);
}
template <typename T>
void
testTinySVDImp()
{
// Try a bunch of 3x3 matrices:
testTinySVD_3x3<T> (1, 0, 0, 0, 1, 0, 0, 0, 1);
testTinySVD_3x3<T> (1, 0, 0, 0, -1, 0, 0, 0, 1);
testTinySVD_3x3<T> (0, 0, 0, 0, 0, 0, 0, 0, 0);
testTinySVD_3x3<T> (0, 0, 0, 0, 0, 0, 0, 0, 1);
testTinySVD_3x3<T> (1, 0, 0, 0, 1, 0, 0, 0, 0);
testTinySVD_3x3<T> (1, 0, 0, 0, 0, 0, 0, 0, 0);
testTinySVD_3x3<T> (1, 0, 0, 1e-10, 0, 0, 0, 0, 0);
testTinySVD_3x3<T> (1, 0, 0, 1e-10, 0, 0, 0, 0, 100000);
testTinySVD_3x3<T> (1, 2, 3, 4, 5, 6, 7, 8, 9);
testTinySVD_3x3<T> (1, 2, 3, 4, 5, 6, 7, 8, 9);
testTinySVD_3x3<T> (outerProduct (IMATH_INTERNAL_NAMESPACE::Vec3<T> (100, 1e-5, 0), IMATH_INTERNAL_NAMESPACE::Vec3<T> (100, 1e-5, 0)));
testTinySVD_3x3<T> (outerProduct (IMATH_INTERNAL_NAMESPACE::Vec3<T> (245, 20, 1), IMATH_INTERNAL_NAMESPACE::Vec3<T> (256, 300, 20)));
testTinySVD_3x3<T> (outerProduct (IMATH_INTERNAL_NAMESPACE::Vec3<T> (245, 20, 1), IMATH_INTERNAL_NAMESPACE::Vec3<T> (245, 20, 1)) +
outerProduct (IMATH_INTERNAL_NAMESPACE::Vec3<T> (1, 2, 3), IMATH_INTERNAL_NAMESPACE::Vec3<T> (1, 2, 3)));
// Some problematic matrices from SVDTest:
testTinySVD_3x3<T> (
0.0023588321752040036, -0.0096558131480729038, 0.0010959850449366493,
0.0088671829608044754, 0.0016771794267033666, -0.0043081475729438235,
0.003976050440932701, 0.0019880497026345716, 0.0089576046614601966);
testTinySVD_3x3<T> (
2.3588321752040035e-09, -9.6558131480729038e-09, 1.0959850449366498e-09,
8.8671829608044748e-09, 1.6771794267033661e-09, -4.3081475729438225e-09,
3.9760504409327016e-09, 1.9880497026345722e-09, 8.9576046614601957e-09);
testTinySVD_3x3<T> (
-0.46673855799602715, 0.67466260360310948, 0.97646986796448998,
-0.032460753747103721, 0.046584527749418278, 0.067431228641151142,
-0.088885055229687815, 0.1280389179308779, 0.18532617511453064);
testTinySVD_3x3<T> (
1e-8, 0, 0,
0, 1e-8, 0,
0, 0, 1e-8);
testTinySVD_3x3<T> (
1, 0, 0,
0, .00036, 0,
1e-18, 0, .00018);
testTinySVD_3x3<T> (
1.3, 0, 0,
0, .0003, 0,
1e-17, 0, 0);
testTinySVD_3x3<T> (
1, 0, 0,
0, 1e-2, 0,
0, 0, 1e-2);
testTinySVD_3x3<T> (
1,0,0,
0,1,0,
0,0,0);
testTinySVD_3x3<T> (
1, 0, 0,
0, 1e-3, 0,
0, 0, 1e-6);
testTinySVD_3x3<T> (
0.59588638570136332, -0.79761234126107794, -1,
0.39194500425202045, 0.91763115383440363, -0.341818175044664,
-0.45056075218951946, -0.71259057727425101, 0.47125008216720271);
testTinySVD_3x3<T> (
4.38805348e-09, -2.53189691e-09, -4.65678607e-09,
-3.23000099e-10, 1.86370294e-10, 3.42781192e-10,
-4.61572824e-09, 2.6632645e-09, 4.89840346e-09);
// problematic 2x2 one for lapack on suse (see below), padded with 0's
testTinySVD_3x3<T> (
0, -1.00000003e-22, 0,
1.00000001e-07, 0, 0,
0, 0, 0);
// problematic 2x2 one for lapack on suse (see below), padded with 0's and 1
testTinySVD_3x3<T> (
0, -1.00000003e-22, 0,
1.00000001e-07, 0, 0,
0, 0, 1);
// Now, 4x4 matrices:
testTinySVD_4x4<T> (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
testTinySVD_4x4<T> (1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
testTinySVD_4x4<T> (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0);
testTinySVD_4x4<T> (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
testTinySVD_4x4<T> (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
testTinySVD_4x4<T> (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
testTinySVD_4x4<T> (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
testTinySVD_4x4<T> (0, -1.00000003e-22, 0, 0, 00000001e-07, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
testTinySVD_4x4<T> (outerProduct (IMATH_INTERNAL_NAMESPACE::Vec4<T> (100, 1e-5, 0, 0), IMATH_INTERNAL_NAMESPACE::Vec4<T> (100, 1e-5, 0, 0)));
testTinySVD_4x4<T> (outerProduct (IMATH_INTERNAL_NAMESPACE::Vec4<T> (245, 20, 1, 0.5), IMATH_INTERNAL_NAMESPACE::Vec4<T> (256, 300, 20, 10)));
testTinySVD_4x4<T> (outerProduct (IMATH_INTERNAL_NAMESPACE::Vec4<T> (245, 20, 1, 0.5), IMATH_INTERNAL_NAMESPACE::Vec4<T> (256, 300, 20, 10)) +
outerProduct (IMATH_INTERNAL_NAMESPACE::Vec4<T> (30, 10, 10, 10), IMATH_INTERNAL_NAMESPACE::Vec4<T> (1, 2, 3, 3)));
}
void
testTinySVD ()
{
std::cout << "Testing TinySVD algorithms in single precision..." << std::endl;
testTinySVDImp<float>();
std::cout << "Testing TinySVD algorithms in double precision..." << std::endl;
testTinySVDImp<double>();
}

View File

@@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testTinySVD ();

View File

@@ -0,0 +1,287 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include <testVec.h>
#include "ImathVec.h"
#include "ImathFun.h"
#include "ImathLimits.h"
#include <iostream>
#include <cassert>
#include <cmath>
using namespace std;
using namespace IMATH_INTERNAL_NAMESPACE;
namespace {
template <class T>
void
testLength2T ()
{
const T s = Math<T>::sqrt (limits<T>::smallest());
const T e = 4 * limits<T>::epsilon();
Vec2<T> v;
v = Vec2<T> (0, 0);
assert (v.length() == 0);
assert (v.normalized().length() == 0);
v = Vec2<T> (3, 4);
assert (v.length() == 5);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (3000, 4000);
assert (v.length() == 5000);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
T t = s * (1 << 4);
v = Vec2<T> (t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (-t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * Math<T>::sqrt (2), t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
t = s / (1 << 4);
v = Vec2<T> (t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (-t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * Math<T>::sqrt (2), t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
t = s / (1 << 20);
v = Vec2<T> (t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec2<T> (-t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * Math<T>::sqrt (2), t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
}
template <class T>
void
testLength3T ()
{
const T s = Math<T>::sqrt (limits<T>::smallest());
const T e = 4 * limits<T>::epsilon();
Vec3<T> v;
v = Vec3<T> (0, 0, 0);
assert (v.length() == 0);
assert (v.normalized().length() == 0);
v = Vec3<T> (3, 4, 0);
assert (v.length() == 5);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (3000, 4000, 0);
assert (v.length() == 5000);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (1, -1, 1);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), 1 * Math<T>::sqrt (3), e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (1000, -1000, 1000);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), 1000 * Math<T>::sqrt (3), 1000 * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
T t = s * (1 << 4);
v = Vec3<T> (t, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (0, t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (0, 0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (-t, -t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * Math<T>::sqrt (3), t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
t = s / (1 << 4);
v = Vec3<T> (t, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (0, t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (0, 0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (-t, -t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * Math<T>::sqrt (3), t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
t = s / (1 << 20);
v = Vec3<T> (t, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (0, t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (0, 0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec3<T> (-t, -t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * Math<T>::sqrt (3), t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
}
template <class T>
void
testLength4T ()
{
const T s = Math<T>::sqrt (limits<T>::smallest());
const T e = 4 * limits<T>::epsilon();
Vec4<T> v;
v = Vec4<T> (0, 0, 0, 0);
assert (v.length() == 0);
assert (v.normalized().length() == 0);
v = Vec4<T> (3, 4, 0, 0);
assert (v.length() == 5);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (3000, 4000, 0, 0);
assert (v.length() == 5000);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (1, -1, 1, 1);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), 2, e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (1000, -1000, 1000, 1000);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), 2000, 1000 * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
T t = s * (1 << 4);
v = Vec4<T> (t, 0, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, t, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, 0, t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, 0, 0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (-t, -t, -t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * 2, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
t = s / (1 << 4);
v = Vec4<T> (t, 0, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, t, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, 0, t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, 0, 0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (-t, -t, -t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * 2, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
t = s / (1 << 20);
v = Vec4<T> (t, 0, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, t, 0, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, 0, t, 0);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (0, 0, 0, t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
v = Vec4<T> (-t, -t, -t, -t);
assert (IMATH_INTERNAL_NAMESPACE::equal (v.length(), t * 2, t * e));
assert (IMATH_INTERNAL_NAMESPACE::equal (v.normalized().length(), 1, e));
}
} // namespace
void
testVec ()
{
cout << "Testing some basic vector operations" << endl;
testLength2T<float>();
testLength2T<double>();
testLength3T<float>();
testLength3T<double>();
testLength4T<float>();
testLength4T<double>();
cout << "ok\n" << endl;
}

View File

@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
void testVec ();