From cb348c359832d9934e840e461c114f9c8427aa6b Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Thu, 3 Oct 2013 17:19:28 -0400 Subject: [PATCH 01/13] Reappropriate vexlib math headers into FasTC. --- Base/include/Matrix3x3.h | 47 ++++ Base/include/MatrixBase.h | 191 ++++++++++++++++ Base/include/MatrixSquare.h | 46 ++++ Base/include/Vector2.h | 80 +++++++ Base/include/Vector3.h | 124 +++++++++++ Base/include/Vector4.h | 420 ++++++++++++++++++++++++++++++++++++ Base/include/VectorBase.h | 171 +++++++++++++++ 7 files changed, 1079 insertions(+) create mode 100644 Base/include/Matrix3x3.h create mode 100644 Base/include/MatrixBase.h create mode 100644 Base/include/MatrixSquare.h create mode 100644 Base/include/Vector2.h create mode 100644 Base/include/Vector3.h create mode 100644 Base/include/Vector4.h create mode 100644 Base/include/VectorBase.h diff --git a/Base/include/Matrix3x3.h b/Base/include/Matrix3x3.h new file mode 100644 index 0000000..b5d226b --- /dev/null +++ b/Base/include/Matrix3x3.h @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_MATRIX3X3_H_ +#define BASE_INCLUDE_MATRIX3X3_H_ + +#include "MatrixSquare.h" + +namespace FasTC { + + template + class Matrix3x3 : public MatrixSquare { + + public: + + // Constructors + Matrix3x3() { } + Matrix3x3(const MatrixSquare &other) { + for(int i = 0; i < kNumElements; i++) { + mat[i] = other[i]; + } + } + }; +}; + +#endif // BASE_INCLUDE_MATRIX3X3_H_ diff --git a/Base/include/MatrixBase.h b/Base/include/MatrixBase.h new file mode 100644 index 0000000..3182b4b --- /dev/null +++ b/Base/include/MatrixBase.h @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_MATRIXBASE_H__ +#define BASE_INCLUDE_MATRIXBASE_H__ + +#include "VectorBase.h" + +namespace FasTC { + + template + class MatrixBase { + protected: + + // Vector representation + static const int kNumElements = nRows * nCols; + T mat[kNumElements]; + + public: + + // Constructors + MatrixBase() { } + MatrixBase(const MatrixBase &other) { + for(int i = 0; i < kNumElements; i++) { + mat[i] = other[i]; + } + } + + // Accessors + T &operator()(int idx) { return mat[idx]; } + const T &operator()(int idx) const { return mat[idx]; } + T &operator()(int r, int c) { return mat[r * nCols + c]; } + const T &operator() const (int r, int c) { return mat[r * nCols + c]; } + + T &operator[](int idx) { return mat[idx]; } + const T &operator[](int idx) const { return mat[idx]; } + + // Operators + template + MatrixBase operator+(const MatrixBase<_T, nRows, nCols> &m) { + MatrixBase a; + for(int i = 0; i < kNumElements; i++) { + a[i] = mat[i] + m[i]; + } + return a; + } + + template + MatrixBase &operator+=(const MatrixBase<_T, nRows, nCols> &m) { + for(int i = 0; i < kNumElements; i++) { + mat[i] += m[i]; + } + return *this; + } + + template + MatrixBase operator-(const MatrixBase<_T, nRows, nCols> &m) { + MatrixBase a; + for(int i = 0; i < kNumElements; i++) { + a[i] = mat[i] - m[i]; + } + return a; + } + + template + MatrixBase &operator-=(const MatrixBase<_T, nRows, nCols> &m) { + for(int i = 0; i < kNumElements; i++) { + mat[i] -= m[i]; + } + return *this; + } + + template + MatrixBase operator*(_T s) { + MatrixBase a; + for(int i = 0; i < kNumElements; i++) { + a[i] = mat[i] * s; + } + return a; + } + + template + MatrixBase &operator*=(_T s) { + for(int i = 0; i < kNumElements; i++) { + mat[i] *= s; + } + return *this; + } + + template + MatrixBase operator/(_T s) { + MatrixBase a; + for(int i = 0; i < kNumElements; i++) { + a[i] = mat[i] / s; + } + return a; + } + + template + MatrixBase &operator/=(_T s) { + for(int i = 0; i < kNumElements; i++) { + mat[i] /= s; + } + return *this; + } + + // Matrix multiplication + template + MatrixBase operator*(const MatrixBase<_T, nCols, nTarget> &m) { + MatrixBase result; + for(int r = 0; r < nRows; r++) + for(int c = 0; c < nTarget; c++) { + result(r, c) = 0; + for(int j = 0; j < nCols; j++) { + result(r, c) += (*this)(r, j) * m(j, c); + } + } + return result; + } + + // Vector multiplication -- treat vectors as Nx1 matrices... + template + VectorBase operator*(const VectorBase<_T, nCols> &v) { + VectorBase result; + for(int r = 0; r < nRows; r++) { + result(r) = 0; + for(int j = 0; j < nCols; j++) { + result(r) += (*this)(r, j) * v(j); + } + } + return result; + } + + // Outer product... + template + friend MatrixBase<_T, N, M> operator^( + const VectorBase<_T, N> &a, + const VectorBase<_U, M> &b + ) { + MatrixBase<_T, N, M> result; + + for(int i = 0; i < N; i++) + for(int j = 0; j < M; j++) + result(i, j) = a[i] * b[j]; + + return result; + } + + template + friend MatrixBase<_T, N, M> OuterProduct( + const VectorBase<_T, N> &a, + const VectorBase<_U, M> &b + ) { + return a ^ b; + } + + // Double dot product + template + T DDot(const MatrixBase<_T, nRows, nCols> &m) { + T result = 0; + for(int i = 0; i < kNumElements; i++) { + result += mat[i] * m[i]; + } + return result; + } + + }; +}; + +#endif // BASE_INCLUDE_MATRIXBASE_H_ diff --git a/Base/include/MatrixSquare.h b/Base/include/MatrixSquare.h new file mode 100644 index 0000000..7fdfb48 --- /dev/null +++ b/Base/include/MatrixSquare.h @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_MATRIXSQUARE_H_ +#define BASE_INCLUDE_MATRIXSQUARE_H_ + +#include "MatrixBase.h" + +namespace FasTC { + + template + class MatrixSquare : public MatrixBase { + public: + + // Constructors + MatrixSquare() { } + MatrixSquare(const MatrixBase &other) { + for(int i = 0; i < kNumElements; i++) { + mat[i] = other[i]; + } + } + }; +}; + +#endif // BASE_INCLUDE_MATRIXSQUARE_H_ diff --git a/Base/include/Vector2.h b/Base/include/Vector2.h new file mode 100644 index 0000000..2c0edcd --- /dev/null +++ b/Base/include/Vector2.h @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_VECTOR2_H_ +#define BASE_INCLUDE_VECTOR2_H_ + +#include "VectorBase.h" + +#ifdef _VEX_ENABLE_SWIZZLE_ +# define _VEX_VEC2_SWIZZLE_DEF(X, Y) \ + Vector2 X##Y() const { return Vector2( X(), Y() ); } +#endif // _VEX_ENABLE_SWIZZLE_ + +namespace FasTC { + + template + class Vector2 : public VectorBase { + public: + // Ideally, we would be able to do this with initialization + // lists, but I'm not really sure how to do that without gross + // code duplication. + Vector2() { } + Vector2(T x, T y) { + X() = x; + Y() = y; + } + + // Overloaded functions + template + Vector2(const Vector2<_T> &v) : VectorBase(v) { } + + template + Vector2 &operator=(const Vector2<_T> &v) { + VectorBase::operator=(v); + return *this; + } + + // Accessors + T &X() { return (*this)[0]; } + const T &X() const { return (*this)[0]; } + + T &Y() { return (*this)[1]; } + const T &Y() const { return (*this)[1]; } + + // Swizzle + #ifdef _VEX_ENABLE_SWIZZLE_ + _VEX_VEC2_SWIZZLE_DEF(X, X) + _VEX_VEC2_SWIZZLE_DEF(X, Y) + _VEX_VEC2_SWIZZLE_DEF(Y, X) + _VEX_VEC2_SWIZZLE_DEF(Y, Y) + #endif //_VEX_ENABLE_SWIZZLE_ + }; + + typedef Vector2 Vec2f; + typedef Vector2 Vec2d; + typedef Vector2 Vec2i; +}; + +#endif // BASE_INCLUDE_VECTOR2_H_ diff --git a/Base/include/Vector3.h b/Base/include/Vector3.h new file mode 100644 index 0000000..3c32b46 --- /dev/null +++ b/Base/include/Vector3.h @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_VECTOR3_H_ +#define BASE_INCLUDE_VECTOR3_H_ + +#include "Vector2.h" + +#ifdef _VEX_ENABLE_SWIZZLE_ +# define _VEX_VEC3_SWIZZLE_DEF(X, Y, Z) \ + Vector3 X##Y##Z() const { return Vector3( X(), Y(), Z() ); } +#endif // _VEX_ENABLE_SWIZZLE_ + +namespace FasTC { + + template + class Vector3 : public VectorBase { + public: + Vector3() { } + Vector3(T x, T y, T z) { + X() = x; + Y() = y; + Z() = z; + } + + // Overloaded functions + template + Vector3(const Vector3<_T> &v) : VectorBase(v) { } + + template + Vector3 &operator=(const Vector3<_T> &v) { + VectorBase::operator=(v); + return *this; + } + + // Accessors + T &X() { return (*this)[0]; } + const T &X() const { return (*this)[0]; } + + T &Y() { return (*this)[1]; } + const T &Y() const { return (*this)[1]; } + + T &Z() { return (*this)[2]; } + const T &Z() const { return (*this)[2]; } + + // Vector operations + template + Vector3 Cross(const Vector3<_T> &v) { + return Vector3( + Y() * v.Z() - v.Y() * Z(), + Z() * v.X() - v.Z() * X(), + X() * v.Y() - v.X() * Y() + ); + } + + // Swizzle + #ifdef _VEX_ENABLE_SWIZZLE_ + _VEX_VEC2_SWIZZLE_DEF(X, X) + _VEX_VEC2_SWIZZLE_DEF(X, Y) + _VEX_VEC2_SWIZZLE_DEF(X, Z) + _VEX_VEC2_SWIZZLE_DEF(Y, X) + _VEX_VEC2_SWIZZLE_DEF(Y, Y) + _VEX_VEC2_SWIZZLE_DEF(Y, Z) + _VEX_VEC2_SWIZZLE_DEF(Z, X) + _VEX_VEC2_SWIZZLE_DEF(Z, Y) + _VEX_VEC2_SWIZZLE_DEF(Z, Z) + + _VEX_VEC3_SWIZZLE_DEF(X, X, X) + _VEX_VEC3_SWIZZLE_DEF(X, X, Y) + _VEX_VEC3_SWIZZLE_DEF(X, X, Z) + _VEX_VEC3_SWIZZLE_DEF(X, Y, X) + _VEX_VEC3_SWIZZLE_DEF(X, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(X, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(X, Z, X) + _VEX_VEC3_SWIZZLE_DEF(X, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(X, Z, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, X, X) + _VEX_VEC3_SWIZZLE_DEF(Y, X, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, X, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, X) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, X) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, X, X) + _VEX_VEC3_SWIZZLE_DEF(Z, X, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, X, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, X) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, X) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, Z) + #endif // _VEX_ENABLE_SWIZZLE_ + }; + + typedef Vector3 Vec3f; + typedef Vector3 Vec3d; + typedef Vector3 Vec3i; +}; + +#endif // BASE_INCLUDE_VECTOR3_H_ diff --git a/Base/include/Vector4.h b/Base/include/Vector4.h new file mode 100644 index 0000000..55f06ae --- /dev/null +++ b/Base/include/Vector4.h @@ -0,0 +1,420 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_VECTOR4_H_ +#define BASE_INCLUDE_VECTOR4_H_ + +#include "TexCompTypes.h" +#include "Vector3.h" + +#ifdef _VEX_ENABLE_SWIZZLE_ +#define _VEX_VEC4_SWIZZLE_DEF(X, Y, Z, W) \ + Vector4 X##Y##Z##W() const { return Vector4( X(), Y(), Z(), W() ); } +#endif // _VEX_ENABLE_SWIZZLE_ + +namespace FasTC { + + template + class Vector4 : public VectorBase { + public: + Vector4() { } + Vector4(T x, T y, T z, T w) { + X() = x; + Y() = y; + Z() = z; + W() = w; + } + + // Overloaded functions + template + Vector4(const Vector4<_T> &v) : VectorBase(v) { } + + template + Vector4 &operator=(const Vector4<_T> &v) { + VectorBase::operator=(v); + return *this; + } + + // Accessors + T &X() { return (*this)[0]; } + const T &X() const { return (*this)[0]; } + + T &Y() { return (*this)[1]; } + const T &Y() const { return (*this)[1]; } + + T &Z() { return (*this)[2]; } + const T &Z() const { return (*this)[2]; } + + T &W() { return (*this)[3]; } + const T &W() const { return (*this)[3]; } + + // Swizzle + #ifdef _VEX_ENABLE_SWIZZLE_ + _VEX_VEC2_SWIZZLE_DEF(X, X) + _VEX_VEC2_SWIZZLE_DEF(X, Y) + _VEX_VEC2_SWIZZLE_DEF(X, Z) + _VEX_VEC2_SWIZZLE_DEF(X, W) + _VEX_VEC2_SWIZZLE_DEF(Y, X) + _VEX_VEC2_SWIZZLE_DEF(Y, Y) + _VEX_VEC2_SWIZZLE_DEF(Y, Z) + _VEX_VEC2_SWIZZLE_DEF(Y, W) + _VEX_VEC2_SWIZZLE_DEF(Z, X) + _VEX_VEC2_SWIZZLE_DEF(Z, Y) + _VEX_VEC2_SWIZZLE_DEF(Z, Z) + _VEX_VEC2_SWIZZLE_DEF(Z, W) + _VEX_VEC2_SWIZZLE_DEF(W, X) + _VEX_VEC2_SWIZZLE_DEF(W, Y) + _VEX_VEC2_SWIZZLE_DEF(W, Z) + _VEX_VEC2_SWIZZLE_DEF(W, W) + + _VEX_VEC3_SWIZZLE_DEF(X, X, X) + _VEX_VEC3_SWIZZLE_DEF(X, X, Y) + _VEX_VEC3_SWIZZLE_DEF(X, X, Z) + _VEX_VEC3_SWIZZLE_DEF(X, X, W) + _VEX_VEC3_SWIZZLE_DEF(X, Y, X) + _VEX_VEC3_SWIZZLE_DEF(X, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(X, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(X, Y, W) + _VEX_VEC3_SWIZZLE_DEF(X, Z, X) + _VEX_VEC3_SWIZZLE_DEF(X, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(X, Z, Z) + _VEX_VEC3_SWIZZLE_DEF(X, Z, W) + _VEX_VEC3_SWIZZLE_DEF(X, W, X) + _VEX_VEC3_SWIZZLE_DEF(X, W, Y) + _VEX_VEC3_SWIZZLE_DEF(X, W, Z) + _VEX_VEC3_SWIZZLE_DEF(X, W, W) + _VEX_VEC3_SWIZZLE_DEF(Y, X, X) + _VEX_VEC3_SWIZZLE_DEF(Y, X, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, X, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, X, W) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, X) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, Y, W) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, X) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, Z, W) + _VEX_VEC3_SWIZZLE_DEF(Y, W, X) + _VEX_VEC3_SWIZZLE_DEF(Y, W, Y) + _VEX_VEC3_SWIZZLE_DEF(Y, W, Z) + _VEX_VEC3_SWIZZLE_DEF(Y, W, W) + _VEX_VEC3_SWIZZLE_DEF(Z, X, X) + _VEX_VEC3_SWIZZLE_DEF(Z, X, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, X, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, X, W) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, X) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, Y, W) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, X) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, Z, W) + _VEX_VEC3_SWIZZLE_DEF(Z, W, X) + _VEX_VEC3_SWIZZLE_DEF(Z, W, Y) + _VEX_VEC3_SWIZZLE_DEF(Z, W, Z) + _VEX_VEC3_SWIZZLE_DEF(Z, W, W) + _VEX_VEC3_SWIZZLE_DEF(W, X, X) + _VEX_VEC3_SWIZZLE_DEF(W, X, Y) + _VEX_VEC3_SWIZZLE_DEF(W, X, Z) + _VEX_VEC3_SWIZZLE_DEF(W, X, W) + _VEX_VEC3_SWIZZLE_DEF(W, Y, X) + _VEX_VEC3_SWIZZLE_DEF(W, Y, Y) + _VEX_VEC3_SWIZZLE_DEF(W, Y, Z) + _VEX_VEC3_SWIZZLE_DEF(W, Y, W) + _VEX_VEC3_SWIZZLE_DEF(W, Z, X) + _VEX_VEC3_SWIZZLE_DEF(W, Z, Y) + _VEX_VEC3_SWIZZLE_DEF(W, Z, Z) + _VEX_VEC3_SWIZZLE_DEF(W, Z, W) + _VEX_VEC3_SWIZZLE_DEF(W, W, X) + _VEX_VEC3_SWIZZLE_DEF(W, W, Y) + _VEX_VEC3_SWIZZLE_DEF(W, W, Z) + _VEX_VEC3_SWIZZLE_DEF(W, W, W) + + _VEX_VEC4_SWIZZLE_DEF(X, X, X, X) + _VEX_VEC4_SWIZZLE_DEF(X, X, X, Y) + _VEX_VEC4_SWIZZLE_DEF(X, X, X, Z) + _VEX_VEC4_SWIZZLE_DEF(X, X, X, W) + _VEX_VEC4_SWIZZLE_DEF(X, X, Y, X) + _VEX_VEC4_SWIZZLE_DEF(X, X, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(X, X, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(X, X, Y, W) + _VEX_VEC4_SWIZZLE_DEF(X, X, Z, X) + _VEX_VEC4_SWIZZLE_DEF(X, X, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(X, X, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(X, X, Z, W) + _VEX_VEC4_SWIZZLE_DEF(X, X, W, X) + _VEX_VEC4_SWIZZLE_DEF(X, X, W, Y) + _VEX_VEC4_SWIZZLE_DEF(X, X, W, Z) + _VEX_VEC4_SWIZZLE_DEF(X, X, W, W) + _VEX_VEC4_SWIZZLE_DEF(X, Y, X, X) + _VEX_VEC4_SWIZZLE_DEF(X, Y, X, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Y, X, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Y, X, W) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Y, X) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Y, W) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Z, X) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Y, Z, W) + _VEX_VEC4_SWIZZLE_DEF(X, Y, W, X) + _VEX_VEC4_SWIZZLE_DEF(X, Y, W, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Y, W, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Y, W, W) + _VEX_VEC4_SWIZZLE_DEF(X, Z, X, X) + _VEX_VEC4_SWIZZLE_DEF(X, Z, X, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Z, X, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Z, X, W) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Y, X) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Y, W) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Z, X) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Z, Z, W) + _VEX_VEC4_SWIZZLE_DEF(X, Z, W, X) + _VEX_VEC4_SWIZZLE_DEF(X, Z, W, Y) + _VEX_VEC4_SWIZZLE_DEF(X, Z, W, Z) + _VEX_VEC4_SWIZZLE_DEF(X, Z, W, W) + _VEX_VEC4_SWIZZLE_DEF(X, W, X, X) + _VEX_VEC4_SWIZZLE_DEF(X, W, X, Y) + _VEX_VEC4_SWIZZLE_DEF(X, W, X, Z) + _VEX_VEC4_SWIZZLE_DEF(X, W, X, W) + _VEX_VEC4_SWIZZLE_DEF(X, W, Y, X) + _VEX_VEC4_SWIZZLE_DEF(X, W, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(X, W, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(X, W, Y, W) + _VEX_VEC4_SWIZZLE_DEF(X, W, Z, X) + _VEX_VEC4_SWIZZLE_DEF(X, W, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(X, W, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(X, W, Z, W) + _VEX_VEC4_SWIZZLE_DEF(X, W, W, X) + _VEX_VEC4_SWIZZLE_DEF(X, W, W, Y) + _VEX_VEC4_SWIZZLE_DEF(X, W, W, Z) + _VEX_VEC4_SWIZZLE_DEF(X, W, W, W) + _VEX_VEC4_SWIZZLE_DEF(Y, X, X, X) + _VEX_VEC4_SWIZZLE_DEF(Y, X, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, X, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, X, X, W) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, X, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Y, X, W, X) + _VEX_VEC4_SWIZZLE_DEF(Y, X, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, X, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, X, W, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, X, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, X, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, W, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Y, W, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, X, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, X, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, W, X) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, Z, W, W) + _VEX_VEC4_SWIZZLE_DEF(Y, W, X, X) + _VEX_VEC4_SWIZZLE_DEF(Y, W, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, W, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, W, X, W) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, W, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Y, W, W, X) + _VEX_VEC4_SWIZZLE_DEF(Y, W, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Y, W, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Y, W, W, W) + _VEX_VEC4_SWIZZLE_DEF(Z, X, X, X) + _VEX_VEC4_SWIZZLE_DEF(Z, X, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, X, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, X, X, W) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, X, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Z, X, W, X) + _VEX_VEC4_SWIZZLE_DEF(Z, X, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, X, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, X, W, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, X, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, X, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, W, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Y, W, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, X, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, X, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, W, X) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, Z, W, W) + _VEX_VEC4_SWIZZLE_DEF(Z, W, X, X) + _VEX_VEC4_SWIZZLE_DEF(Z, W, X, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, W, X, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, W, X, W) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Y, X) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Y, W) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Z, X) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, W, Z, W) + _VEX_VEC4_SWIZZLE_DEF(Z, W, W, X) + _VEX_VEC4_SWIZZLE_DEF(Z, W, W, Y) + _VEX_VEC4_SWIZZLE_DEF(Z, W, W, Z) + _VEX_VEC4_SWIZZLE_DEF(Z, W, W, W) + _VEX_VEC4_SWIZZLE_DEF(W, X, X, X) + _VEX_VEC4_SWIZZLE_DEF(W, X, X, Y) + _VEX_VEC4_SWIZZLE_DEF(W, X, X, Z) + _VEX_VEC4_SWIZZLE_DEF(W, X, X, W) + _VEX_VEC4_SWIZZLE_DEF(W, X, Y, X) + _VEX_VEC4_SWIZZLE_DEF(W, X, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(W, X, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(W, X, Y, W) + _VEX_VEC4_SWIZZLE_DEF(W, X, Z, X) + _VEX_VEC4_SWIZZLE_DEF(W, X, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(W, X, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(W, X, Z, W) + _VEX_VEC4_SWIZZLE_DEF(W, X, W, X) + _VEX_VEC4_SWIZZLE_DEF(W, X, W, Y) + _VEX_VEC4_SWIZZLE_DEF(W, X, W, Z) + _VEX_VEC4_SWIZZLE_DEF(W, X, W, W) + _VEX_VEC4_SWIZZLE_DEF(W, Y, X, X) + _VEX_VEC4_SWIZZLE_DEF(W, Y, X, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Y, X, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Y, X, W) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Y, X) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Y, W) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Z, X) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Y, Z, W) + _VEX_VEC4_SWIZZLE_DEF(W, Y, W, X) + _VEX_VEC4_SWIZZLE_DEF(W, Y, W, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Y, W, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Y, W, W) + _VEX_VEC4_SWIZZLE_DEF(W, Z, X, X) + _VEX_VEC4_SWIZZLE_DEF(W, Z, X, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Z, X, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Z, X, W) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Y, X) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Y, W) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Z, X) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Z, Z, W) + _VEX_VEC4_SWIZZLE_DEF(W, Z, W, X) + _VEX_VEC4_SWIZZLE_DEF(W, Z, W, Y) + _VEX_VEC4_SWIZZLE_DEF(W, Z, W, Z) + _VEX_VEC4_SWIZZLE_DEF(W, Z, W, W) + _VEX_VEC4_SWIZZLE_DEF(W, W, X, X) + _VEX_VEC4_SWIZZLE_DEF(W, W, X, Y) + _VEX_VEC4_SWIZZLE_DEF(W, W, X, Z) + _VEX_VEC4_SWIZZLE_DEF(W, W, X, W) + _VEX_VEC4_SWIZZLE_DEF(W, W, Y, X) + _VEX_VEC4_SWIZZLE_DEF(W, W, Y, Y) + _VEX_VEC4_SWIZZLE_DEF(W, W, Y, Z) + _VEX_VEC4_SWIZZLE_DEF(W, W, Y, W) + _VEX_VEC4_SWIZZLE_DEF(W, W, Z, X) + _VEX_VEC4_SWIZZLE_DEF(W, W, Z, Y) + _VEX_VEC4_SWIZZLE_DEF(W, W, Z, Z) + _VEX_VEC4_SWIZZLE_DEF(W, W, Z, W) + _VEX_VEC4_SWIZZLE_DEF(W, W, W, X) + _VEX_VEC4_SWIZZLE_DEF(W, W, W, Y) + _VEX_VEC4_SWIZZLE_DEF(W, W, W, Z) + _VEX_VEC4_SWIZZLE_DEF(W, W, W, W) + #endif // _VEX_ENABLE_SWIZZLE_ + }; + + typedef Vector4 Vec4f; + typedef Vector4 Vec4d; + typedef Vector4 Vec4i; +}; + +#endif // BASE_INCLUDE_VECTOR4_H_ diff --git a/Base/include/VectorBase.h b/Base/include/VectorBase.h new file mode 100644 index 0000000..a7d892f --- /dev/null +++ b/Base/include/VectorBase.h @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) 2012 Pavel Krajcevski + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + ******************************************************************************/ + +#ifndef BASE_INCLUDE_VECTORBASE_H_ +#define BASE_INCLUDE_VECTORBASE_H_ + +// !FIXME! For sqrt function. This increases compilation time by a LOT +// but I couldn't guarantee any faster general-purpose implementation +#include + +namespace FasTC { + + template + class VectorBase { + protected: + + // Vector representation + T vec[N]; + + public: + + VectorBase() { } + VectorBase(const VectorBase &other) { + for(int i = 0; i < N; i++) vec[i] = other[i]; + } + + explicit VectorBase(T *_vec) { + for(int i = 0; i < N; i++) { + vec[i] = _vec[i]; + } + } + + // Accessors + T &operator()(int idx) { return vec[idx]; } + T &operator[](int idx) { return vec[idx]; } + const T &operator()(int idx) const { return vec[idx]; } + const T &operator[](int idx) const { return vec[idx]; } + + // Allow casts to the respective array representation... + operator T *() const { return vec; } + VectorBase &operator=(const T *v) { + for(int i = 0; i < N; i++) + vec[i] = v[i]; + return *this; + } + + // 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); + } + + // Operators + template + VectorBase operator+(const VectorBase<_T, N> &v) const { + VectorBase a; + for(int i = 0; i < N; i++) + a.vec[i] = v(i) + vec[i]; + return a; + } + + template + VectorBase &operator+=(const VectorBase<_T, N> &v) const { + for(int i = 0; i < N; i++) + vec[i] += v(i); + return *this; + } + + template + VectorBase operator-(const VectorBase<_T, N> &v) const { + VectorBase a; + for(int i = 0; i < N; i++) + a(i) = vec[i] - v[i]; + return a; + } + + template + VectorBase &operator-=(const VectorBase<_T, N> &v) const { + for(int i = 0; i < N; i++) { + vec[i] -= v[i]; + } + return *this; + } + + template + VectorBase &operator=(const VectorBase<_T, N> &v) { + for(int i = 0; i < N; i++) + vec[i] = v[i]; + return *this; + } + + template + VectorBase operator*(const _T s) const { + VectorBase a; + for(int i = 0; i < N; i++) + a[i] = vec[i] * s; + return a; + } + + template + friend VectorBase operator*(const _T s, const VectorBase &v) { + VectorBase a; + for(int i = 0; i < N; i++) + a[i] = v[i] * s; + return a; + } + + template + VectorBase operator/(const _T s) const { + VectorBase a; + for(int i = 0; i < N; i++) + a[i] = vec[i] / s; + return a; + } + + template + friend VectorBase operator/(const _T s, const VectorBase &v) { + VectorBase a; + for(int i = 0; i < N; i++) + a[i] = v[i] / s; + return a; + } + + template + void operator*=(const _T s) { + for(int i = 0; i < N; i++) + vec[i] *= s; + } + + template + void operator/=(const _T s) { + for(int i = 0; i < N; i++) + vec[i] /= s; + } + + // Vector operations + template + T Dot(const VectorBase<_T, N> &v) const { + T sum = 0; + for(int i = 0; i < N; i++) + sum += vec[i] * v[i]; + return sum; + } + + T LengthSq() const { return this->Dot(*this); } + T Length() const { return sqrt(LengthSq()); } + }; +}; + +#endif // BASE_INCLUDE_VECTORBASE_H_ From ab598c9ef7f1b26e36ffb0fedb2980e494c187f0 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Thu, 3 Oct 2013 17:25:15 -0400 Subject: [PATCH 02/13] Move Pixel class from PVRTCEncoder to FasTCBase. --- Base/CMakeLists.txt | 9 + {PVRTCEncoder/src => Base/include}/Pixel.h | 68 +++-- {PVRTCEncoder => Base}/src/Pixel.cpp | 12 +- Base/test/CMakeLists.txt | 66 +++++ .../test/TestARGBPixel.cpp | 58 ++-- Base/test/TestPixel.cpp | 250 ++++++++++++++++++ PVRTCEncoder/CMakeLists.txt | 3 +- PVRTCEncoder/src/Block.h | 1 + PVRTCEncoder/src/Compressor.cpp | 2 +- PVRTCEncoder/src/Decompressor.cpp | 4 +- PVRTCEncoder/src/Image.cpp | 2 +- PVRTCEncoder/src/Image.h | 8 +- PVRTCEncoder/test/CMakeLists.txt | 2 +- PVRTCEncoder/test/ImageTest.cpp | 2 +- 14 files changed, 404 insertions(+), 83 deletions(-) rename {PVRTCEncoder/src => Base/include}/Pixel.h (80%) rename {PVRTCEncoder => Base}/src/Pixel.cpp (96%) create mode 100644 Base/test/CMakeLists.txt rename PVRTCEncoder/test/PixelTest.cpp => Base/test/TestARGBPixel.cpp (80%) create mode 100644 Base/test/TestPixel.cpp diff --git a/Base/CMakeLists.txt b/Base/CMakeLists.txt index 53fb033..0d43519 100644 --- a/Base/CMakeLists.txt +++ b/Base/CMakeLists.txt @@ -52,12 +52,21 @@ SET( SOURCES "src/Image.cpp" "src/CompressionJob.cpp" + "src/Pixel.cpp" ) SET( HEADERS "include/TexCompTypes.h" "include/Image.h" "include/CompressionJob.h" + "include/Pixel.h" + "include/VectorBase.h" + "include/Vector2.h" + "include/Vector3.h" + "include/Vector4.h" + "include/MatrixBase.h" + "include/MatrixSquare.h" + "include/Matrix3x3.h" ) INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) diff --git a/PVRTCEncoder/src/Pixel.h b/Base/include/Pixel.h similarity index 80% rename from PVRTCEncoder/src/Pixel.h rename to Base/include/Pixel.h index f8821f4..4fa9312 100644 --- a/PVRTCEncoder/src/Pixel.h +++ b/Base/include/Pixel.h @@ -50,27 +50,33 @@ * */ -#ifndef PVRTCENCODER_SRC_PIXEL_H_ -#define PVRTCENCODER_SRC_PIXEL_H_ +#ifndef BASE_INCLUDE_PIXEL_H_ +#define BASE_INCLUDE_PIXEL_H_ #include "TexCompTypes.h" +#include "Vector4.h" -namespace PVRTCC { +namespace FasTC { + +class Pixel : public Vector4 { + private: + uint8 m_BitDepth[4]; -class Pixel { public: - Pixel(): m_A(0), m_R(0), m_G(0), m_B(0) { - for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; + Pixel() : Vector4(0, 0, 0, 0) { + for(int i = 0; i < 4; i++) + m_BitDepth[i] = 8; } - explicit Pixel(uint32 rgba) { - for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; - UnpackRGBA(rgba); + explicit Pixel(uint32 rgba) : Vector4() { + for(int i = 0; i < 4; i++) + m_BitDepth[i] = 8; + Unpack(rgba); } Pixel(const uint8 *bits, const uint8 channelDepth[4] = static_cast(0), - uint8 bitOffset = 0) { + uint8 bitOffset = 0) : Vector4() { FromBits(bits, channelDepth, bitOffset); } @@ -100,16 +106,16 @@ class Pixel { // above for how we do this. static uint8 ChangeBitDepth(uint8 val, uint8 oldDepth, uint8 newDepth); - const uint8 &A() const { return m_A; } - uint8 &A() { return m_A; } - const uint8 &R() const { return m_R; } - uint8 &R() { return m_R; } - const uint8 &G() const { return m_G; } - uint8 &G() { return m_G; } - const uint8 &B() const { return m_B; } - uint8 &B() { return m_B; } - const uint8 &Component(uint32 idx) const { return m_Component[idx]; } - uint8 &Component(uint32 idx) { return m_Component[idx]; } + const uint8 &A() const { return X(); } + uint8 &A() { return X(); } + const uint8 &R() const { return Y(); } + uint8 &R() { return Y(); } + const uint8 &G() const { return Z(); } + uint8 &G() { return Z(); } + const uint8 &B() const { return W(); } + uint8 &B() { return W(); } + const uint8 &Component(uint32 idx) const { return vec[idx]; } + uint8 &Component(uint32 idx) { return vec[idx]; } void GetBitDepth(uint8 (&outDepth)[4]) const { for(int i = 0; i < 4; i++) { @@ -121,27 +127,13 @@ class Pixel { // and then pack each channel into an R8G8B8A8 32-bit integer. We assume // that the architecture is little-endian, so the alpha channel will end // up in the most-significant byte. - uint32 PackRGBA() const; - void UnpackRGBA(uint32 rgba); + uint32 Pack() const; + void Unpack(uint32 rgba); // Tests for equality by comparing the values and the bit depths. bool operator==(const Pixel &) const; - - private: - union { - struct { - uint8 m_A; - uint8 m_R; - uint8 m_G; - uint8 m_B; - }; - uint8 m_Component[4]; - }; - - // This contains the number of bits that each pixel has. - uint8 m_BitDepth[4]; }; -} // namespace PVRTCC +} // namespace FasTC -#endif // PVRTCENCODER_SRC_PIXEL_H_ +#endif // BASE_INCLUDE_PIXEL_H_ diff --git a/PVRTCEncoder/src/Pixel.cpp b/Base/src/Pixel.cpp similarity index 96% rename from PVRTCEncoder/src/Pixel.cpp rename to Base/src/Pixel.cpp index 8ea763d..2b047bd 100644 --- a/PVRTCEncoder/src/Pixel.cpp +++ b/Base/src/Pixel.cpp @@ -56,7 +56,7 @@ #include #include -namespace PVRTCC { +namespace FasTC { void Pixel::FromBits(const uint8 *bits, const uint8 channelDepth[4], @@ -82,7 +82,7 @@ namespace PVRTCC { } for(int32 i = 0; i < 4; i++) { - uint8 &channel = m_Component[i]; + uint8 &channel = Component(i); uint32 depth = m_BitDepth[i]; assert(depth <= 8); @@ -185,12 +185,12 @@ namespace PVRTCC { void Pixel::ChangeBitDepth(const uint8 (&depth)[4]) { for(uint32 i = 0; i < 4; i++) { - m_Component[i] = ChangeBitDepth(m_Component[i], m_BitDepth[i], depth[i]); + Component(i) = ChangeBitDepth(Component(i), m_BitDepth[i], depth[i]); m_BitDepth[i] = depth[i]; } } - uint32 Pixel::PackRGBA() const { + uint32 Pixel::Pack() const { Pixel eightBit(*this); const uint8 eightBitDepth[4] = { 8, 8, 8, 8 }; eightBit.ChangeBitDepth(eightBitDepth); @@ -206,7 +206,7 @@ namespace PVRTCC { return r; } - void Pixel::UnpackRGBA(uint32 rgba) { + void Pixel::Unpack(uint32 rgba) { A() = ChangeBitDepth((rgba >> 24) & 0xFF, 8, m_BitDepth[0]); R() = ChangeBitDepth(rgba & 0xFF, 8, m_BitDepth[1]); G() = ChangeBitDepth((rgba >> 8) & 0xFF, 8, m_BitDepth[2]); @@ -228,4 +228,4 @@ namespace PVRTCC { return ok; } -} // namespace PVRTCC +} // namespace FasTC diff --git a/Base/test/CMakeLists.txt b/Base/test/CMakeLists.txt new file mode 100644 index 0000000..43fb154 --- /dev/null +++ b/Base/test/CMakeLists.txt @@ -0,0 +1,66 @@ +# FasTC +# Copyright (c) 2013 University of North Carolina at Chapel Hill. +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for educational, research, and non-profit purposes, without +# fee, and without a written agreement is hereby granted, provided that the +# above copyright notice, this paragraph, and the following four paragraphs +# appear in all copies. +# +# Permission to incorporate this software into commercial products may be +# obtained by contacting the authors or the Office of Technology Development +# at the University of North Carolina at Chapel Hill . +# +# This software program and documentation are copyrighted by the University of +# North Carolina at Chapel Hill. The software program and documentation are +# supplied "as is," without any accompanying services from the University of +# North Carolina at Chapel Hill or the authors. The University of North +# Carolina at Chapel Hill and the authors do not warrant that the operation of +# the program will be uninterrupted or error-free. The end-user understands +# that the program was developed for research purposes and is advised not to +# rely exclusively on the program for any reason. +# +# IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE +# AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, +# OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF +# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA +# AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# +# THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY +# DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY +# STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON +# AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND +# THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, +# ENHANCEMENTS, OR MODIFICATIONS. +# +# Please send all BUG REPORTS to . +# +# The authors may be contacted via: +# +# Pavel Krajcevski +# Dept of Computer Science +# 201 S Columbia St +# Frederick P. Brooks, Jr. Computer Science Bldg +# Chapel Hill, NC 27599-3175 +# USA +# +# + +INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) +INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/GTest/include) + +SET(TESTS + Pixel +) + +FOREACH(TEST ${TESTS}) + SET(TEST_NAME Test${TEST}) + SET(TEST_MODULE Test${TEST}.cpp) + ADD_EXECUTABLE(${TEST_NAME} ${TEST_MODULE}) + TARGET_LINK_LIBRARIES(${TEST_NAME} FasTCBase) + TARGET_LINK_LIBRARIES(${TEST_NAME} gtest_main) + ADD_TEST(${TEST_NAME} ${TEST_NAME}) +ENDFOREACH() diff --git a/PVRTCEncoder/test/PixelTest.cpp b/Base/test/TestARGBPixel.cpp similarity index 80% rename from PVRTCEncoder/test/PixelTest.cpp rename to Base/test/TestARGBPixel.cpp index decab5b..b3e2234 100644 --- a/PVRTCEncoder/test/PixelTest.cpp +++ b/Base/test/TestARGBPixel.cpp @@ -54,7 +54,7 @@ #include "Pixel.h" TEST(Pixel, DefaultConstructor) { - PVRTCC::Pixel p; + FasTC::Pixel p; EXPECT_EQ(p.R(), 0); EXPECT_EQ(p.G(), 0); EXPECT_EQ(p.B(), 0); @@ -70,12 +70,12 @@ TEST(Pixel, DefaultConstructor) { TEST(Pixel, FromBitsAndAssociatedConstructor) { const uint8 bits[8] = { 0xA8, 0xB3, 0x7C, 0x21, 0xBD, 0xD4, 0x09, 0x92 }; - PVRTCC::Pixel ps[2]; - ps[0] = PVRTCC::Pixel(bits); + FasTC::Pixel ps[2]; + ps[0] = FasTC::Pixel(bits); ps[1].FromBits(bits); for(int i = 0; i < 2; i++) { - PVRTCC::Pixel &p = ps[i]; + FasTC::Pixel &p = ps[i]; EXPECT_EQ(p.A(), 0xA8); EXPECT_EQ(p.R(), 0xB3); @@ -90,11 +90,11 @@ TEST(Pixel, FromBitsAndAssociatedConstructor) { } const uint8 depth1[4] = { 3, 2, 0, 8 }; - ps[0] = PVRTCC::Pixel(bits + 3, depth1); + ps[0] = FasTC::Pixel(bits + 3, depth1); ps[1].FromBits(bits + 3, depth1); for(int i = 0; i < 2; i++) { - PVRTCC::Pixel &p = ps[i]; + FasTC::Pixel &p = ps[i]; EXPECT_EQ(p.A(), 0x01); EXPECT_EQ(p.R(), 0x00); @@ -112,11 +112,11 @@ TEST(Pixel, FromBitsAndAssociatedConstructor) { const uint8 depth2[4] = { 5, 6, 2, 4 }; - ps[0] = PVRTCC::Pixel(bits + 4, depth2, 2); + ps[0] = FasTC::Pixel(bits + 4, depth2, 2); ps[1].FromBits(bits + 4, depth2, 2); for(int i = 0; i < 2; i++) { - PVRTCC::Pixel &p = ps[i]; + FasTC::Pixel &p = ps[i]; EXPECT_EQ(p.A(), 0x1E); EXPECT_EQ(p.R(), 0x3A); @@ -134,7 +134,7 @@ TEST(Pixel, FromBitsAndAssociatedConstructor) { } TEST(Pixel, ToBits) { - PVRTCC::Pixel p; + FasTC::Pixel p; uint8 bitDepth[4] = { 2, 8, 1, 7 }; p.ChangeBitDepth(bitDepth); @@ -163,39 +163,39 @@ TEST(Pixel, ChangeChannelBitDepth) { uint8 val = 0x43; uint8 depth = 7; - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 8), 0x87); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 7), 0x43); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 6), 0x22); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 2), 0x2); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 0), 0xFF); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 8), 0x87); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 7), 0x43); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 6), 0x22); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 2), 0x2); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 0), 0xFF); val = 0x3; depth = 3; - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 8), 0x6D); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 6), 0x1B); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 3), 0x03); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 2), 0x02); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 0), 0xFF); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 8), 0x6D); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 6), 0x1B); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 3), 0x03); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 2), 0x02); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 0), 0xFF); } TEST(Pixel, ChangeChannelBitDepthFromZero) { uint8 val = 0x43; uint8 depth = 0; - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 8), 0xFF); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 7), 0x7F); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 6), 0x3F); - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 2), 0x03); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 8), 0xFF); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 7), 0x7F); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 6), 0x3F); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 2), 0x03); // Shouldn't change it... - EXPECT_EQ(PVRTCC::Pixel::ChangeBitDepth(val, depth, 0), 0x43); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 0), 0x43); } TEST(Pixel, ChangePixelBitDepth) { const uint8 bits[4] = { 0x86, 0xC0, 0x0, 0x0 }; const uint8 depth[4] = {7, 3, 0, 0}; - PVRTCC::Pixel p(bits, depth); + FasTC::Pixel p(bits, depth); const uint8 newDepth[4] = { 8, 8, 8, 8 }; p.ChangeBitDepth(newDepth); @@ -216,7 +216,7 @@ TEST(Pixel, ChangePixelBitDepth) { TEST(Pixel, PackRGBA) { const uint8 bits[4] = { 0x86, 0xC0, 0x0, 0x0 }; const uint8 depth[4] = {7, 3, 0, 0}; - PVRTCC::Pixel p(bits, depth); + FasTC::Pixel p(bits, depth); uint32 val = p.PackRGBA(); EXPECT_EQ(val, 0x87FFFF6D); @@ -224,7 +224,7 @@ TEST(Pixel, PackRGBA) { TEST(Pixel, UnpackRGBA) { uint32 rgba = 0x4619B3FE; - PVRTCC::Pixel p; + FasTC::Pixel p; p.UnpackRGBA(rgba); EXPECT_EQ(p.A(), 0x46); @@ -232,13 +232,13 @@ TEST(Pixel, UnpackRGBA) { EXPECT_EQ(p.G(), 0xB3); EXPECT_EQ(p.R(), 0xFE); - p = PVRTCC::Pixel(rgba); + p = FasTC::Pixel(rgba); EXPECT_EQ(p.A(), 0x46); EXPECT_EQ(p.B(), 0x19); EXPECT_EQ(p.G(), 0xB3); EXPECT_EQ(p.R(), 0xFE); - p = PVRTCC::Pixel(); + p = FasTC::Pixel(); uint8 newBitDepth[4] = { 3, 5, 2, 1 }; // A R G B p.ChangeBitDepth(newBitDepth); p.UnpackRGBA(rgba); diff --git a/Base/test/TestPixel.cpp b/Base/test/TestPixel.cpp new file mode 100644 index 0000000..0a630b8 --- /dev/null +++ b/Base/test/TestPixel.cpp @@ -0,0 +1,250 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#include "gtest/gtest.h" +#include "Pixel.h" + +TEST(Pixel, DefaultConstructor) { + FasTC::Pixel p; + EXPECT_EQ(p.R(), 0); + EXPECT_EQ(p.G(), 0); + EXPECT_EQ(p.B(), 0); + EXPECT_EQ(p.A(), 0); + + uint8 depth[4]; + p.GetBitDepth(depth); + + for(int i = 0; i < 4; i++) { + EXPECT_EQ(depth[i], 8); + } +} + +TEST(Pixel, FromBitsAndAssociatedConstructor) { + const uint8 bits[8] = { 0xA8, 0xB3, 0x7C, 0x21, 0xBD, 0xD4, 0x09, 0x92 }; + FasTC::Pixel ps[2]; + ps[0] = FasTC::Pixel(bits); + ps[1].FromBits(bits); + + for(int i = 0; i < 2; i++) { + FasTC::Pixel &p = ps[i]; + + EXPECT_EQ(p.A(), 0xA8); + EXPECT_EQ(p.R(), 0xB3); + EXPECT_EQ(p.G(), 0x7C); + EXPECT_EQ(p.B(), 0x21); + + uint8 depth[4]; + p.GetBitDepth(depth); + for(int j = 0; j < 4; j++) { + EXPECT_EQ(depth[j], 8); + } + } + + const uint8 depth1[4] = { 3, 2, 0, 8 }; + ps[0] = FasTC::Pixel(bits + 3, depth1); + ps[1].FromBits(bits + 3, depth1); + + for(int i = 0; i < 2; i++) { + FasTC::Pixel &p = ps[i]; + + EXPECT_EQ(p.A(), 0x01); + EXPECT_EQ(p.R(), 0x00); + EXPECT_EQ(p.G(), 0xFF); + EXPECT_EQ(p.B(), 0x37); + + uint8 depth[4]; + p.GetBitDepth(depth); + + EXPECT_EQ(depth[0], 3); + EXPECT_EQ(depth[1], 2); + EXPECT_EQ(depth[2], 0); + EXPECT_EQ(depth[3], 8); + } + + + const uint8 depth2[4] = { 5, 6, 2, 4 }; + ps[0] = FasTC::Pixel(bits + 4, depth2, 2); + ps[1].FromBits(bits + 4, depth2, 2); + + for(int i = 0; i < 2; i++) { + FasTC::Pixel &p = ps[i]; + + EXPECT_EQ(p.A(), 0x1E); + EXPECT_EQ(p.R(), 0x3A); + EXPECT_EQ(p.G(), 0x02); + EXPECT_EQ(p.B(), 0x00); + + uint8 depth[4]; + p.GetBitDepth(depth); + + EXPECT_EQ(depth[0], 5); + EXPECT_EQ(depth[1], 6); + EXPECT_EQ(depth[2], 2); + EXPECT_EQ(depth[3], 4); + } +} + +TEST(Pixel, ToBits) { + FasTC::Pixel p; + + uint8 bitDepth[4] = { 2, 8, 1, 7 }; + p.ChangeBitDepth(bitDepth); + + p.A() = 0x2; + p.R() = 0x56; + p.G() = 0; + p.B() = 0x4F; + + uint8 bits[3]; + memset(bits, 0, sizeof(bits)); + p.ToBits(bits, sizeof(bits)); + + EXPECT_EQ(bits[0], 0x4F); + EXPECT_EQ(bits[1], 0x56); + EXPECT_EQ(bits[2], 0x2); + + memset(bits, 0, sizeof(bits)); + p.ToBits(bits, 3, 2); + EXPECT_EQ(bits[0], 0x3C); + EXPECT_EQ(bits[1], 0x59); + EXPECT_EQ(bits[2], 0x09); +} + +TEST(Pixel, ChangeChannelBitDepth) { + uint8 val = 0x43; + uint8 depth = 7; + + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 8), 0x87); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 7), 0x43); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 6), 0x22); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 2), 0x2); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 0), 0xFF); + + val = 0x3; + depth = 3; + + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 8), 0x6D); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 6), 0x1B); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 3), 0x03); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 2), 0x02); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 0), 0xFF); +} + +TEST(Pixel, ChangeChannelBitDepthFromZero) { + uint8 val = 0x43; + uint8 depth = 0; + + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 8), 0xFF); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 7), 0x7F); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 6), 0x3F); + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 2), 0x03); + + // Shouldn't change it... + EXPECT_EQ(FasTC::Pixel::ChangeBitDepth(val, depth, 0), 0x43); +} + +TEST(Pixel, ChangePixelBitDepth) { + const uint8 bits[4] = { 0x86, 0xC0, 0x0, 0x0 }; + const uint8 depth[4] = {7, 3, 0, 0}; + FasTC::Pixel p(bits, depth); + + const uint8 newDepth[4] = { 8, 8, 8, 8 }; + p.ChangeBitDepth(newDepth); + + EXPECT_EQ(p.A(), 0x87); + EXPECT_EQ(p.R(), 0x6D); + EXPECT_EQ(p.G(), 0xFF); + EXPECT_EQ(p.B(), 0xFF); + + uint8 outDepth[4]; + p.GetBitDepth(outDepth); + + for(uint32 i = 0; i < 4; i++) { + EXPECT_EQ(outDepth[i], 8); + } +} + +TEST(Pixel, PackRGBA) { + const uint8 bits[4] = { 0x86, 0xC0, 0x0, 0x0 }; + const uint8 depth[4] = {7, 3, 0, 0}; + FasTC::Pixel p(bits, depth); + + uint32 val = p.Pack(); + EXPECT_EQ(val, 0x87FFFF6D); +} + +TEST(Pixel, UnpackRGBA) { + uint32 rgba = 0x4619B3FE; + FasTC::Pixel p; + + p.Unpack(rgba); + EXPECT_EQ(p.A(), 0x46); + EXPECT_EQ(p.B(), 0x19); + EXPECT_EQ(p.G(), 0xB3); + EXPECT_EQ(p.R(), 0xFE); + + p = FasTC::Pixel(rgba); + EXPECT_EQ(p.A(), 0x46); + EXPECT_EQ(p.B(), 0x19); + EXPECT_EQ(p.G(), 0xB3); + EXPECT_EQ(p.R(), 0xFE); + + p = FasTC::Pixel(); + uint8 newBitDepth[4] = { 3, 5, 2, 1 }; // A R G B + p.ChangeBitDepth(newBitDepth); + p.Unpack(rgba); + + EXPECT_EQ(p.A(), 0x2); + EXPECT_EQ(p.B(), 0x0); + EXPECT_EQ(p.G(), 0x3); + EXPECT_EQ(p.R(), 0x1f); +} diff --git a/PVRTCEncoder/CMakeLists.txt b/PVRTCEncoder/CMakeLists.txt index 80ef77c..9c3ff6c 100644 --- a/PVRTCEncoder/CMakeLists.txt +++ b/PVRTCEncoder/CMakeLists.txt @@ -56,7 +56,6 @@ INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) SET( HEADERS include/PVRTCCompressor.h - src/Pixel.h src/Block.h src/Image.h ) @@ -64,7 +63,6 @@ SET( HEADERS SET( SOURCES src/Compressor.cpp src/Decompressor.cpp - src/Pixel.cpp src/Block.cpp src/Image.cpp ) @@ -74,5 +72,6 @@ ADD_LIBRARY( PVRTCEncoder ${SOURCES} ) +TARGET_LINK_LIBRARIES( PVRTCEncoder FasTCBase ) TARGET_LINK_LIBRARIES( PVRTCEncoder FasTCCore ) TARGET_LINK_LIBRARIES( PVRTCEncoder FasTCIO ) diff --git a/PVRTCEncoder/src/Block.h b/PVRTCEncoder/src/Block.h index 7404f40..cd5dc91 100644 --- a/PVRTCEncoder/src/Block.h +++ b/PVRTCEncoder/src/Block.h @@ -58,6 +58,7 @@ namespace PVRTCC { +using FasTC::Pixel; class Block { public: Block(): m_LongData(0) { } diff --git a/PVRTCEncoder/src/Compressor.cpp b/PVRTCEncoder/src/Compressor.cpp index 56183b7..7126d6f 100644 --- a/PVRTCEncoder/src/Compressor.cpp +++ b/PVRTCEncoder/src/Compressor.cpp @@ -130,7 +130,7 @@ namespace PVRTCC { uint32 y = i / dcj.width; const uint32 *pixels = reinterpret_cast(dcj.inBuf); - img(x, y).UnpackRGBA(pixels[i]); + img(x, y).Unpack(pixels[i]); } Image original = img; diff --git a/PVRTCEncoder/src/Decompressor.cpp b/PVRTCEncoder/src/Decompressor.cpp index 4365aac..9b7bb5b 100644 --- a/PVRTCEncoder/src/Decompressor.cpp +++ b/PVRTCEncoder/src/Decompressor.cpp @@ -160,7 +160,7 @@ namespace PVRTCC { } uint32 *outPixels = reinterpret_cast(outBuf); - outPixels[(j * w) + i] = result.PackRGBA(); + outPixels[(j * w) + i] = result.Pack(); } } @@ -269,7 +269,7 @@ namespace PVRTCC { } uint32 *outPixels = reinterpret_cast(outBuf); - outPixels[(j * w) + i] = result.PackRGBA(); + outPixels[(j * w) + i] = result.Pack(); } } diff --git a/PVRTCEncoder/src/Image.cpp b/PVRTCEncoder/src/Image.cpp index 0de9335..9ac282f 100644 --- a/PVRTCEncoder/src/Image.cpp +++ b/PVRTCEncoder/src/Image.cpp @@ -476,7 +476,7 @@ void Image::DebugOutput(const char *filename) const { p.ChangeBitDepth(fullDepth); p.A() = 255; - outPixels[idx] = p.PackRGBA(); + outPixels[idx] = p.Pack(); } } diff --git a/PVRTCEncoder/src/Image.h b/PVRTCEncoder/src/Image.h index 959ba4c..33616d3 100644 --- a/PVRTCEncoder/src/Image.h +++ b/PVRTCEncoder/src/Image.h @@ -56,10 +56,14 @@ #include "TexCompTypes.h" #include "PVRTCCompressor.h" +// Forward include +namespace FasTC { + class Pixel; +} + namespace PVRTCC { -class Pixel; - +using FasTC::Pixel; class Image { public: Image(uint32 height, uint32 width); diff --git a/PVRTCEncoder/test/CMakeLists.txt b/PVRTCEncoder/test/CMakeLists.txt index 67a5b20..3f2e1ec 100644 --- a/PVRTCEncoder/test/CMakeLists.txt +++ b/PVRTCEncoder/test/CMakeLists.txt @@ -56,7 +56,7 @@ INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/GTest/include) SET(TESTS - Block Pixel Image Decompressor + Block Image Decompressor ) FOREACH(TEST ${TESTS}) diff --git a/PVRTCEncoder/test/ImageTest.cpp b/PVRTCEncoder/test/ImageTest.cpp index 527e530..ead8ba4 100644 --- a/PVRTCEncoder/test/ImageTest.cpp +++ b/PVRTCEncoder/test/ImageTest.cpp @@ -179,7 +179,7 @@ TEST(Image, BilinearUpscaleMaintainsPixels) { for(uint32 j = 2; j < img.GetHeight(); j+=4) { PVRTCC::Pixel p = img(i, j); uint32 idx = ((j - 2) / 4) * w + ((i-2)/4); - EXPECT_EQ(PixelPrinter(p.PackRGBA()), PixelPrinter(pxs[idx].PackRGBA())); + EXPECT_EQ(PixelPrinter(p.Pack()), PixelPrinter(pxs[idx].Pack())); } } } From 4baf2ce3111ca3bd9f2a4916f53068bc8f9e7ca8 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Fri, 4 Oct 2013 18:35:18 -0400 Subject: [PATCH 03/13] Combine image functionality from PVRTCEncoder into Base library. --- Base/include/Image.h | 120 +++++++---- Base/include/ImageFwd.h | 63 ++++++ Base/src/Image.cpp | 196 ++++++++++++------ Base/test/CMakeLists.txt | 4 +- Base/test/TestImage.cpp | 121 +++++++++++ Base/test/Utils.h | 82 ++++++++ CLTool/src/clunix.cpp | 2 +- Core/include/CompressedImage.h | 22 +- Core/include/TexComp.h | 5 +- Core/src/CompressedImage.cpp | 70 ++++--- Core/src/TexComp.cpp | 44 ++-- IO/config/ImageWriter.h.in | 20 +- IO/include/ImageFile.h | 10 +- IO/src/ImageFile.cpp | 6 +- IO/src/ImageWriter.cpp | 9 +- IO/src/ImageWriterPNG.cpp | 22 +- IO/src/ImageWriterPNG.h | 4 +- PVRTCEncoder/CMakeLists.txt | 4 +- PVRTCEncoder/src/Compressor.cpp | 2 +- PVRTCEncoder/src/Decompressor.cpp | 12 +- .../src/{Image.cpp => PVRTCImage.cpp} | 123 ++++------- PVRTCEncoder/src/{Image.h => PVRTCImage.h} | 27 +-- PVRTCEncoder/test/CMakeLists.txt | 4 +- PVRTCEncoder/test/ImageTest.cpp | 85 +------- 24 files changed, 669 insertions(+), 388 deletions(-) create mode 100644 Base/include/ImageFwd.h create mode 100644 Base/test/TestImage.cpp create mode 100644 Base/test/Utils.h rename PVRTCEncoder/src/{Image.cpp => PVRTCImage.cpp} (79%) rename PVRTCEncoder/src/{Image.h => PVRTCImage.h} (87%) diff --git a/Base/include/Image.h b/Base/include/Image.h index bd34b95..0c0eaec 100644 --- a/Base/include/Image.h +++ b/Base/include/Image.h @@ -41,58 +41,86 @@ * */ -#ifndef __TEXCOMP_IMAGE_H__ -#define __TEXCOMP_IMAGE_H__ +#ifndef FASTC_BASE_INCLUDE_IMAGE_H_ +#define FASTC_BASE_INCLUDE_IMAGE_H_ #include "TexCompTypes.h" +#include "ImageFwd.h" -class Image { +namespace FasTC { - public: - Image(uint32 width, uint32 height, - const uint32 *pixels, - bool bBlockStreamOrder = false); - Image(const Image &); - Image &operator=(const Image &); - virtual ~Image(); + template + extern double ComputePSNR(Image *img1, Image *img2); - virtual Image *Clone() const { - return new Image(*this); + // Forward declare + template + class Image { + + public: + Image(uint32 width, uint32 height); + Image(uint32 width, uint32 height, + const PixelType *pixels, + bool bBlockStreamOrder = false); + Image(uint32 width, uint32 height, + const uint32 *pixels, + bool bBlockStreamOrder = false); + Image(const Image &); + Image &operator=(const Image &); + virtual ~Image(); + + virtual Image *Clone() const { + return new Image(*this); + }; + + PixelType &operator()(uint32 i, uint32 j); + const PixelType &operator()(uint32 i, uint32 j) const; + + // Reads a buffer full of pixels and stores them in the + // data associated with this image. + virtual bool ReadPixels(const uint32 *rgba); + const PixelType *GetPixels() const { return m_Pixels; } + + uint32 GetWidth() const { return m_Width; } + uint32 GetHeight() const { return m_Height; } + uint32 GetNumPixels() const { return GetWidth() * GetHeight(); } + + void SetBlockStreamOrder(bool flag) { + if(flag) { + ConvertToBlockStreamOrder(); + } else { + ConvertFromBlockStreamOrder(); + } + } + bool GetBlockStreamOrder() const { return m_bBlockStreamOrder; } + + template + double ComputePSNR(Image *other) { + return FasTC::ComputePSNR(this, other); + } + + // Function to allow derived classes to populate the pixel array. + // This may involve decompressing a compressed image or otherwise + // processing some data in order to populate the m_Pixels pointer. + // This function should use SetImageData in order to set all of the + // appropriate pixels. + virtual void ComputePixels() { } + + private: + uint32 m_Width; + uint32 m_Height; + + bool m_bBlockStreamOrder; + + PixelType *m_Pixels; + + protected: + + void SetImageData(uint32 width, uint32 height, PixelType *data); + + void ConvertToBlockStreamOrder(); + void ConvertFromBlockStreamOrder(); }; - const uint8 *RawData() const { return m_Data; } - - uint32 GetWidth() const { return m_Width; } - uint32 GetHeight() const { return m_Height; } - - void SetBlockStreamOrder(bool flag) { - if(flag) { - ConvertToBlockStreamOrder(); - } else { - ConvertFromBlockStreamOrder(); - } - } - bool GetBlockStreamOrder() const { return m_bBlockStreamOrder; } - - double ComputePSNR(Image *other); - - virtual void ComputeRGBA() { } - virtual const uint32 *GetRGBA() const { - return reinterpret_cast(RawData()); - } - - private: - uint32 m_Width; - uint32 m_Height; - - bool m_bBlockStreamOrder; - - protected: - uint32 m_DataSz; - uint8 *m_Data; - - void ConvertToBlockStreamOrder(); - void ConvertFromBlockStreamOrder(); -}; +} // namespace FasTC #endif // __TEXCOMP_IMAGE_H__ diff --git a/Base/include/ImageFwd.h b/Base/include/ImageFwd.h new file mode 100644 index 0000000..9204781 --- /dev/null +++ b/Base/include/ImageFwd.h @@ -0,0 +1,63 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#ifndef FASTC_BASE_INCLUDE_IMAGEFWD_H_ +#define FASTC_BASE_INCLUDE_IMAGEFWD_H_ + +#include "TexCompTypes.h" + +namespace FasTC { + class Pixel; + template class Image; +} + +#endif // FASTC_BASE_INCLUDE_IMAGEFWD_H_ diff --git a/Base/src/Image.cpp b/Base/src/Image.cpp index ea61a6e..557af1a 100644 --- a/Base/src/Image.cpp +++ b/Base/src/Image.cpp @@ -49,107 +49,156 @@ #include #include +#include "Pixel.h" + template static inline T sad( const T &a, const T &b ) { return (a > b)? a - b : b - a; } -Image::Image(const Image &other) +namespace FasTC { + +template +Image::Image(uint32 width, uint32 height) + : m_Width(width) + , m_Height(height) + , m_bBlockStreamOrder(false) + , m_Pixels(new PixelType[GetNumPixels()]) +{ } + +template +Image::Image(uint32 width, uint32 height, + const PixelType *pixels, + bool bBlockStreamOrder) + : m_Width(width) + , m_Height(height) + , m_bBlockStreamOrder(false) +{ + if(pixels) { + m_Pixels = new PixelType[GetNumPixels()]; + memcpy(m_Pixels, pixels, GetNumPixels() * sizeof(PixelType)); + } else { + m_Pixels = 0; + } +} + +template +Image::Image(const Image &other) : m_Width(other.m_Width) , m_Height(other.m_Height) , m_bBlockStreamOrder(other.GetBlockStreamOrder()) - , m_DataSz(other.m_DataSz) - , m_Data(new uint8[m_DataSz]) + , m_Pixels(new PixelType[GetNumPixels()]) { - if(m_Data) { - memcpy(m_Data, other.m_Data, m_DataSz); - } else { - fprintf(stderr, "Out of memory!\n"); - } + memcpy(m_Pixels, other.m_Pixels, GetNumPixels() * sizeof(PixelType)); } -Image::Image(uint32 width, uint32 height, const uint32 *pixels, bool bBlockStreamOrder) +template +bool Image::ReadPixels(const uint32 *rgba) { + + assert(m_Pixels); + for(uint32 i = 0; i < GetNumPixels(); i++) { + m_Pixels[i].Unpack(rgba[i]); + } + + return true; +} + +template +Image::Image(uint32 width, uint32 height, const uint32 *pixels, bool bBlockStreamOrder) : m_Width(width) , m_Height(height) , m_bBlockStreamOrder(bBlockStreamOrder) - , m_DataSz(m_Width * m_Height * sizeof(uint32)) { if(pixels) { - m_Data = new uint8[m_DataSz]; - memcpy(m_Data, pixels, m_DataSz); + m_Pixels = new PixelType[GetNumPixels()]; + ReadPixels(pixels); } else { - m_Data = NULL; + m_Pixels = NULL; } } -Image::~Image() { - if(m_Data) { - delete [] m_Data; - m_Data = 0; +template +Image::~Image() { + if(m_Pixels) { + delete [] m_Pixels; + m_Pixels = 0; } } -Image &Image::operator=(const Image &other) { +template +Image &Image::operator=(const Image &other) { m_Width = other.m_Width; m_Height = other.m_Height; m_bBlockStreamOrder = other.GetBlockStreamOrder(); - m_DataSz = other.m_DataSz; - if(m_Data) { - delete [] m_Data; + if(m_Pixels) { + delete [] m_Pixels; } - if(other.m_Data) { - m_Data = new uint8[m_DataSz]; - if(m_Data) - memcpy(m_Data, other.m_Data, m_DataSz); + if(other.m_Pixels) { + m_Pixels = new PixelType[GetNumPixels()]; + if(m_Pixels) + memcpy(m_Pixels, other.m_Pixels, GetNumPixels() * sizeof(PixelType)); else fprintf(stderr, "Out of memory!\n"); + } else { + m_Pixels = NULL; } - else { - m_Data = other.m_Data; - } - + return *this; } -double Image::ComputePSNR(Image *other) { - if(!other) +template +PixelType & Image::operator()(uint32 i, uint32 j) { + assert(i < GetWidth()); + assert(j < GetHeight()); + return m_Pixels[j * GetWidth() + i]; +} + +template +const PixelType & Image::operator()(uint32 i, uint32 j) const { + assert(i < GetWidth()); + assert(j < GetHeight()); + return m_Pixels[j * GetWidth() + i]; +} + +template +double ComputePSNR(Image *img1, Image *img2) { + if(!img1 || !img2) return -1.0; - if(other->GetWidth() != GetWidth() || - other->GetHeight() != GetHeight()) { + if(img1->GetWidth() != img2->GetWidth() || + img1->GetHeight() != img2->GetHeight()) { return -1.0; } // Compute raw 8-bit RGBA data... - other->ComputeRGBA(); - ComputeRGBA(); + img1->ComputePixels(); + img2->ComputePixels(); - const uint8 *ourData = - reinterpret_cast(GetRGBA()); - const uint8 *otherData = - reinterpret_cast(other->GetRGBA()); + const PixelTypeOne *ourPixels = img1->GetPixels(); + const PixelTypeTwo *otherPixels = img2->GetPixels(); // const double w[3] = { 0.2126, 0.7152, 0.0722 }; const double w[3] = { 1.0, 1.0, 1.0 }; double mse = 0.0; - const uint32 imageSz = GetWidth() * GetHeight() * 4; - for(uint32 i = 0; i < imageSz; i+=4) { + const uint32 imageSz = img1->GetNumPixels(); + for(uint32 i = 0; i < imageSz; i++) { - const unsigned char *pixelDataRaw = ourData + i; - const unsigned char *pixelDataUncomp = otherData + i; + uint32 ourPixel = ourPixels[i].Pack(); + uint32 otherPixel = otherPixels[i].Pack(); double r[4], u[4]; for(uint32 c = 0; c < 4; c++) { + uint32 shift = c * 8; if(c == 3) { - r[c] = pixelDataRaw[c] / 255.0; - u[c] = pixelDataUncomp[c] / 255.0; + r[c] = static_cast((ourPixel >> shift) & 0xFF) / 255.0; + u[c] = static_cast((otherPixel >> shift) & 0xFF) / 255.0; } else { - r[c] = static_cast(pixelDataRaw[c]) * w[c]; - u[c] = static_cast(pixelDataUncomp[c]) * w[c]; + r[c] = static_cast((ourPixel >> shift) & 0xFF) * w[c]; + u[c] = static_cast((otherPixel >> shift) & 0xFF) * w[c]; } } @@ -159,19 +208,22 @@ double Image::ComputePSNR(Image *other) { } } - mse /= GetWidth() * GetHeight(); + mse /= img1->GetWidth() * img1->GetHeight(); const double C = 255.0 * 255.0; double maxi = (w[0]*w[0] + w[1]*w[1] + w[2]*w[2]) * C; return 10 * log10(maxi/mse); } +template double ComputePSNR(Image *, Image *); + // !FIXME! These won't work for non-RGBA8 data. -void Image::ConvertToBlockStreamOrder() { - if(m_bBlockStreamOrder || !m_Data) +template +void Image::ConvertToBlockStreamOrder() { + if(m_bBlockStreamOrder || !m_Pixels) return; - uint32 *newPixelData = new uint32[GetWidth() * GetHeight() * 4]; + PixelType *newPixelData = new PixelType[GetWidth() * GetHeight()]; for(uint32 j = 0; j < GetHeight(); j+=4) { for(uint32 i = 0; i < GetWidth(); i+=4) { uint32 blockX = i / 4; @@ -182,22 +234,22 @@ void Image::ConvertToBlockStreamOrder() { for(uint32 t = 0; t < 16; t++) { uint32 x = i + t % 4; uint32 y = j + t / 4; - newPixelData[offset + t] = - reinterpret_cast(m_Data)[y*GetWidth() + x]; + newPixelData[offset + t] = m_Pixels[y*GetWidth() + x]; } } } - delete m_Data; - m_Data = reinterpret_cast(newPixelData); + delete m_Pixels; + m_Pixels = newPixelData; m_bBlockStreamOrder = true; } -void Image::ConvertFromBlockStreamOrder() { - if(!m_bBlockStreamOrder || !m_Data) +template +void Image::ConvertFromBlockStreamOrder() { + if(!m_bBlockStreamOrder || !m_Pixels) return; - uint32 *newPixelData = new uint32[GetWidth() * GetHeight() * 4]; + PixelType *newPixelData = new PixelType[GetWidth() * GetHeight()]; for(uint32 j = 0; j < GetHeight(); j+=4) { for(uint32 i = 0; i < GetWidth(); i+=4) { uint32 blockX = i / 4; @@ -208,13 +260,33 @@ void Image::ConvertFromBlockStreamOrder() { for(uint32 t = 0; t < 16; t++) { uint32 x = i + t % 4; uint32 y = j + t / 4; - newPixelData[y*GetWidth() + x] = - reinterpret_cast(m_Data)[offset + t]; + newPixelData[y*GetWidth() + x] = m_Pixels[offset + t]; } } } - delete m_Data; - m_Data = reinterpret_cast(newPixelData); + delete m_Pixels; + m_Pixels = newPixelData; m_bBlockStreamOrder = false; } + +template +void Image::SetImageData(uint32 width, uint32 height, PixelType *data) { + if(m_Pixels) { + delete m_Pixels; + } + + if(!data) { + width = 0; + height = 0; + m_Pixels = NULL; + } else { + m_Width = width; + m_Height = height; + m_Pixels = data; + } +} + +template class Image; + +} // namespace FasTC diff --git a/Base/test/CMakeLists.txt b/Base/test/CMakeLists.txt index 43fb154..84518f7 100644 --- a/Base/test/CMakeLists.txt +++ b/Base/test/CMakeLists.txt @@ -53,11 +53,11 @@ INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/GTest/include) SET(TESTS - Pixel + Pixel Image ) FOREACH(TEST ${TESTS}) - SET(TEST_NAME Test${TEST}) + SET(TEST_NAME Test_Base_${TEST}) SET(TEST_MODULE Test${TEST}.cpp) ADD_EXECUTABLE(${TEST_NAME} ${TEST_MODULE}) TARGET_LINK_LIBRARIES(${TEST_NAME} FasTCBase) diff --git a/Base/test/TestImage.cpp b/Base/test/TestImage.cpp new file mode 100644 index 0000000..df1ffc7 --- /dev/null +++ b/Base/test/TestImage.cpp @@ -0,0 +1,121 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#include "gtest/gtest.h" +#include "Image.h" +#include "Pixel.h" +#include "Utils.h" + +#include + +TEST(Image, NonSpecificConstructor) { + FasTC::Pixel p; + FasTC::Image img (4, 4); + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + EXPECT_TRUE(img(i, j) == p); + } + } +} + +TEST(Image, SpecificConstructor) { + FasTC::Pixel pxs[16]; + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + pxs[j*4 + i].R() = i; + pxs[j*4 + i].G() = j; + } + } + + FasTC::Image img(4, 4, pxs); + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + EXPECT_TRUE(img(i, j) == pxs[j*4 + i]); + } + } +} + +TEST(Image, CopyConstructor) { + FasTC::Pixel pxs[16]; + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + pxs[j*4 + i].R() = i; + pxs[j*4 + i].G() = j; + } + } + + FasTC::Image img(4, 4, pxs); + FasTC::Image img2(img); + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + EXPECT_TRUE(img2(i, j) == pxs[j*4 + i]); + } + } +} + +TEST(Image, AssignmentOperator) { + FasTC::Pixel pxs[16]; + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + pxs[j*4 + i].R() = i; + pxs[j*4 + i].G() = j; + } + } + + FasTC::Image img(4, 4, pxs); + FasTC::Image img2 = img; + for(uint32 i = 0; i < 4; i++) { + for(uint32 j = 0; j < 4; j++) { + EXPECT_TRUE(img2(i, j) == pxs[j*4 + i]); + } + } +} diff --git a/Base/test/Utils.h b/Base/test/Utils.h new file mode 100644 index 0000000..9c371d3 --- /dev/null +++ b/Base/test/Utils.h @@ -0,0 +1,82 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#ifndef PVRTCENCODER_TEST_TESTUTILS_H_ +#define PVRTCENCODER_TEST_TESTUTILS_H_ + +#include "TexCompTypes.h" + +class PixelPrinter { + private: + uint32 m_PixelValue; + public: + explicit PixelPrinter(uint32 p) : m_PixelValue(p) { } + bool operator==(const PixelPrinter &other) const { + return other.m_PixelValue == this->m_PixelValue; + } + uint32 Value() const { return m_PixelValue; } +}; + +inline ::std::ostream& operator<<(::std::ostream& os, const PixelPrinter& pp) { + uint32 p = pp.Value(); + uint32 r = p & 0xFF; + uint32 g = (p >> 8) & 0xFF; + uint32 b = (p >> 16) & 0xFF; + uint32 a = (p >> 24) & 0xFF; + return os << + "R: 0x" << ::std::hex << r << " " << + "G: 0x" << ::std::hex << g << " " << + "B: 0x" << ::std::hex << b << " " << + "A: 0x" << ::std::hex << a; +} + +#endif // PVRTCENCODER_TEST_TESTUTILS_H_ diff --git a/CLTool/src/clunix.cpp b/CLTool/src/clunix.cpp index e6c4035..24f0e73 100644 --- a/CLTool/src/clunix.cpp +++ b/CLTool/src/clunix.cpp @@ -208,7 +208,7 @@ int main(int argc, char **argv) { return 1; } - Image img = Image(*file.GetImage()); + FasTC::Image<> img(*file.GetImage()); if(format == eCompressionFormat_PVRTC) { img.SetBlockStreamOrder(false); } diff --git a/Core/include/CompressedImage.h b/Core/include/CompressedImage.h index f07818e..930d160 100644 --- a/Core/include/CompressedImage.h +++ b/Core/include/CompressedImage.h @@ -57,10 +57,10 @@ enum ECompressionFormat { #include "Image.h" -class CompressedImage : public Image { +class CompressedImage : public FasTC::Image { private: ECompressionFormat m_Format; - uint32 *m_RGBAData; + uint8 *m_CompressedData; public: CompressedImage(const CompressedImage &); @@ -70,20 +70,19 @@ class CompressedImage : public Image { // the passed format. The size of the data is expected to conform // to the width, height, and format specified. CompressedImage( - const uint32 width, - const uint32 height, - const ECompressionFormat format, + const uint32 width, + const uint32 height, + const ECompressionFormat format, const uint8 *data ); virtual ~CompressedImage(); - virtual Image *Clone() const { + virtual FasTC::Image *Clone() const { return new CompressedImage(*this); } - virtual void ComputeRGBA(); - virtual const uint32 *GetRGBA() const { return m_RGBAData; } + virtual void ComputePixels(); static uint32 GetCompressedSize(uint32 uncompressedSize, ECompressionFormat format); static uint32 GetUncompressedSize(uint32 compressedSize, ECompressionFormat format) { @@ -91,6 +90,13 @@ class CompressedImage : public Image { return compressedSize * (compressedSize / cmp); } + uint32 GetCompressedSize() const { + return GetCompressedSize(GetUncompressedSize(), m_Format); + } + uint32 GetUncompressedSize() const { + return GetWidth() * GetHeight() * sizeof(uint32); + } + // Decompress the compressed image data into outBuf. outBufSz is expected // to be the proper size determined by the width, height, and format. // !FIXME! We should have a function to explicitly return the in/out buf diff --git a/Core/include/TexComp.h b/Core/include/TexComp.h index f62bbd6..bb431c9 100644 --- a/Core/include/TexComp.h +++ b/Core/include/TexComp.h @@ -48,9 +48,9 @@ #include "CompressionJob.h" #include +#include "ImageFwd.h" // Forward declarations -class Image; class ImageFile; struct SCompressionSettings { @@ -91,7 +91,8 @@ struct SCompressionSettings { std::ostream *logStream; }; -extern CompressedImage *CompressImage(Image *img, const SCompressionSettings &settings); +template +extern CompressedImage *CompressImage(FasTC::Image *img, const SCompressionSettings &settings); extern bool CompressImageData( const unsigned char *data, diff --git a/Core/src/CompressedImage.cpp b/Core/src/CompressedImage.cpp index cc68fe4..f6f4f1f 100644 --- a/Core/src/CompressedImage.cpp +++ b/Core/src/CompressedImage.cpp @@ -48,6 +48,8 @@ #include #include +#include "Pixel.h" + #include "TexCompTypes.h" #include "BC7Compressor.h" #include "PVRTCCompressor.h" @@ -55,11 +57,12 @@ CompressedImage::CompressedImage( const CompressedImage &other ) : Image(other) , m_Format(other.m_Format) - , m_RGBAData(0) + , m_CompressedData(0) { - if(other.m_RGBAData) { - m_RGBAData = new uint32[GetWidth() * GetHeight()]; - memcpy(m_RGBAData, other.m_RGBAData, sizeof(uint32) * GetWidth() * GetHeight()); + if(other.m_CompressedData) { + uint32 compressedSz = GetCompressedSize(); + m_CompressedData = new uint8[compressedSz]; + memcpy(m_CompressedData, other.m_CompressedData, compressedSz); } } @@ -69,47 +72,44 @@ CompressedImage::CompressedImage( const ECompressionFormat format, const unsigned char *data ) - : Image(width, height, NULL, format != eCompressionFormat_PVRTC) + : FasTC::Image<>(width, height, + reinterpret_cast(NULL), + format != eCompressionFormat_PVRTC) , m_Format(format) - , m_RGBAData(0) + , m_CompressedData(0) { - m_DataSz = GetCompressedSize(GetWidth() * GetHeight() * 4, m_Format); - if(m_DataSz > 0) { - assert(!m_Data); - m_Data = new unsigned char[m_DataSz]; - memcpy(m_Data, data, m_DataSz); + uint32 cmpSz = GetCompressedSize(); + if(cmpSz > 0) { + assert(!m_CompressedData); + m_CompressedData = new uint8[cmpSz]; + memcpy(m_CompressedData, data, cmpSz); } } CompressedImage &CompressedImage::operator=(const CompressedImage &other) { Image::operator=(other); m_Format = other.m_Format; - if(other.m_RGBAData) { - m_RGBAData = new uint32[GetWidth() * GetHeight()]; - memcpy(m_RGBAData, other.m_RGBAData, sizeof(uint32) * GetWidth() * GetHeight()); + if(other.m_CompressedData) { + uint32 cmpSz = GetCompressedSize(); + m_CompressedData = new uint8[cmpSz]; + memcpy(m_CompressedData, other.m_CompressedData, cmpSz); } return *this; } CompressedImage::~CompressedImage() { - if(m_RGBAData) { - delete m_RGBAData; - m_RGBAData = NULL; + if(m_CompressedData) { + delete m_CompressedData; + m_CompressedData = NULL; } } bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBufSz) const { - // First make sure that we have enough data - uint32 dataSz = GetUncompressedSize(m_DataSz, m_Format); - if(dataSz > outBufSz) { - fprintf(stderr, "Not enough space to store entire decompressed image! " - "Got %d bytes, but need %d!\n", outBufSz, dataSz); - assert(false); - return false; - } + assert(outBufSz == GetUncompressedSize()); - DecompressionJob dj (m_Data, outBuf, GetWidth(), GetHeight()); + uint8 *byteData = reinterpret_cast(m_CompressedData); + DecompressionJob dj (byteData, outBuf, GetWidth(), GetHeight()); switch(m_Format) { case eCompressionFormat_PVRTC: { @@ -135,15 +135,20 @@ bool CompressedImage::DecompressImage(unsigned char *outBuf, unsigned int outBuf return true; } -void CompressedImage::ComputeRGBA() { +void CompressedImage::ComputePixels() { - if(m_RGBAData) { - delete m_RGBAData; + uint32 unCompSz = GetWidth() * GetHeight() * 4; + uint8 *unCompBuf = new uint8[unCompSz]; + DecompressImage(unCompBuf, unCompSz); + + uint32 * newPixelBuf = reinterpret_cast(unCompBuf); + + FasTC::Pixel *newPixels = new FasTC::Pixel[GetWidth() * GetHeight()]; + for(uint32 i = 0; i < GetWidth() * GetHeight(); i++) { + newPixels[i].Unpack(newPixelBuf[i]); } - m_RGBAData = new uint32[GetWidth() * GetHeight()]; - uint8 *pixelData = reinterpret_cast(m_RGBAData); - DecompressImage(pixelData, GetWidth() * GetHeight() * 4); + SetImageData(GetWidth(), GetHeight(), newPixels); } uint32 CompressedImage::GetCompressedSize(uint32 uncompressedSize, ECompressionFormat format) { @@ -167,4 +172,3 @@ uint32 CompressedImage::GetCompressedSize(uint32 uncompressedSize, ECompressionF return cmpDataSzNeeded; } - diff --git a/Core/src/TexComp.cpp b/Core/src/TexComp.cpp index ee91714..2d4d03a 100644 --- a/Core/src/TexComp.cpp +++ b/Core/src/TexComp.cpp @@ -54,6 +54,7 @@ #include "CompressionFuncs.h" #include "Image.h" #include "ImageFile.h" +#include "Pixel.h" #include "PVRTCCompressor.h" #include "Thread.h" #include "ThreadGroup.h" @@ -349,8 +350,9 @@ static double CompressImageWithWorkerQueue( return cmpTimeTotal / double(settings.iNumCompressions); } +template CompressedImage *CompressImage( - Image *img, const SCompressionSettings &settings + FasTC::Image *img, const SCompressionSettings &settings ) { if(!img) return NULL; @@ -359,6 +361,7 @@ CompressedImage *CompressImage( CompressedImage *outImg = NULL; const unsigned int dataSz = w * h * 4; + uint32 *data = new uint32[dataSz / 4]; assert(dataSz > 0); @@ -366,24 +369,33 @@ CompressedImage *CompressImage( uint32 cmpDataSz = CompressedImage::GetCompressedSize(dataSz, settings.format); // Make sure that we have RGBA data... - img->ComputeRGBA(); + img->ComputePixels(); + const PixelType *pixels = img->GetPixels(); + for(uint32 i = 0; i < img->GetNumPixels(); i++) { + data[i] = pixels[i].Pack(); + } unsigned char *cmpData = new unsigned char[cmpDataSz]; - const uint8 *pixelData = reinterpret_cast(img->GetRGBA()); - CompressImageData(pixelData, w, h, cmpData, cmpDataSz, settings); + CompressImageData(reinterpret_cast(data), w, h, cmpData, cmpDataSz, settings); outImg = new CompressedImage(w, h, settings.format, cmpData); + delete [] data; delete [] cmpData; return outImg; } +// !FIXME! Ideally, we wouldn't have to do this because there would be a way to instantiate this +// function in the header or using some fancy template metaprogramming. I can't think of the way +// at the moment. +template CompressedImage *CompressImage(FasTC::Image *, const SCompressionSettings &settings); + bool CompressImageData( - const unsigned char *data, - const unsigned int width, - const unsigned int height, - unsigned char *cmpData, - const unsigned int cmpDataSz, + const uint8 *data, + const uint32 width, + const uint32 height, + uint8 *compressedData, + const uint32 cmpDataSz, const SCompressionSettings &settings ) { @@ -417,14 +429,14 @@ bool CompressImageData( } // Allocate data based on the compression method - uint32 cmpDataSzNeeded = + uint32 compressedDataSzNeeded = CompressedImage::GetCompressedSize(dataSz, settings.format); - if(cmpDataSzNeeded == 0) { + if(compressedDataSzNeeded == 0) { ReportError("Unknown compression format"); return false; } - else if(cmpDataSzNeeded > cmpDataSz) { + else if(compressedDataSzNeeded > cmpDataSz) { ReportError("Not enough space for compressed data!"); return false; } @@ -436,15 +448,15 @@ bool CompressImageData( if(numThreads > 1) { if(settings.bUseAtomics) { - cmpMSTime = CompressImageWithAtomics(data, width, height, settings, cmpData); + cmpMSTime = CompressImageWithAtomics(data, width, height, settings, compressedData); } else if(settings.iJobSize > 0) { - cmpMSTime = CompressImageWithWorkerQueue(data, dataSz, settings, cmpData); + cmpMSTime = CompressImageWithWorkerQueue(data, dataSz, settings, compressedData); } else { - cmpMSTime = CompressImageWithThreads(data, dataSz, settings, cmpData); + cmpMSTime = CompressImageWithThreads(data, dataSz, settings, compressedData); } } else { - cmpMSTime = CompressImageInSerial(data, width, height, settings, cmpData); + cmpMSTime = CompressImageInSerial(data, width, height, settings, compressedData); } // Report compression time diff --git a/IO/config/ImageWriter.h.in b/IO/config/ImageWriter.h.in index c876a08..0d609d5 100644 --- a/IO/config/ImageWriter.h.in +++ b/IO/config/ImageWriter.h.in @@ -47,19 +47,23 @@ #include "ImageFileFormat.h" #include "TexCompTypes.h" +namespace FasTC { + class Pixel; +} + class ImageWriter { protected: - const uint8 *m_PixelData; + const FasTC::Pixel *m_Pixels; uint32 m_RawFileDataSz; uint8 *m_RawFileData; uint32 m_Width; uint32 m_Height; - ImageWriter(const int width, const int height, const uint8 *rawData) - : m_PixelData(rawData) + ImageWriter(const int width, const int height, const FasTC::Pixel *rawData) + : m_Pixels(rawData) , m_RawFileDataSz(256) , m_RawFileData(new uint8[m_RawFileDataSz]) , m_Width(width), m_Height(height) @@ -69,15 +73,15 @@ class ImageWriter { public: virtual ~ImageWriter() { - if(m_RawFileData) { - delete m_RawFileData; - m_RawFileData = 0; - } + if(m_RawFileData) { + delete m_RawFileData; + m_RawFileData = 0; + } } uint32 GetWidth() const { return m_Width; } uint32 GetHeight() const { return m_Height; } - uint32 GetImageDataSz() const { return m_Width * m_Height * 4; } + uint32 GetImageDataSz() const { return m_Width * m_Height * sizeof(uint32); } uint32 GetRawFileDataSz() const { return m_RawFileDataSz; } uint8 *GetRawFileData() const { return m_RawFileData; } virtual bool WriteImage() = 0; diff --git a/IO/include/ImageFile.h b/IO/include/ImageFile.h index eb365c6..6c2bbfe 100644 --- a/IO/include/ImageFile.h +++ b/IO/include/ImageFile.h @@ -46,9 +46,9 @@ #include "TexCompTypes.h" #include "ImageFileFormat.h" +#include "ImageFwd.h" // Forward declare -class Image; class CompressedImage; struct SCompressionSettings; @@ -66,13 +66,13 @@ public: // Creates an imagefile with the corresponding image data. This is ready // to be written to disk with the passed filename. - ImageFile(const char *filename, EImageFileFormat format, const Image &); + ImageFile(const char *filename, EImageFileFormat format, const FasTC::Image<> &); ~ImageFile(); unsigned int GetWidth() const { return m_Width; } unsigned int GetHeight() const { return m_Height; } - Image *GetImage() const { return m_Image; } + FasTC::Image<> *GetImage() const { return m_Image; } // Loads the image into memory. If this function returns true, then a valid // m_Image will be created and available. @@ -91,12 +91,12 @@ public: const EImageFileFormat m_FileFormat; - Image *m_Image; + FasTC::Image<> *m_Image; static unsigned char *ReadFileData(const CHAR *filename); static bool WriteImageDataToFile(const uint8 *data, const uint32 dataSz, const CHAR *filename); static EImageFileFormat DetectFileFormat(const CHAR *filename); - Image *LoadImage(const unsigned char *rawImageData) const; + FasTC::Image<> *LoadImage(const unsigned char *rawImageData) const; }; #endif // _IMAGE_FILE_H_ diff --git a/IO/src/ImageFile.cpp b/IO/src/ImageFile.cpp index 293bc9b..8b29a34 100644 --- a/IO/src/ImageFile.cpp +++ b/IO/src/ImageFile.cpp @@ -105,7 +105,7 @@ ImageFile::ImageFile(const CHAR *filename, EImageFileFormat format) strncpy(m_Filename, filename, kMaxFilenameSz); } -ImageFile::ImageFile(const char *filename, EImageFileFormat format, const Image &image) +ImageFile::ImageFile(const char *filename, EImageFileFormat format, const FasTC::Image<> &image) : m_FileFormat(format) , m_Image(image.Clone()) { @@ -165,7 +165,7 @@ bool ImageFile::Write() { return true; } -Image *ImageFile::LoadImage(const unsigned char *rawImageData) const { +FasTC::Image<> *ImageFile::LoadImage(const unsigned char *rawImageData) const { ImageLoader *loader = NULL; switch(m_FileFormat) { @@ -207,7 +207,7 @@ Image *ImageFile::LoadImage(const unsigned char *rawImageData) const { } uint32 *pixels = reinterpret_cast(pixelData); - Image *i = new Image(loader->GetWidth(), loader->GetHeight(), pixels, true); + FasTC::Image<> *i = new FasTC::Image<>(loader->GetWidth(), loader->GetHeight(), pixels, true); // Cleanup delete loader; diff --git a/IO/src/ImageWriter.cpp b/IO/src/ImageWriter.cpp index a01ec50..17e3ac8 100644 --- a/IO/src/ImageWriter.cpp +++ b/IO/src/ImageWriter.cpp @@ -42,6 +42,7 @@ */ #include "ImageWriter.h" +#include "Pixel.h" uint32 ImageWriter::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) { @@ -58,10 +59,8 @@ uint32 ImageWriter::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) { const uint32 blockOffsetY = y % 4; const uint32 pixelOffset = blockOffsetY * 4 + blockOffsetX; - // There are 16 pixels per block and bytes per pixel... - uint32 dataOffset = blockIdx * 4 * 16; - dataOffset += 4 * pixelOffset; - dataOffset += ch; + // There are 16 pixels per block... + uint32 dataOffset = blockIdx * 16 + pixelOffset; - return m_PixelData[dataOffset]; + return m_Pixels[dataOffset].Component(ch); } diff --git a/IO/src/ImageWriterPNG.cpp b/IO/src/ImageWriterPNG.cpp index d9d1344..1013253 100644 --- a/IO/src/ImageWriterPNG.cpp +++ b/IO/src/ImageWriterPNG.cpp @@ -43,14 +43,15 @@ #include "ImageWriterPNG.h" -#include -#include -#include - -#include "Image.h" +#include +#include +#include #include +#include "Image.h" +#include "Pixel.h" + class PNGStreamWriter { public: static void WriteDataToStream( @@ -84,13 +85,13 @@ public: }; -ImageWriterPNG::ImageWriterPNG(Image &im) - : ImageWriter(im.GetWidth(), im.GetHeight(), im.RawData()) +ImageWriterPNG::ImageWriterPNG(FasTC::Image<> &im) + : ImageWriter(im.GetWidth(), im.GetHeight(), im.GetPixels()) , m_bBlockStreamOrder(im.GetBlockStreamOrder()) , m_StreamPosition(0) { - im.ComputeRGBA(); - m_PixelData = reinterpret_cast(im.GetRGBA()); + im.ComputePixels(); + m_Pixels = im.GetPixels(); } bool ImageWriterPNG::WriteImage() { @@ -136,8 +137,7 @@ bool ImageWriterPNG::WriteImage() { *row++ = GetChannelForPixel(x, y, ch); } } else { - reinterpret_cast(row)[x] = - reinterpret_cast(m_PixelData)[y * m_Width + x]; + reinterpret_cast(row)[x] = m_Pixels[y * m_Width + x].Pack(); } } } diff --git a/IO/src/ImageWriterPNG.h b/IO/src/ImageWriterPNG.h index 3b4c515..5bd03ca 100644 --- a/IO/src/ImageWriterPNG.h +++ b/IO/src/ImageWriterPNG.h @@ -45,12 +45,12 @@ #define _IMAGE_WRITER_PNG_H_ #include "ImageWriter.h" +#include "ImageFwd.h" // Forward Declare -class Image; class ImageWriterPNG : public ImageWriter { public: - ImageWriterPNG(Image &); + ImageWriterPNG(FasTC::Image<> &); virtual ~ImageWriterPNG() { } virtual bool WriteImage(); diff --git a/PVRTCEncoder/CMakeLists.txt b/PVRTCEncoder/CMakeLists.txt index 9c3ff6c..1f0df2d 100644 --- a/PVRTCEncoder/CMakeLists.txt +++ b/PVRTCEncoder/CMakeLists.txt @@ -57,14 +57,14 @@ INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) SET( HEADERS include/PVRTCCompressor.h src/Block.h - src/Image.h + src/PVRTCImage.h ) SET( SOURCES src/Compressor.cpp src/Decompressor.cpp src/Block.cpp - src/Image.cpp + src/PVRTCImage.cpp ) ADD_LIBRARY( PVRTCEncoder diff --git a/PVRTCEncoder/src/Compressor.cpp b/PVRTCEncoder/src/Compressor.cpp index 7126d6f..1620a2c 100644 --- a/PVRTCEncoder/src/Compressor.cpp +++ b/PVRTCEncoder/src/Compressor.cpp @@ -58,7 +58,7 @@ #include #include "Pixel.h" -#include "Image.h" +#include "PVRTCImage.h" #include "Block.h" namespace PVRTCC { diff --git a/PVRTCEncoder/src/Decompressor.cpp b/PVRTCEncoder/src/Decompressor.cpp index 9b7bb5b..7fb66fc 100644 --- a/PVRTCEncoder/src/Decompressor.cpp +++ b/PVRTCEncoder/src/Decompressor.cpp @@ -57,7 +57,7 @@ #include "Pixel.h" #include "Block.h" -#include "Image.h" +#include "PVRTCImage.h" namespace PVRTCC { @@ -94,7 +94,7 @@ namespace PVRTCC { assert(imgA.GetWidth() == imgB.GetWidth()); assert(imgA.GetHeight() == imgB.GetHeight()); - Image debugModulation(h, w); + Image debugModulation(w, h); const uint8 debugModulationBitDepth[4] = { 8, 4, 4, 4 }; debugModulation.ChangeBitDepth(debugModulationBitDepth); @@ -113,7 +113,6 @@ namespace PVRTCC { const Pixel &pa = imgA(i, j); const Pixel &pb = imgB(i, j); - Pixel result; bool punchThrough = false; uint8 lerpVal = 0; if(b.GetModeBit()) { @@ -147,6 +146,7 @@ namespace PVRTCC { } } + Pixel result; for(uint32 c = 0; c < 4; c++) { uint16 va = static_cast(pa.Component(c)); uint16 vb = static_cast(pb.Component(c)); @@ -274,7 +274,7 @@ namespace PVRTCC { } if(bDebugImages) { - Image dbgMod(h, w); + Image dbgMod(w, h); for(uint32 i = 0; i < h*w; i++) { float fb = static_cast(modValues[i]); uint8 val = static_cast((fb / 8.0f) * 15.0f); @@ -324,8 +324,8 @@ namespace PVRTCC { assert(blocks.size() > 0); // Extract the endpoints into A and B images - Image imgA(blocksH, blocksW); - Image imgB(blocksH, blocksW); + Image imgA(blocksW, blocksH); + Image imgB(blocksW, blocksH); for(uint32 j = 0; j < blocksH; j++) { for(uint32 i = 0; i < blocksW; i++) { diff --git a/PVRTCEncoder/src/Image.cpp b/PVRTCEncoder/src/PVRTCImage.cpp similarity index 79% rename from PVRTCEncoder/src/Image.cpp rename to PVRTCEncoder/src/PVRTCImage.cpp index 9ac282f..d6beb2f 100644 --- a/PVRTCEncoder/src/Image.cpp +++ b/PVRTCEncoder/src/PVRTCImage.cpp @@ -55,7 +55,7 @@ # define snprintf _snprintf #endif -#include "Image.h" +#include "PVRTCImage.h" #include #include @@ -80,55 +80,39 @@ static float ConvertChannelToFloat(uint8 channel, uint8 bitDepth) { namespace PVRTCC { -Image::Image(uint32 height, uint32 width) - : m_Width(width) - , m_Height(height) - , m_Pixels(new Pixel[width * height]) - , m_FractionalPixels(new Pixel[width * height]) { +Image::Image(uint32 width, uint32 height) + : FasTC::Image(width, height) + , m_FractionalPixels(new FasTC::Pixel[width * height]) { assert(width > 0); assert(height > 0); } -Image::Image(uint32 height, uint32 width, const Pixel *pixels) - : m_Width(width) - , m_Height(height) - , m_Pixels(new Pixel[width * height]) - , m_FractionalPixels(new Pixel[width * height]) { +Image::Image(uint32 width, uint32 height, const FasTC::Pixel *pixels) + : FasTC::Image(width, height, pixels) + , m_FractionalPixels(new FasTC::Pixel[width * height]) { assert(width > 0); assert(height > 0); - memcpy(m_Pixels, pixels, width * height * sizeof(Pixel)); } Image::Image(const Image &other) - : m_Width(other.GetWidth()) - , m_Height(other.GetHeight()) - , m_Pixels(new Pixel[other.GetWidth() * other.GetHeight()]) - , m_FractionalPixels(new Pixel[other.GetWidth() * other.GetHeight()]) { - memcpy(m_Pixels, other.m_Pixels, GetWidth() * GetHeight() * sizeof(Pixel)); + : FasTC::Image(other) + , m_FractionalPixels(new FasTC::Pixel[other.GetWidth() * other.GetHeight()]) { + memcpy(m_FractionalPixels, other.m_FractionalPixels, GetWidth() * GetHeight() * sizeof(FasTC::Pixel)); } Image &Image::operator=(const Image &other) { - m_Width = other.GetWidth(); - m_Height = other.GetHeight(); - - assert(m_Pixels); - delete m_Pixels; - m_Pixels = new Pixel[other.GetWidth() * other.GetHeight()]; - memcpy(m_Pixels, other.m_Pixels, GetWidth() * GetHeight() * sizeof(Pixel)); + FasTC::Image::operator=(other); assert(m_FractionalPixels); delete m_FractionalPixels; - m_FractionalPixels = new Pixel[other.GetWidth() * other.GetHeight()]; + m_FractionalPixels = new FasTC::Pixel[other.GetWidth() * other.GetHeight()]; memcpy(m_FractionalPixels, other.m_FractionalPixels, - GetWidth() * GetHeight() * sizeof(Pixel)); + GetWidth() * GetHeight() * sizeof(FasTC::Pixel)); return *this; } Image::~Image() { - assert(m_Pixels); - delete [] m_Pixels; - assert(m_FractionalPixels); delete [] m_FractionalPixels; } @@ -155,18 +139,18 @@ void Image::BilinearUpscale(uint32 xtimes, uint32 ytimes, const uint32 yscale = 1 << ytimes; const uint32 yoffset = yscale >> 1; - Pixel *upscaledPixels = new Pixel[newWidth * newHeight]; + FasTC::Pixel *upscaledPixels = new FasTC::Pixel[newWidth * newHeight]; assert(m_FractionalPixels); delete m_FractionalPixels; - m_FractionalPixels = new Pixel[newWidth * newHeight]; + m_FractionalPixels = new FasTC::Pixel[newWidth * newHeight]; for(uint32 j = 0; j < newHeight; j++) { for(uint32 i = 0; i < newWidth; i++) { const uint32 pidx = j * newWidth + i; - Pixel &p = upscaledPixels[pidx]; - Pixel &fp = m_FractionalPixels[pidx]; + FasTC::Pixel &p = upscaledPixels[pidx]; + FasTC::Pixel &fp = m_FractionalPixels[pidx]; const int32 highXIdx = (i + xoffset) / xscale; const int32 lowXIdx = highXIdx - 1; @@ -183,10 +167,10 @@ void Image::BilinearUpscale(uint32 xtimes, uint32 ytimes, const uint32 bottomLeftWeight = lowXWeight * highYWeight; const uint32 bottomRightWeight = highXWeight * highYWeight; - const Pixel &topLeft = GetPixel(lowXIdx, lowYIdx, wrapMode); - const Pixel &topRight = GetPixel(highXIdx, lowYIdx, wrapMode); - const Pixel &bottomLeft = GetPixel(lowXIdx, highYIdx, wrapMode); - const Pixel &bottomRight = GetPixel(highXIdx, highYIdx, wrapMode); + const FasTC::Pixel &topLeft = GetPixel(lowXIdx, lowYIdx, wrapMode); + const FasTC::Pixel &topRight = GetPixel(highXIdx, lowYIdx, wrapMode); + const FasTC::Pixel &bottomLeft = GetPixel(lowXIdx, highYIdx, wrapMode); + const FasTC::Pixel &bottomRight = GetPixel(highXIdx, highYIdx, wrapMode); // Make sure the bit depth matches the original... uint8 bitDepth[4]; @@ -224,10 +208,7 @@ void Image::BilinearUpscale(uint32 xtimes, uint32 ytimes, } } - delete m_Pixels; - m_Pixels = upscaledPixels; - m_Width = newWidth; - m_Height = newHeight; + SetImageData(newWidth, newHeight, upscaledPixels); } void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes, @@ -238,11 +219,11 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes, const uint32 newWidth = w >> xtimes; const uint32 newHeight = h >> ytimes; - Pixel *downscaledPixels = new Pixel[newWidth * newHeight]; + FasTC::Pixel *downscaledPixels = new FasTC::Pixel[newWidth * newHeight]; const uint32 numDownscaledPixels = newWidth * newHeight; uint8 bitDepth[4]; - m_Pixels[0].GetBitDepth(bitDepth); + GetPixels()[0].GetBitDepth(bitDepth); for(uint32 i = 0; i < numDownscaledPixels; i++) { downscaledPixels[i].ChangeBitDepth(bitDepth); @@ -282,10 +263,10 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes, for(uint32 i = 0; i < w * h; i++) { // First convert the pixel values to floats using // premultiplied alpha... - float a = ConvertChannelToFloat(m_Pixels[i].A(), bitDepth[0]); - float r = a * ConvertChannelToFloat(m_Pixels[i].R(), bitDepth[1]); - float g = a * ConvertChannelToFloat(m_Pixels[i].G(), bitDepth[2]); - float b = a * ConvertChannelToFloat(m_Pixels[i].B(), bitDepth[3]); + float a = ConvertChannelToFloat(GetPixels()[i].A(), bitDepth[0]); + float r = a * ConvertChannelToFloat(GetPixels()[i].R(), bitDepth[1]); + float g = a * ConvertChannelToFloat(GetPixels()[i].G(), bitDepth[2]); + float b = a * ConvertChannelToFloat(GetPixels()[i].B(), bitDepth[3]); I[i] = r * 0.21f + g * 0.71f + b * 0.07f; } @@ -308,7 +289,7 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes, Iy[idx] = (I[yphidx] - I[ymhidx]) / 2.0f; for(uint32 c = 0; c <= 3; c++) { - #define CPNT(dx) ConvertChannelToFloat(m_Pixels[dx].Component(c), bitDepth[c]) + #define CPNT(dx) ConvertChannelToFloat(GetPixels()[dx].Component(c), bitDepth[c]) Ix[c][idx] = (CPNT(xphidx) - CPNT(xmhidx)) / 2.0f; Ixx[c][idx] = (CPNT(xphidx) - 2.0f*CPNT(idx) + CPNT(xmhidx)) / 2.0f; Iyy[c][idx] = (CPNT(yphidx) - 2.0f*CPNT(idx) + CPNT(ymhidx)) / 2.0f; @@ -339,9 +320,9 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes, } uint32 idx = GetPixelIndex(x, y); - Pixel current = m_Pixels[idx]; + FasTC::Pixel current = GetPixels()[idx]; - Pixel result; + FasTC::Pixel result; result.ChangeBitDepth(bitDepth); float Ixsq = Ix[4][idx] * Ix[4][idx]; @@ -364,26 +345,21 @@ void Image::ContentAwareDownscale(uint32 xtimes, uint32 ytimes, } } - delete m_Pixels; - m_Pixels = downscaledPixels; - m_Width = newWidth; - m_Height = newHeight; - + SetImageData(newWidth, newHeight, downscaledPixels); delete [] imgData; } void Image::ChangeBitDepth(const uint8 (&depths)[4]) { for(uint32 j = 0; j < GetHeight(); j++) { for(uint32 i = 0; i < GetWidth(); i++) { - uint32 pidx = j * GetWidth() + i; - m_Pixels[pidx].ChangeBitDepth(depths); + (*this)(i, j).ChangeBitDepth(depths); } } } void Image::ExpandTo8888() { uint8 currentDepth[4]; - m_Pixels[0].GetBitDepth(currentDepth); + GetPixels()[0].GetBitDepth(currentDepth); uint8 fractionDepth[4]; const uint8 fullDepth[4] = { 8, 8, 8, 8 }; @@ -391,8 +367,10 @@ void Image::ExpandTo8888() { for(uint32 j = 0; j < GetHeight(); j++) { for(uint32 i = 0; i < GetWidth(); i++) { + FasTC::Pixel &p = (*this)(i, j); + p.ChangeBitDepth(fullDepth); + uint32 pidx = j * GetWidth() + i; - m_Pixels[pidx].ChangeBitDepth(fullDepth); m_FractionalPixels[pidx].GetBitDepth(fractionDepth); for(uint32 c = 0; c < 4; c++) { @@ -402,17 +380,17 @@ void Image::ExpandTo8888() { uint32 shift = fractionDepth[c] - (fullDepth[c] - currentDepth[c]); uint32 fractionBits = m_FractionalPixels[pidx].Component(c) >> shift; - uint32 component = m_Pixels[pidx].Component(c); + uint32 component = p.Component(c); component += ((fractionBits * numerator) / denominator); - m_Pixels[pidx].Component(c) = component; + p.Component(c) = component; } } } } -const Pixel &Image::GetPixel(int32 i, int32 j, EWrapMode wrapMode) const { - return m_Pixels[GetPixelIndex(i, j, wrapMode)]; +const FasTC::Pixel &Image::GetPixel(int32 i, int32 j, EWrapMode wrapMode) const { + return GetPixels()[GetPixelIndex(i, j, wrapMode)]; } const uint32 Image::GetPixelIndex(int32 i, int32 j, EWrapMode wrapMode) const { @@ -454,33 +432,20 @@ const uint32 Image::GetPixelIndex(int32 i, int32 j, EWrapMode wrapMode) const { return idx; } -Pixel & Image::operator()(uint32 i, uint32 j) { - assert(i < GetWidth()); - assert(j < GetHeight()); - return m_Pixels[j * GetWidth() + i]; -} - -const Pixel & Image::operator()(uint32 i, uint32 j) const { - assert(i < GetWidth()); - assert(j < GetHeight()); - return m_Pixels[j * GetWidth() + i]; -} - void Image::DebugOutput(const char *filename) const { uint32 *outPixels = new uint32[GetWidth() * GetHeight()]; const uint8 fullDepth[4] = { 8, 8, 8, 8 }; for(uint32 j = 0; j < GetHeight(); j++) { for(uint32 i = 0; i < GetWidth(); i++) { - uint32 idx = j * GetWidth() + i; - Pixel p = m_Pixels[idx]; + FasTC::Pixel p = (*this)(i, j); p.ChangeBitDepth(fullDepth); p.A() = 255; - outPixels[idx] = p.Pack(); + outPixels[j*GetWidth() + i] = p.Pack(); } } - ::Image img(GetWidth(), GetHeight(), outPixels); + FasTC::Image<> img(GetWidth(), GetHeight(), outPixels); char debugFilename[256]; snprintf(debugFilename, sizeof(debugFilename), "%s.png", filename); diff --git a/PVRTCEncoder/src/Image.h b/PVRTCEncoder/src/PVRTCImage.h similarity index 87% rename from PVRTCEncoder/src/Image.h rename to PVRTCEncoder/src/PVRTCImage.h index 33616d3..69bfe73 100644 --- a/PVRTCEncoder/src/Image.h +++ b/PVRTCEncoder/src/PVRTCImage.h @@ -55,6 +55,7 @@ #include "TexCompTypes.h" #include "PVRTCCompressor.h" +#include "Image.h" // Forward include namespace FasTC { @@ -63,15 +64,13 @@ namespace FasTC { namespace PVRTCC { -using FasTC::Pixel; -class Image { +class Image : public FasTC::Image { public: - Image(uint32 height, uint32 width); - Image(uint32 height, uint32 width, const Pixel *pixels); + Image(uint32 width, uint32 height); + Image(uint32 width, uint32 height, const FasTC::Pixel *pixels); Image(const Image &); Image &operator=(const Image &); - ~Image(); - + virtual ~Image(); void BilinearUpscale(uint32 xtimes, uint32 ytimes, EWrapMode wrapMode = eWrapMode_Wrap); @@ -84,25 +83,15 @@ class Image { EWrapMode wrapMode = eWrapMode_Wrap, bool bOffsetNewPixels = false); - void ChangeBitDepth(const uint8 (&depths)[4]); void ExpandTo8888(); - - Pixel &operator()(uint32 i, uint32 j); - const Pixel &operator()(uint32 i, uint32 j) const; - - uint32 GetWidth() const { return m_Width; } - uint32 GetHeight() const { return m_Height; } - + void ChangeBitDepth(const uint8 (&depths)[4]); void DebugOutput(const char *filename) const; private: - uint32 m_Width; - uint32 m_Height; - Pixel *m_Pixels; - Pixel *m_FractionalPixels; + FasTC::Pixel *m_FractionalPixels; const uint32 GetPixelIndex(int32 i, int32 j, EWrapMode wrapMode = eWrapMode_Clamp) const; - const Pixel &GetPixel(int32 i, int32 j, EWrapMode wrapMode = eWrapMode_Clamp) const; + const FasTC::Pixel &GetPixel(int32 i, int32 j, EWrapMode wrapMode = eWrapMode_Clamp) const; }; } // namespace PVRTCC diff --git a/PVRTCEncoder/test/CMakeLists.txt b/PVRTCEncoder/test/CMakeLists.txt index 3f2e1ec..75889ed 100644 --- a/PVRTCEncoder/test/CMakeLists.txt +++ b/PVRTCEncoder/test/CMakeLists.txt @@ -60,7 +60,7 @@ SET(TESTS ) FOREACH(TEST ${TESTS}) - SET(TEST_NAME Test${TEST}) + SET(TEST_NAME Test_PVRTCEncoder_${TEST}) SET(TEST_MODULE ${TEST}Test.cpp) ADD_EXECUTABLE(${TEST_NAME} ${TEST_MODULE}) TARGET_LINK_LIBRARIES(${TEST_NAME} PVRTCEncoder) @@ -71,7 +71,7 @@ ENDFOREACH() # Test the decompressor against the included PVR Texture library.... IF(PVRTEXLIB_FOUND) - SET(TEST_NAME TestDecompVersusPVRLib) + SET(TEST_NAME Test_PVRTCEncoder_DecompVersusPVRLib) # Copy the .pvr files that we will use for testing... SET(TEST_IMAGES diff --git a/PVRTCEncoder/test/ImageTest.cpp b/PVRTCEncoder/test/ImageTest.cpp index ead8ba4..0022418 100644 --- a/PVRTCEncoder/test/ImageTest.cpp +++ b/PVRTCEncoder/test/ImageTest.cpp @@ -51,78 +51,14 @@ */ #include "gtest/gtest.h" -#include "Image.h" +#include "PVRTCImage.h" #include "Pixel.h" #include "TestUtils.h" #include -TEST(Image, NonSpecificConstructor) { - PVRTCC::Pixel p; - - PVRTCC::Image img (4, 4); - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - EXPECT_TRUE(img(i, j) == p); - } - } -} - -TEST(Image, SpecificConstructor) { - PVRTCC::Pixel pxs[16]; - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - pxs[j*4 + i].R() = i; - pxs[j*4 + i].G() = j; - } - } - - PVRTCC::Image img(4, 4, pxs); - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - EXPECT_TRUE(img(i, j) == pxs[j*4 + i]); - } - } -} - -TEST(Image, CopyConstructor) { - PVRTCC::Pixel pxs[16]; - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - pxs[j*4 + i].R() = i; - pxs[j*4 + i].G() = j; - } - } - - PVRTCC::Image img(4, 4, pxs); - PVRTCC::Image img2(img); - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - EXPECT_TRUE(img2(i, j) == pxs[j*4 + i]); - } - } -} - -TEST(Image, AssignmentOperator) { - PVRTCC::Pixel pxs[16]; - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - pxs[j*4 + i].R() = i; - pxs[j*4 + i].G() = j; - } - } - - PVRTCC::Image img(4, 4, pxs); - PVRTCC::Image img2 = img; - for(uint32 i = 0; i < 4; i++) { - for(uint32 j = 0; j < 4; j++) { - EXPECT_TRUE(img2(i, j) == pxs[j*4 + i]); - } - } -} - TEST(Image, BilinearUpscale) { - PVRTCC::Pixel pxs[16]; + FasTC::Pixel pxs[16]; for(uint32 i = 0; i < 4; i++) { for(uint32 j = 0; j < 4; j++) { pxs[j*4 + i].R() = i*2; @@ -152,7 +88,6 @@ TEST(Image, BilinearUpscale) { } } - TEST(Image, BilinearUpscaleMaintainsPixels) { srand(0xabd1ca7e); @@ -160,7 +95,7 @@ TEST(Image, BilinearUpscaleMaintainsPixels) { const uint32 w = 4; const uint32 h = 4; - PVRTCC::Pixel pxs[16]; + FasTC::Pixel pxs[16]; for(uint32 i = 0; i < w; i++) { for(uint32 j = 0; j < h; j++) { pxs[j*w + i].R() = rand() % 256; @@ -177,7 +112,7 @@ TEST(Image, BilinearUpscaleMaintainsPixels) { for(uint32 i = 2; i < img.GetWidth(); i+=4) { for(uint32 j = 2; j < img.GetHeight(); j+=4) { - PVRTCC::Pixel p = img(i, j); + FasTC::Pixel p = img(i, j); uint32 idx = ((j - 2) / 4) * w + ((i-2)/4); EXPECT_EQ(PixelPrinter(p.Pack()), PixelPrinter(pxs[idx].Pack())); } @@ -190,7 +125,7 @@ TEST(Image, NonuniformBilinearUpscale) { const uint32 kWidth = 4; const uint32 kHeight = 8; - PVRTCC::Pixel pxs[kWidth * kHeight]; + FasTC::Pixel pxs[kWidth * kHeight]; for(uint32 i = 0; i < kWidth; i++) { for(uint32 j = 0; j < kHeight; j++) { pxs[j*kWidth + i].R() = i*4; @@ -198,7 +133,7 @@ TEST(Image, NonuniformBilinearUpscale) { } } - PVRTCC::Image img(kHeight, kWidth, pxs); + PVRTCC::Image img(kWidth, kHeight, pxs); img.BilinearUpscale(2, 1, PVRTCC::eWrapMode_Clamp); EXPECT_EQ(img.GetWidth(), static_cast(kWidth << 2)); EXPECT_EQ(img.GetHeight(), static_cast(kHeight << 1)); @@ -223,7 +158,7 @@ TEST(Image, NonuniformBilinearUpscale) { } TEST(Image, BilinearUpscaleWrapped) { - PVRTCC::Pixel pxs[16]; + FasTC::Pixel pxs[16]; // Make sure that our bit depth is less than full... for(uint32 i = 0; i < 16; i++) { @@ -245,7 +180,7 @@ TEST(Image, BilinearUpscaleWrapped) { for(uint32 i = 0; i < img.GetWidth(); i++) { for(uint32 j = 0; j < img.GetHeight(); j++) { - const PVRTCC::Pixel &p = img(i, j); + const FasTC::Pixel &p = img(i, j); // First make sure that the bit depth didn't change uint8 depth[4]; @@ -284,9 +219,9 @@ TEST(Image, ContentAwareDownscale) { for(uint32 j = 0; j < img.GetHeight(); j++) { for(uint32 i = 0; i < img.GetWidth(); i++) { if(j < 4) { - img(i, j) = PVRTCC::Pixel( 0xFF000000 ); + img(i, j) = FasTC::Pixel( 0xFF000000 ); } else { - img(i, j) = PVRTCC::Pixel( 0xFF0000FF ); + img(i, j) = FasTC::Pixel( 0xFF0000FF ); } } } From 473a1c1869961e976034334c654839a6f129be21 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 15:06:20 -0400 Subject: [PATCH 04/13] Move the operators out of the class definition so that we can derive from Vectors. --- Base/include/VectorBase.h | 167 +++++++++++++++++++------------------- 1 file changed, 84 insertions(+), 83 deletions(-) diff --git a/Base/include/VectorBase.h b/Base/include/VectorBase.h index a7d892f..f27664f 100644 --- a/Base/include/VectorBase.h +++ b/Base/include/VectorBase.h @@ -51,6 +51,8 @@ namespace FasTC { } } + static const int Size = N; + // Accessors T &operator()(int idx) { return vec[idx]; } T &operator[](int idx) { return vec[idx]; } @@ -71,89 +73,6 @@ namespace FasTC { return VectorBase<_T, N>(vec); } - // Operators - template - VectorBase operator+(const VectorBase<_T, N> &v) const { - VectorBase a; - for(int i = 0; i < N; i++) - a.vec[i] = v(i) + vec[i]; - return a; - } - - template - VectorBase &operator+=(const VectorBase<_T, N> &v) const { - for(int i = 0; i < N; i++) - vec[i] += v(i); - return *this; - } - - template - VectorBase operator-(const VectorBase<_T, N> &v) const { - VectorBase a; - for(int i = 0; i < N; i++) - a(i) = vec[i] - v[i]; - return a; - } - - template - VectorBase &operator-=(const VectorBase<_T, N> &v) const { - for(int i = 0; i < N; i++) { - vec[i] -= v[i]; - } - return *this; - } - - template - VectorBase &operator=(const VectorBase<_T, N> &v) { - for(int i = 0; i < N; i++) - vec[i] = v[i]; - return *this; - } - - template - VectorBase operator*(const _T s) const { - VectorBase a; - for(int i = 0; i < N; i++) - a[i] = vec[i] * s; - return a; - } - - template - friend VectorBase operator*(const _T s, const VectorBase &v) { - VectorBase a; - for(int i = 0; i < N; i++) - a[i] = v[i] * s; - return a; - } - - template - VectorBase operator/(const _T s) const { - VectorBase a; - for(int i = 0; i < N; i++) - a[i] = vec[i] / s; - return a; - } - - template - friend VectorBase operator/(const _T s, const VectorBase &v) { - VectorBase a; - for(int i = 0; i < N; i++) - a[i] = v[i] / s; - return a; - } - - template - void operator*=(const _T s) { - for(int i = 0; i < N; i++) - vec[i] *= s; - } - - template - void operator/=(const _T s) { - for(int i = 0; i < N; i++) - vec[i] /= s; - } - // Vector operations template T Dot(const VectorBase<_T, N> &v) const { @@ -166,6 +85,88 @@ namespace FasTC { T LengthSq() const { return this->Dot(*this); } T Length() const { return sqrt(LengthSq()); } }; + + // Operators + template + static inline VectorTypeOne operator+(const VectorTypeOne &v1, + const VectorTypeTwo &v2) { + VectorTypeOne a; + for(int i = 0; i < VectorTypeOne::Size; i++) + a(i) = v1(i) + v2(i); + return a; + } + + template + static inline VectorTypeOne &operator+=(VectorTypeOne &v1, + const VectorTypeTwo &v2) { + for(int i = 0; i < VectorTypeOne::Size; i++) + v1(i) += v2(i); + return v1; + } + + template + static inline VectorTypeOne operator-(const VectorTypeOne &v1, + const VectorTypeTwo &v2) { + VectorTypeOne a; + for(int i = 0; i < VectorTypeOne::Size; i++) + a(i) = v1(i) - v2(i); + return a; + } + + template + static inline VectorTypeOne &operator-=(VectorTypeOne &v1, + const VectorTypeTwo &v2) { + for(int i = 0; i < VectorTypeOne::Size; i++) { + v1(i) -= v2(i); + } + return v1; + } + + template + static inline VectorType operator*(const VectorType &v, const ScalarType &s) { + VectorType a; + for(int i = 0; i < VectorType::Size; i++) + a(i) = v(i) * s; + return a; + } + + template + static inline VectorType operator*(const ScalarType &s, const VectorType &v) { + VectorType a; + for(int i = 0; i < VectorType::Size; i++) + a(i) = v(i) * s; + return a; + } + + template + static inline VectorType operator/(const VectorType &v, const ScalarType &s) { + VectorType a; + for(int i = 0; i < VectorType::Size; i++) + a(i) = v(i) / s; + return a; + } + + template + static inline operator/(const ScalarType &s, const VectorType &v) { + VectorType a; + for(int i = 0; i < VectorType::Size; i++) + a(i) = v(i) / s; + return a; + } + + template + static inline VectorType &operator*=(VectorType &v, const ScalarType &s) { + for(int i = 0; i < VectorType::Size; i++) + v(i) *= s; + return v; + } + + template + static inline VectorType &operator/=(VectorType &v, const ScalarType &s) { + for(int i = 0; i < VectorType::Size; i++) + v(i) /= s; + return v; + } }; #endif // BASE_INCLUDE_VECTORBASE_H_ From 85c3f9fc90b2a115dc6910583b15ac179e11d700 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 15:07:11 -0400 Subject: [PATCH 05/13] Pixels are actually 4vecs of ints --- Base/include/Pixel.h | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Base/include/Pixel.h b/Base/include/Pixel.h index 4fa9312..a2cb53c 100644 --- a/Base/include/Pixel.h +++ b/Base/include/Pixel.h @@ -58,17 +58,18 @@ namespace FasTC { -class Pixel : public Vector4 { +class Pixel { private: + Vector4 m_Vec; uint8 m_BitDepth[4]; public: - Pixel() : Vector4(0, 0, 0, 0) { + Pixel() : m_Vec(0, 0, 0, 0) { for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; } - explicit Pixel(uint32 rgba) : Vector4() { + explicit Pixel(uint32 rgba) { for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; Unpack(rgba); @@ -76,7 +77,7 @@ class Pixel : public Vector4 { Pixel(const uint8 *bits, const uint8 channelDepth[4] = static_cast(0), - uint8 bitOffset = 0) : Vector4() { + uint8 bitOffset = 0) { FromBits(bits, channelDepth, bitOffset); } @@ -106,16 +107,16 @@ class Pixel : public Vector4 { // above for how we do this. static uint8 ChangeBitDepth(uint8 val, uint8 oldDepth, uint8 newDepth); - const uint8 &A() const { return X(); } - uint8 &A() { return X(); } - const uint8 &R() const { return Y(); } - uint8 &R() { return Y(); } - const uint8 &G() const { return Z(); } - uint8 &G() { return Z(); } - const uint8 &B() const { return W(); } - uint8 &B() { return W(); } - const uint8 &Component(uint32 idx) const { return vec[idx]; } - uint8 &Component(uint32 idx) { return vec[idx]; } + const uint8 &A() const { return m_Vec.X(); } + uint8 &A() { return m_Vec.X(); } + const uint8 &R() const { return m_Vec.Y(); } + uint8 &R() { return m_Vec.Y(); } + const uint8 &G() const { return m_Vec.Z(); } + uint8 &G() { return m_Vec.Z(); } + const uint8 &B() const { return m_Vec.W(); } + uint8 &B() { return m_Vec.W(); } + const uint8 &Component(uint32 idx) const { return m_Vec[idx]; } + uint8 &Component(uint32 idx) { return m_Vec[idx]; } void GetBitDepth(uint8 (&outDepth)[4]) const { for(int i = 0; i < 4; i++) { From 2159a6688a5b56f425d9894c66c8b4013da9bc00 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 15:07:43 -0400 Subject: [PATCH 06/13] Add colors. --- Base/CMakeLists.txt | 2 + Base/include/Color.h | 100 +++++++++++++++++++++++++++++++++++++++ Base/src/Color.cpp | 87 ++++++++++++++++++++++++++++++++++ Base/test/CMakeLists.txt | 2 +- Base/test/TestColor.cpp | 98 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 Base/include/Color.h create mode 100644 Base/src/Color.cpp create mode 100644 Base/test/TestColor.cpp diff --git a/Base/CMakeLists.txt b/Base/CMakeLists.txt index 0d43519..61b331e 100644 --- a/Base/CMakeLists.txt +++ b/Base/CMakeLists.txt @@ -53,11 +53,13 @@ SET( SOURCES "src/Image.cpp" "src/CompressionJob.cpp" "src/Pixel.cpp" + "src/Color.cpp" ) SET( HEADERS "include/TexCompTypes.h" "include/Image.h" + "include/Color.h" "include/CompressionJob.h" "include/Pixel.h" "include/VectorBase.h" diff --git a/Base/include/Color.h b/Base/include/Color.h new file mode 100644 index 0000000..d7dd778 --- /dev/null +++ b/Base/include/Color.h @@ -0,0 +1,100 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#ifndef BASE_INCLUDE_COLOR_H_ +#define BASE_INCLUDE_COLOR_H_ + +#include "TexCompTypes.h" +#include "Vector4.h" + +namespace FasTC { + +class Color : public Vec4f { + public: + Color(float r, float g, float b, float a) : Vec4f(a, r, g, b) { } + Color() : Vec4f(0, 0, 0, 0) { } + + // Let's allow us to use the operators... + template + Color &operator=(const Vector4 &other) { + Vec4f::operator=(other); + return *this; + } + + template + Color(const Vector4 &other) : Vec4f(other) { } + + const float &A() const { return vec[0]; } + float &A() { return vec[0]; } + const float &R() const { return vec[1]; } + float &R() { return vec[1]; } + const float &G() const { return vec[2]; } + float &G() { return vec[2]; } + const float &B() const { return vec[3]; } + float &B() { return vec[3]; } + const float &Component(uint32 idx) const { return vec[idx]; } + float &Component(uint32 idx) { return vec[idx]; } + + // Take all of the components, transform them to their 8-bit variants, + // and then pack each channel into an R8G8B8A8 32-bit integer. We assume + // that the architecture is little-endian, so the alpha channel will end + // up in the most-significant byte. + uint32 Pack() const; + void Unpack(uint32 rgba); + + // Tests for equality by comparing the values and the bit depths. + bool operator==(const Color &) const; +}; + +} // namespace FasTC + +#endif // BASE_INCLUDE_COLOR_H_ diff --git a/Base/src/Color.cpp b/Base/src/Color.cpp new file mode 100644 index 0000000..386b33a --- /dev/null +++ b/Base/src/Color.cpp @@ -0,0 +1,87 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#include "Color.h" + +namespace FasTC { + + uint32 Color::Pack() const { + uint32 result = 0; + result = static_cast((A() + 0.5f) * 255.0f); + result <<= 8; + result = static_cast((B() + 0.5f) * 255.0f); + result <<= 8; + result = static_cast((G() + 0.5f) * 255.0f); + result <<= 8; + result = static_cast((R() + 0.5f) * 255.0f); + return result; + } + + void Color::Unpack(uint32 rgba) { + R() = static_cast(rgba & 0xFF) / 255.0f; + G() = static_cast((rgba >> 8) & 0xFF) / 255.0f; + B() = static_cast((rgba >> 16) & 0xFF) / 255.0f; + A() = static_cast((rgba >> 24) & 0xFF) / 255.0f; + } + + // Tests for equality by comparing the values and the bit depths. + bool Color::operator==(const Color &other) const { + static const float kEpsilon = 0.001; + for(uint32 c = 0; c < 4; c++) { + if(fabs(Component(c) - other.Component(c)) > kEpsilon) { + return false; + } + } + + return true; + } +} // namespace FasTC diff --git a/Base/test/CMakeLists.txt b/Base/test/CMakeLists.txt index 84518f7..42caebd 100644 --- a/Base/test/CMakeLists.txt +++ b/Base/test/CMakeLists.txt @@ -53,7 +53,7 @@ INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/Base/include) INCLUDE_DIRECTORIES(${FasTC_SOURCE_DIR}/GTest/include) SET(TESTS - Pixel Image + Pixel Image Color ) FOREACH(TEST ${TESTS}) diff --git a/Base/test/TestColor.cpp b/Base/test/TestColor.cpp new file mode 100644 index 0000000..9ea7d11 --- /dev/null +++ b/Base/test/TestColor.cpp @@ -0,0 +1,98 @@ +/* FasTC + * Copyright (c) 2013 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#include "gtest/gtest.h" +#include "Color.h" + +static const float kEpsilon = 1e-6; + +TEST(Color, DefaultConstructor) { + FasTC::Color c; + EXPECT_EQ(c.R(), 0.0f); + EXPECT_EQ(c.G(), 0.0f); + EXPECT_EQ(c.B(), 0.0f); + EXPECT_EQ(c.A(), 0.0f); +} + +TEST(Color, AssignmentConstructor) { + FasTC::Color c(1.0f, 0.0f, 3.0f, -1.0f); + EXPECT_EQ(c.R(), 1.0f); + EXPECT_EQ(c.G(), 0.0f); + EXPECT_EQ(c.B(), 3.0f); + EXPECT_EQ(c.A(), -1.0f); +} + +TEST(Color, VectorOperators) { + FasTC::Color a(0.1, 0.2, 0.3, 0.4); + FasTC::Color b(0.2, 0.3, 0.4, 0.5); + FasTC::Color c = a + b; + + EXPECT_NEAR(c.R(), 0.3, kEpsilon); + EXPECT_NEAR(c.G(), 0.5, kEpsilon); + EXPECT_NEAR(c.B(), 0.7, kEpsilon); + EXPECT_NEAR(c.A(), 0.9, kEpsilon); + + FasTC::Color d = a - b; + + EXPECT_NEAR(d.R(), -0.1, kEpsilon); + EXPECT_NEAR(d.G(), -0.1, kEpsilon); + EXPECT_NEAR(d.B(), -0.1, kEpsilon); + EXPECT_NEAR(d.A(), -0.1, kEpsilon); +} + +TEST(Color, EqualityComparison) { + FasTC::Color a(0.1, 0.2, 0.3, 0.4); + FasTC::Color b(0.2, 0.3, 0.4, 0.5); + + EXPECT_TRUE(a == a && b == b); + EXPECT_FALSE(a == b && b == a); +} From dd12cc92cdf8e1f7125efb2ece2c87b9e9ec3b71 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 17:32:40 -0400 Subject: [PATCH 07/13] Revert "Pixels are actually 4vecs of ints" This reverts commit 85c3f9fc90b2a115dc6910583b15ac179e11d700. --- Base/include/Pixel.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Base/include/Pixel.h b/Base/include/Pixel.h index a2cb53c..4fa9312 100644 --- a/Base/include/Pixel.h +++ b/Base/include/Pixel.h @@ -58,18 +58,17 @@ namespace FasTC { -class Pixel { +class Pixel : public Vector4 { private: - Vector4 m_Vec; uint8 m_BitDepth[4]; public: - Pixel() : m_Vec(0, 0, 0, 0) { + Pixel() : Vector4(0, 0, 0, 0) { for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; } - explicit Pixel(uint32 rgba) { + explicit Pixel(uint32 rgba) : Vector4() { for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; Unpack(rgba); @@ -77,7 +76,7 @@ class Pixel { Pixel(const uint8 *bits, const uint8 channelDepth[4] = static_cast(0), - uint8 bitOffset = 0) { + uint8 bitOffset = 0) : Vector4() { FromBits(bits, channelDepth, bitOffset); } @@ -107,16 +106,16 @@ class Pixel { // above for how we do this. static uint8 ChangeBitDepth(uint8 val, uint8 oldDepth, uint8 newDepth); - const uint8 &A() const { return m_Vec.X(); } - uint8 &A() { return m_Vec.X(); } - const uint8 &R() const { return m_Vec.Y(); } - uint8 &R() { return m_Vec.Y(); } - const uint8 &G() const { return m_Vec.Z(); } - uint8 &G() { return m_Vec.Z(); } - const uint8 &B() const { return m_Vec.W(); } - uint8 &B() { return m_Vec.W(); } - const uint8 &Component(uint32 idx) const { return m_Vec[idx]; } - uint8 &Component(uint32 idx) { return m_Vec[idx]; } + const uint8 &A() const { return X(); } + uint8 &A() { return X(); } + const uint8 &R() const { return Y(); } + uint8 &R() { return Y(); } + const uint8 &G() const { return Z(); } + uint8 &G() { return Z(); } + const uint8 &B() const { return W(); } + uint8 &B() { return W(); } + const uint8 &Component(uint32 idx) const { return vec[idx]; } + uint8 &Component(uint32 idx) { return vec[idx]; } void GetBitDepth(uint8 (&outDepth)[4]) const { for(int i = 0; i < 4; i++) { From a4a289c17761a057673d601363439da023a41a57 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 18:37:38 -0400 Subject: [PATCH 08/13] Change the pixel channel size to 16 bits so that our arithmetic operations don't overflow. --- Base/include/Pixel.h | 32 +++++++++++++++++--------------- Base/src/Pixel.cpp | 8 ++++---- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Base/include/Pixel.h b/Base/include/Pixel.h index 4fa9312..bee3134 100644 --- a/Base/include/Pixel.h +++ b/Base/include/Pixel.h @@ -58,17 +58,19 @@ namespace FasTC { -class Pixel : public Vector4 { +class Pixel : public Vector4 { private: + typedef uint16 ChannelType; + typedef Vector4 VectorType; uint8 m_BitDepth[4]; public: - Pixel() : Vector4(0, 0, 0, 0) { + Pixel() : VectorType(0, 0, 0, 0) { for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; } - explicit Pixel(uint32 rgba) : Vector4() { + explicit Pixel(uint32 rgba) : VectorType() { for(int i = 0; i < 4; i++) m_BitDepth[i] = 8; Unpack(rgba); @@ -76,7 +78,7 @@ class Pixel : public Vector4 { Pixel(const uint8 *bits, const uint8 channelDepth[4] = static_cast(0), - uint8 bitOffset = 0) : Vector4() { + uint8 bitOffset = 0) : VectorType() { FromBits(bits, channelDepth, bitOffset); } @@ -104,18 +106,18 @@ class Pixel : public Vector4 { // Changes the bit depth of a single component. See the comment // above for how we do this. - static uint8 ChangeBitDepth(uint8 val, uint8 oldDepth, uint8 newDepth); + static ChannelType ChangeBitDepth(ChannelType val, uint8 oldDepth, uint8 newDepth); - const uint8 &A() const { return X(); } - uint8 &A() { return X(); } - const uint8 &R() const { return Y(); } - uint8 &R() { return Y(); } - const uint8 &G() const { return Z(); } - uint8 &G() { return Z(); } - const uint8 &B() const { return W(); } - uint8 &B() { return W(); } - const uint8 &Component(uint32 idx) const { return vec[idx]; } - uint8 &Component(uint32 idx) { return vec[idx]; } + const ChannelType &A() const { return X(); } + ChannelType &A() { return X(); } + const ChannelType &R() const { return Y(); } + ChannelType &R() { return Y(); } + const ChannelType &G() const { return Z(); } + ChannelType &G() { return Z(); } + const ChannelType &B() const { return W(); } + ChannelType &B() { return W(); } + const ChannelType &Component(uint32 idx) const { return vec[idx]; } + ChannelType &Component(uint32 idx) { return vec[idx]; } void GetBitDepth(uint8 (&outDepth)[4]) const { for(int i = 0; i < 4; i++) { diff --git a/Base/src/Pixel.cpp b/Base/src/Pixel.cpp index 2b047bd..08a5bc4 100644 --- a/Base/src/Pixel.cpp +++ b/Base/src/Pixel.cpp @@ -82,7 +82,7 @@ namespace FasTC { } for(int32 i = 0; i < 4; i++) { - uint8 &channel = Component(i); + ChannelType &channel = Component(i); uint32 depth = m_BitDepth[i]; assert(depth <= 8); @@ -125,7 +125,7 @@ namespace FasTC { uint8 bitIdx = bitOffset; for(int i = 3; i >= 0; i--) { - uint8 val = Component(i); + ChannelType val = Component(i); uint8 depth = m_BitDepth[i]; if(depth + bitIdx > 8) { @@ -146,7 +146,7 @@ namespace FasTC { } } - uint8 Pixel::ChangeBitDepth(uint8 val, uint8 oldDepth, uint8 newDepth) { + Pixel::ChannelType Pixel::ChangeBitDepth(Pixel::ChannelType val, uint8 oldDepth, uint8 newDepth) { assert(newDepth <= 8); assert(oldDepth <= 8); @@ -222,7 +222,7 @@ namespace FasTC { ok = ok && m_BitDepth[i] == depths[i]; uint8 mask = (1 << depths[i]) - 1; - const uint8 c = other.Component(i) & mask; + const ChannelType c = other.Component(i) & mask; ok = ok && (c == (Component(i) & mask)); } return ok; From 0add6a5ee99eb0499d7be47a97cf84a79722c101 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 18:38:11 -0400 Subject: [PATCH 09/13] Allow FasTC::Image --- Base/src/Image.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Base/src/Image.cpp b/Base/src/Image.cpp index 557af1a..c78d2f8 100644 --- a/Base/src/Image.cpp +++ b/Base/src/Image.cpp @@ -49,6 +49,7 @@ #include #include +#include "Color.h" #include "Pixel.h" template @@ -288,5 +289,6 @@ void Image::SetImageData(uint32 width, uint32 height, PixelType *data } template class Image; +template class Image; } // namespace FasTC From 01a38dc76ba817d29936108be447b94e710e0512 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 18:39:32 -0400 Subject: [PATCH 10/13] Add more generic structures for performing scalar multiplication with vectors (i.e. ones that actually compile) --- Base/include/Color.h | 1 + Base/include/Pixel.h | 1 + Base/include/Vector2.h | 1 + Base/include/Vector3.h | 1 + Base/include/Vector4.h | 1 + Base/include/VectorBase.h | 95 ++++++++++++++++++++++++++++++++------- 6 files changed, 84 insertions(+), 16 deletions(-) diff --git a/Base/include/Color.h b/Base/include/Color.h index d7dd778..0ca5846 100644 --- a/Base/include/Color.h +++ b/Base/include/Color.h @@ -94,6 +94,7 @@ class Color : public Vec4f { // Tests for equality by comparing the values and the bit depths. bool operator==(const Color &) const; }; +REGISTER_VECTOR_TYPE(Color); } // namespace FasTC diff --git a/Base/include/Pixel.h b/Base/include/Pixel.h index bee3134..1d2e6fe 100644 --- a/Base/include/Pixel.h +++ b/Base/include/Pixel.h @@ -135,6 +135,7 @@ class Pixel : public Vector4 { // Tests for equality by comparing the values and the bit depths. bool operator==(const Pixel &) const; }; +REGISTER_VECTOR_TYPE(Pixel); } // namespace FasTC diff --git a/Base/include/Vector2.h b/Base/include/Vector2.h index 2c0edcd..52bce4b 100644 --- a/Base/include/Vector2.h +++ b/Base/include/Vector2.h @@ -71,6 +71,7 @@ namespace FasTC { _VEX_VEC2_SWIZZLE_DEF(Y, Y) #endif //_VEX_ENABLE_SWIZZLE_ }; + REGISTER_ONE_TEMPLATE_VECTOR_TYPE(Vector2); typedef Vector2 Vec2f; typedef Vector2 Vec2d; diff --git a/Base/include/Vector3.h b/Base/include/Vector3.h index 3c32b46..02de606 100644 --- a/Base/include/Vector3.h +++ b/Base/include/Vector3.h @@ -115,6 +115,7 @@ namespace FasTC { _VEX_VEC3_SWIZZLE_DEF(Z, Z, Z) #endif // _VEX_ENABLE_SWIZZLE_ }; + REGISTER_ONE_TEMPLATE_VECTOR_TYPE(Vector3); typedef Vector3 Vec3f; typedef Vector3 Vec3d; diff --git a/Base/include/Vector4.h b/Base/include/Vector4.h index 55f06ae..bf5311d 100644 --- a/Base/include/Vector4.h +++ b/Base/include/Vector4.h @@ -411,6 +411,7 @@ namespace FasTC { _VEX_VEC4_SWIZZLE_DEF(W, W, W, W) #endif // _VEX_ENABLE_SWIZZLE_ }; + REGISTER_ONE_TEMPLATE_VECTOR_TYPE(Vector4); typedef Vector4 Vec4f; typedef Vector4 Vec4d; diff --git a/Base/include/VectorBase.h b/Base/include/VectorBase.h index f27664f..e7962bb 100644 --- a/Base/include/VectorBase.h +++ b/Base/include/VectorBase.h @@ -122,49 +122,112 @@ namespace FasTC { return v1; } + template + class VectorTraits { + public: + static const bool IsVector = false; + }; + + template + class VectorTraits > { + public: + static const bool IsVector = true; + }; + + #define REGISTER_VECTOR_TYPE(TYPE) \ + template<> \ + class VectorTraits< TYPE > { \ + public: \ + static const bool IsVector = true; \ + } + + #define REGISTER_ONE_TEMPLATE_VECTOR_TYPE(TYPE) \ + template \ + class VectorTraits< TYPE > { \ + public: \ + static const bool IsVector = true; \ + } + + template + class VectorSwitch { + private: + const TypeOne &m_A; + const TypeTwo &m_B; + public: + typedef TypeOne VectorType; + typedef TypeTwo ScalarType; + + VectorSwitch(const TypeOne &a, const TypeTwo &b) + : m_A(a), m_B(b) { } + + const TypeOne &GetVector() { return m_A; } + const TypeTwo &GetScalar() { return m_B; } + }; + + template + class VectorSwitch { + private: + const TypeOne &m_A; + const TypeTwo &m_B; + + public: + typedef TypeTwo VectorType; + typedef TypeOne ScalarType; + + VectorSwitch(const TypeOne &a, const TypeTwo &b) + : m_A(a), m_B(b) { } + + const TypeOne &GetVector() { return m_B; } + const TypeTwo &GetScalar() { return m_A; } + }; + template - static inline VectorType operator*(const VectorType &v, const ScalarType &s) { + static inline VectorType ScalarMultiply(const VectorType &v, const ScalarType &s) { VectorType a; for(int i = 0; i < VectorType::Size; i++) a(i) = v(i) * s; return a; } - template - static inline VectorType operator*(const ScalarType &s, const VectorType &v) { - VectorType a; - for(int i = 0; i < VectorType::Size; i++) - a(i) = v(i) * s; - return a; + template + static inline + typename VectorSwitch< VectorTraits::IsVector, TypeOne, TypeTwo >::VectorType + operator*(const TypeOne &v1, const TypeTwo &v2) { + typedef VectorSwitch< VectorTraits::IsVector, TypeOne, TypeTwo > VSwitch; + VSwitch s(v1, v2); + return ScalarMultiply(s.GetVector(), s.GetScalar()); } template - static inline VectorType operator/(const VectorType &v, const ScalarType &s) { + static inline VectorType ScalarDivide(const VectorType &v, const ScalarType &s) { VectorType a; for(int i = 0; i < VectorType::Size; i++) a(i) = v(i) / s; return a; } - template - static inline operator/(const ScalarType &s, const VectorType &v) { - VectorType a; - for(int i = 0; i < VectorType::Size; i++) - a(i) = v(i) / s; - return a; + template + static inline + typename VectorSwitch< VectorTraits::IsVector, TypeOne, TypeTwo >::VectorType + operator/(const TypeOne &v1, const TypeTwo &v2) { + typedef VectorSwitch< VectorTraits::IsVector, TypeOne, TypeTwo > VSwitch; + VSwitch s(v1, v2); + return ScalarDivide(s.GetVector(), s.GetScalar()); } template static inline VectorType &operator*=(VectorType &v, const ScalarType &s) { - for(int i = 0; i < VectorType::Size; i++) + for(int i = 0; i < VectorType::Size; i++) { v(i) *= s; + } return v; } template static inline VectorType &operator/=(VectorType &v, const ScalarType &s) { - for(int i = 0; i < VectorType::Size; i++) + for(int i = 0; i < VectorType::Size; i++) { v(i) /= s; + } return v; } }; From 47074c1224e3b45e8661f1dd2ad147619017625b Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 20:29:56 -0400 Subject: [PATCH 11/13] Abstract away a bit more logic in order to allow us to easily override the core vector operations if need be. --- Base/include/Pixel.h | 35 ++++++++++++++++++++++++++++ Base/include/VectorBase.h | 49 +++++++++++++++++++++------------------ 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/Base/include/Pixel.h b/Base/include/Pixel.h index 1d2e6fe..3c1a189 100644 --- a/Base/include/Pixel.h +++ b/Base/include/Pixel.h @@ -137,6 +137,41 @@ class Pixel : public Vector4 { }; REGISTER_VECTOR_TYPE(Pixel); +// Overload operators so that we can preserve bit depths... +template +static inline Pixel ScalarMultiply(const Pixel &p, const ScalarType &s) { + Pixel a(p); + for(int i = 0; i < Pixel::Size; i++) + a(i) = p(i) * s; + return a; +} + +template +static inline Pixel ScalarDivide(const Pixel &p, const ScalarType &s) { + Pixel a(p); + for(int i = 0; i < Pixel::Size; i++) + a(i) = p(i) / s; + return a; +} + +template +static inline Pixel VectorAddition(const Pixel &p, const VectorType &v) { + Pixel a(p); + for(int i = 0; i < Pixel::Size; i++) { + a(i) += v(i); + } + return a; +} + +template +static inline Pixel VectorSubtraction(const Pixel &p, const VectorType &v) { + Pixel a(p); + for(int i = 0; i < Pixel::Size; i++) { + a(i) -= v(i); + } + return a; +} + } // namespace FasTC #endif // BASE_INCLUDE_PIXEL_H_ diff --git a/Base/include/VectorBase.h b/Base/include/VectorBase.h index e7962bb..f870799 100644 --- a/Base/include/VectorBase.h +++ b/Base/include/VectorBase.h @@ -87,39 +87,48 @@ namespace FasTC { }; // Operators + template + static inline VectorTypeOne VectorAddition(const VectorTypeOne &v1, + const VectorTypeTwo &v2) { + VectorTypeOne a; + for(int i = 0; i < VectorTypeOne::Size; i++) { + a(i) = v1(i) + v2(i); + } + return a; + } + template static inline VectorTypeOne operator+(const VectorTypeOne &v1, const VectorTypeTwo &v2) { - VectorTypeOne a; - for(int i = 0; i < VectorTypeOne::Size; i++) - a(i) = v1(i) + v2(i); - return a; + return VectorAddition(v1, v2); } template static inline VectorTypeOne &operator+=(VectorTypeOne &v1, const VectorTypeTwo &v2) { - for(int i = 0; i < VectorTypeOne::Size; i++) - v1(i) += v2(i); - return v1; + return v1 = VectorAddition(v1, v2); + } + + template + static inline VectorTypeOne VectorSubtraction(const VectorTypeOne &v1, + const VectorTypeTwo &v2) { + VectorTypeOne a; + for(int i = 0; i < VectorTypeOne::Size; i++) { + a(i) = v1(i) - v2(i); + } + return a; } template static inline VectorTypeOne operator-(const VectorTypeOne &v1, const VectorTypeTwo &v2) { - VectorTypeOne a; - for(int i = 0; i < VectorTypeOne::Size; i++) - a(i) = v1(i) - v2(i); - return a; + return VectorSubtraction(v1, v2); } template static inline VectorTypeOne &operator-=(VectorTypeOne &v1, const VectorTypeTwo &v2) { - for(int i = 0; i < VectorTypeOne::Size; i++) { - v1(i) -= v2(i); - } - return v1; + return v1 = VectorSubtraction(v1, v2); } template @@ -217,18 +226,12 @@ namespace FasTC { template static inline VectorType &operator*=(VectorType &v, const ScalarType &s) { - for(int i = 0; i < VectorType::Size; i++) { - v(i) *= s; - } - return v; + return v = ScalarMultiply(v, s); } template static inline VectorType &operator/=(VectorType &v, const ScalarType &s) { - for(int i = 0; i < VectorType::Size; i++) { - v(i) /= s; - } - return v; + return v = ScalarDivide(v, s); } }; From f502e2bd0e8886d2e43d27428de926c749218bb5 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 20:30:16 -0400 Subject: [PATCH 12/13] Change the order of directory traversal so that our tests work nicer --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63f5b30..32ab81a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,7 @@ SET(CMAKE_MODULE_PATH "${FasTC_SOURCE_DIR}/CMakeModules" ${CMAKE_MODULE_PATH}) FIND_PACKAGE(PVRTexLib) SET(FASTC_DIRECTORIES - BPTCEncoder PVRTCEncoder IO Core Base + Base Core IO BPTCEncoder PVRTCEncoder ) FOREACH(DIR ${FASTC_DIRECTORIES}) From 9911d5edc5e2225f66dc62953334026ed8471212 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Tue, 8 Oct 2013 20:30:31 -0400 Subject: [PATCH 13/13] Get rid of some redundant code =) --- PVRTCEncoder/src/Decompressor.cpp | 20 ++------------------ PVRTCEncoder/src/PVRTCImage.cpp | 16 +++++++++------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/PVRTCEncoder/src/Decompressor.cpp b/PVRTCEncoder/src/Decompressor.cpp index 7fb66fc..6495040 100644 --- a/PVRTCEncoder/src/Decompressor.cpp +++ b/PVRTCEncoder/src/Decompressor.cpp @@ -146,15 +146,7 @@ namespace PVRTCC { } } - Pixel result; - for(uint32 c = 0; c < 4; c++) { - uint16 va = static_cast(pa.Component(c)); - uint16 vb = static_cast(pb.Component(c)); - - uint16 res = (va * (8 - lerpVal) + vb * lerpVal) / 8; - result.Component(c) = static_cast(res); - } - + Pixel result = (pa * (8 - lerpVal) + pb * lerpVal) / 8; if(punchThrough) { result.A() = 0; } @@ -259,15 +251,7 @@ namespace PVRTCC { const Pixel &pa = imgA(i, j); const Pixel &pb = imgB(i, j); - Pixel result; - for(uint32 c = 0; c < 4; c++) { - uint16 va = static_cast(pa.Component(c)); - uint16 vb = static_cast(pb.Component(c)); - - uint16 res = (va * (8 - lerpVal) + vb * lerpVal) / 8; - result.Component(c) = static_cast(res); - } - + Pixel result = (pa * (8 - lerpVal) + pb * lerpVal) / 8; uint32 *outPixels = reinterpret_cast(outBuf); outPixels[(j * w) + i] = result.Pack(); } diff --git a/PVRTCEncoder/src/PVRTCImage.cpp b/PVRTCEncoder/src/PVRTCImage.cpp index d6beb2f..b182a67 100644 --- a/PVRTCEncoder/src/PVRTCImage.cpp +++ b/PVRTCEncoder/src/PVRTCImage.cpp @@ -196,15 +196,17 @@ void Image::BilinearUpscale(uint32 xtimes, uint32 ytimes, for(uint32 c = 0; c < 4; c++) fpDepths[c] = xtimes + ytimes; fp.ChangeBitDepth(fpDepths); + const FasTC::Pixel tl = topLeft * topLeftWeight; + const FasTC::Pixel tr = topRight * topRightWeight; + const FasTC::Pixel bl = bottomLeft * bottomLeftWeight; + const FasTC::Pixel br = bottomRight * bottomRightWeight; + const FasTC::Pixel sum = tl + tr + bl + br; + for(uint32 c = 0; c < 4; c++) { - const uint32 tl = topLeft.Component(c) * topLeftWeight; - const uint32 tr = topRight.Component(c) * topRightWeight; - const uint32 bl = bottomLeft.Component(c) * bottomLeftWeight; - const uint32 br = bottomRight.Component(c) * bottomRightWeight; - const uint32 sum = tl + tr + bl + br; - fp.Component(c) = sum & scaleMask; - p.Component(c) = sum / (xscale * yscale); + fp.Component(c) = sum.Component(c) & scaleMask; } + + p = sum / (xscale * yscale); } }