diff --git a/Base/include/VectorBase.h b/Base/include/VectorBase.h index 3aa2232..50f9ef1 100644 --- a/Base/include/VectorBase.h +++ b/Base/include/VectorBase.h @@ -61,7 +61,7 @@ namespace FasTC { const T &operator[](int idx) const { return vec[idx]; } // Allow casts to the respective array representation... - operator T *() const { return vec; } + operator const T *() const { return vec; } VectorBase &operator=(const T *v) { for(int i = 0; i < N; i++) vec[i] = v[i]; @@ -71,7 +71,11 @@ namespace FasTC { // Allows casting to other vector types if the underlying type system does as well... template operator VectorBase<_T, N>() const { - return VectorBase<_T, N>(vec); + VectorBase<_T, N> ret; + for(int i = 0; i < N; i++) { + ret[i] = static_cast<_T>(vec[i]); + } + return ret; } // Vector operations diff --git a/Base/test/TestVector.cpp b/Base/test/TestVector.cpp index 9abd2e6..45c05a4 100644 --- a/Base/test/TestVector.cpp +++ b/Base/test/TestVector.cpp @@ -51,19 +51,20 @@ */ #include "gtest/gtest.h" -#include "TexCompTypes.h" #include "VectorBase.h" +static const float kEpsilon = 1e-6; + TEST(VectorBase, Constructors) { FasTC::VectorBase v3f; FasTC::VectorBase v1d; FasTC::VectorBase v7i; - FasTC::VectorBase v16u; + FasTC::VectorBase v16u; #define TEST_VECTOR_COPY_CONS(v, t, n) \ do { \ FasTC::VectorBase d##v (v); \ - for(uint32 i = 0; i < n; i++) { \ + for(int i = 0; i < n; i++) { \ EXPECT_EQ(d##v [i], v[i]); \ } \ } while(0) \ @@ -71,5 +72,146 @@ TEST(VectorBase, Constructors) { TEST_VECTOR_COPY_CONS(v3f, float, 3); TEST_VECTOR_COPY_CONS(v1d, double, 1); TEST_VECTOR_COPY_CONS(v7i, int, 7); - TEST_VECTOR_COPY_CONS(v16u, uint32, 16); + TEST_VECTOR_COPY_CONS(v16u, unsigned, 16); + +#undef TEST_VECTOR_COPY_CONS +} + +TEST(VectorBase, Accessors) { + FasTC::VectorBase v3f; + v3f[0] = 1.0f; + v3f[1] = -2.3f; + v3f[2] = 1000; + + for(int i = 0; i < 3; i++) { + EXPECT_EQ(v3f[i], v3f(i)); + } + + v3f(0) = -1.0f; + v3f(1) = 2.3f; + v3f(2) = -1000; + + for(int i = 0; i < 3; i++) { + EXPECT_EQ(v3f(i), v3f[i]); + } +} + +TEST(VectorBase, PointerConversion) { + FasTC::VectorBase v3f; + v3f[0] = 1.0f; + v3f[1] = -2.3f; + v3f[2] = 1000; + + float cmp[3] = { 1.0f, -2.3f, 1000 }; + const float *v3fp = v3f; + int result = memcmp(cmp, v3fp, 3 * sizeof(float)); + EXPECT_EQ(result, 0); + + cmp[0] = -1.0f; + cmp[1] = 2.3f; + cmp[2] = 1000.0f; + v3f = cmp; + for(int i = 0; i < 3; i++) { + EXPECT_EQ(v3f[i], cmp[i]); + } +} + +TEST(VectorBase, CastVector) { + FasTC::VectorBase v3f; + FasTC::VectorBase v3d = v3f; + FasTC::VectorBase v3i = v3f; + for(int i = 0; i < 3; i++) { + EXPECT_EQ(v3d(i), static_cast(v3f(i))); + EXPECT_EQ(v3i(i), static_cast(v3f(i))); + } +} + +TEST(VectorBase, DotProduct) { + int iv[5] = { -2, -1, 0, 1, 2 }; + FasTC::VectorBase v5i(iv); + + unsigned uv[5] = { 1, 2, 3, 4, 5 }; + FasTC::VectorBase v5u(uv); + + EXPECT_EQ(v5i.Dot(v5u), 10); + EXPECT_EQ(v5u.Dot(v5i), 10); +} + +TEST(VectorBase, Length) { + int iv[5] = { 1, 2, 3, 4, 5 }; + FasTC::VectorBase v5i (iv); + + EXPECT_EQ(v5i.LengthSq(), 55); + EXPECT_EQ(v5i.Length(), 7); + + float fv[6] = {1, 2, 3, 4, 5, 6}; + FasTC::VectorBase v6f (fv); + + EXPECT_EQ(v6f.LengthSq(), 91); + EXPECT_NEAR(v6f.Length(), sqrt(91.0f), kEpsilon); +} + +TEST(VectorBase, Normalization) { + float fv[2] = {1, 0}; + FasTC::VectorBase v2f (fv); + v2f.Normalize(); + EXPECT_EQ(v2f[0], 1); + EXPECT_EQ(v2f[1], 0); + + // Normalized vector should be sqrt(2) for each axis, although + // this can't be represented as integers... + unsigned uv[2] = {2, 2}; + FasTC::VectorBase v2u (uv); + v2u.Normalize(); + EXPECT_EQ(v2u[0], 1); + EXPECT_EQ(v2u[1], 1); + + const float sqrt2 = sqrt(2)/2.0f; + for(int i = 2; i < 10; i++) { + v2f[0] = static_cast(i); + v2f[1] = static_cast(i); + v2f.Normalize(); + EXPECT_NEAR(v2f[0], sqrt2, kEpsilon); + EXPECT_NEAR(v2f[1], sqrt2, kEpsilon); + } +} + +TEST(VectorBase, Scaling) { + float fv[2] = {1.0f, 3.0f}; + FasTC::VectorBase v2f (fv); + FasTC::VectorBase v2fd = v2f * 3.0f; + EXPECT_NEAR(v2fd[0], 3.0f, kEpsilon); + EXPECT_NEAR(v2fd[1], 9.0f, kEpsilon); + + v2fd = -1.0 * v2f; + EXPECT_NEAR(v2fd[0], -1.0f, kEpsilon); + EXPECT_NEAR(v2fd[1], -3.0f, kEpsilon); + + v2fd = v2f / 3; + EXPECT_NEAR(v2fd[0], 1.0f / 3.0f, kEpsilon); + EXPECT_NEAR(v2fd[1], 1.0f, kEpsilon); +} + +TEST(VectorBase, Addition) { + float fv[2] = {1.1f, 3.2f}; + FasTC::VectorBase v2f (fv); + + unsigned uv[2] = {5, 2}; + FasTC::VectorBase v2u (uv); + + FasTC::VectorBase au = v2u + v2f; + EXPECT_EQ(au[0], 6); + EXPECT_EQ(au[1], 5); + + FasTC::VectorBase af = v2f + v2u; + EXPECT_NEAR(af[0], 6.1f, kEpsilon); + EXPECT_NEAR(af[1], 5.2f, kEpsilon); + + au = v2u - v2f; + EXPECT_EQ(au[0], 3); + EXPECT_EQ(au[1], 0); + + af = v2f - v2u; + EXPECT_NEAR(af[0], -3.9f, kEpsilon); + EXPECT_NEAR(af[1], 1.2f, kEpsilon); }