diff --git a/CMakeLists.txt b/CMakeLists.txt index 91d3204..65b8346 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ set(PUBLIC_HEADERS include/hitinfo.h include/kraken-math.h include/matrix2.h + include/matrix2x3.h include/matrix4.h include/quaternion.h include/scalar.h @@ -25,6 +26,7 @@ set(SRCS src/hitinfo.cpp src/krhelpers.cpp src/matrix2.cpp + src/matrix2x3.cpp src/matrix4.cpp src/quaternion.cpp src/scalar.cpp diff --git a/include/kraken-math.h b/include/kraken-math.h index ea2384c..d3d93c5 100644 --- a/include/kraken-math.h +++ b/include/kraken-math.h @@ -37,6 +37,7 @@ #include "vector4.h" #include "vector2i.h" #include "matrix2.h" +#include "matrix2x3.h" #include "matrix4.h" #include "quaternion.h" #include "aabb.h" diff --git a/include/matrix2x3.h b/include/matrix2x3.h new file mode 100644 index 0000000..516c06e --- /dev/null +++ b/include/matrix2x3.h @@ -0,0 +1,109 @@ +// +// Matrix2x3.h +// Kraken +// +// Copyright 2018 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#include "vector2.h" +#include "vector3.h" + +#ifndef KRAKEN_MATRIX2X3_H +#define KRAKEN_MATRIX2X3_H + +namespace kraken { + +class Matrix2x3 { +public: + + union { + struct { + Vector2 axis_x, axis_y, transform; + }; + // Matrix components, in column-major order + float c[6]; + }; + + // Default initializer - Creates an identity matrix + void init(); + + void init(float *pMat); + + void init(const Vector2 &new_axis_x, const Vector2 &new_axis_y, const Vector2 &new_transform); + + void init(const Matrix2x3 &m); + + // Overload comparison operator + bool operator==(const Matrix2x3 &m) const; + + // Overload compound multiply operator + Matrix2x3& operator*=(const Matrix2x3 &m); + + float& operator[](unsigned i); + float operator[](unsigned i) const; + + // Overload multiply operator + Matrix2x3 operator*(const Matrix2x3 &m) const; + + float *getPointer(); + + void translate(float x, float y); + void translate(const Vector2 &v); + void scale(float x, float y); + void scale(const Vector2 &v); + void scale(float s); + void rotate(float angle); + bool invert(); + + static Vector2 DotNoTranslate(const Matrix2x3 &m, const Vector2 &v); // Dot product without including translation; useful for transforming normals and tangents + static Matrix2x3 Invert(const Matrix2x3 &m); + static Vector2 Dot(const Matrix2x3 &m, const Vector2 &v); + + static Matrix2x3 Translation(const Vector2 &v); + static Matrix2x3 Rotation(float angle); + static Matrix2x3 Scaling(const Vector2 &v); + static Matrix2x3 Identity(); +}; +static_assert(std::is_pod::value, "kraken::Matrix2x3 must be a POD type."); + +} // namespace kraken + +namespace std { + template<> + struct hash { + public: + size_t operator()(const kraken::Matrix2x3 &s) const + { + size_t h1 = hash()(s.axis_x); + size_t h2 = hash()(s.axis_y); + size_t h3 = hash()(s.transform); + return h1 ^ (h2 << 1) ^ (h3 << 2); + } + }; +} // namespace std + +#endif // KRAKEN_MATRIX2X3_H diff --git a/include/vector2i.h b/include/vector2i.h index 4e9a3db..caaf00d 100644 --- a/include/vector2i.h +++ b/include/vector2i.h @@ -1,124 +1,124 @@ -// -// vector2i.h -// Kraken -// -// Copyright 2018 Kearwood Gilbert. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The views and conclusions contained in the software and documentation are those of the -// authors and should not be interpreted as representing official policies, either expressed -// or implied, of Kearwood Gilbert. -// - - -#ifndef KRAKEN_VECTOR2I_H -#define KRAKEN_VECTOR2I_H - -#include // for hash<> -#include // for std::numeric_limits<> -#include // for sqrtf - -namespace kraken { - -class Vector2i { - -public: - union { - struct { - int x, y; - }; - int c[2]; - }; - - void init(); - void init(int X, int Y); - void init(int v); - void init(int *v); - void init(const Vector2i &v); - static Vector2i Create(); - static Vector2i Create(int X, int Y); - static Vector2i Create(int v); - static Vector2i Create(int *v); - static Vector2i Create(const Vector2i &v); - - // Vector2 swizzle getters - Vector2i yx() const; - - // Vector2 swizzle setters - void yx(const Vector2i &v); - - Vector2i operator +(const Vector2i& b) const; - Vector2i operator -(const Vector2i& b) const; - Vector2i operator +() const; - Vector2i operator -() const; - Vector2i operator *(const int v) const; - Vector2i operator /(const int v) const; - - Vector2i& operator +=(const Vector2i& b); - Vector2i& operator -=(const Vector2i& b); - Vector2i& operator *=(const int v); - Vector2i& operator /=(const int v); - - // Comparison operators are implemented to allow insertion into sorted containers such as std::set - bool operator >(const Vector2i& b) const; - bool operator <(const Vector2i& b) const; - - bool operator ==(const Vector2i& b) const; - bool operator !=(const Vector2i& b) const; - - int& operator[](unsigned i); - int operator[](unsigned i) const; - - int sqrMagnitude() const; - int magnitude() const; - - void normalize(); - static Vector2i Normalize(const Vector2i &v); - - static int Cross(const Vector2i &v1, const Vector2i &v2); - static int Dot(const Vector2i &v1, const Vector2i &v2); +// +// vector2i.h +// Kraken +// +// Copyright 2018 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + + +#ifndef KRAKEN_VECTOR2I_H +#define KRAKEN_VECTOR2I_H + +#include // for hash<> +#include // for std::numeric_limits<> +#include // for sqrtf + +namespace kraken { + +class Vector2i { + +public: + union { + struct { + int x, y; + }; + int c[2]; + }; + + void init(); + void init(int X, int Y); + void init(int v); + void init(int *v); + void init(const Vector2i &v); + static Vector2i Create(); + static Vector2i Create(int X, int Y); + static Vector2i Create(int v); + static Vector2i Create(int *v); + static Vector2i Create(const Vector2i &v); + + // Vector2 swizzle getters + Vector2i yx() const; + + // Vector2 swizzle setters + void yx(const Vector2i &v); + + Vector2i operator +(const Vector2i& b) const; + Vector2i operator -(const Vector2i& b) const; + Vector2i operator +() const; + Vector2i operator -() const; + Vector2i operator *(const int v) const; + Vector2i operator /(const int v) const; + + Vector2i& operator +=(const Vector2i& b); + Vector2i& operator -=(const Vector2i& b); + Vector2i& operator *=(const int v); + Vector2i& operator /=(const int v); + + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + bool operator >(const Vector2i& b) const; + bool operator <(const Vector2i& b) const; + + bool operator ==(const Vector2i& b) const; + bool operator !=(const Vector2i& b) const; + + int& operator[](unsigned i); + int operator[](unsigned i) const; + + int sqrMagnitude() const; + int magnitude() const; + + void normalize(); + static Vector2i Normalize(const Vector2i &v); + + static int Cross(const Vector2i &v1, const Vector2i &v2); + static int Dot(const Vector2i &v1, const Vector2i &v2); static Vector2i Min(const Vector2i &v1, const Vector2i &v2); - static Vector2i Max(const Vector2i &v1, const Vector2i &v2); - - static Vector2i Min(); - static Vector2i Max(); - static Vector2i Zero(); - static Vector2i One(); -}; // class Vector2i -static_assert(std::is_pod::value, "kraken::Vector2i must be a POD type."); - -} // namespace kraken - -namespace std { - template<> - struct hash { - public: - size_t operator()(const kraken::Vector2i &s) const - { - size_t h1 = hash()(s.x); - size_t h2 = hash()(s.y); - return h1 ^ (h2 << 1); - } - }; -} // namespace std - -#endif // KRAKEN_VECTOR2I_H + static Vector2i Max(const Vector2i &v1, const Vector2i &v2); + + static Vector2i Min(); + static Vector2i Max(); + static Vector2i Zero(); + static Vector2i One(); +}; // class Vector2i +static_assert(std::is_pod::value, "kraken::Vector2i must be a POD type."); + +} // namespace kraken + +namespace std { + template<> + struct hash { + public: + size_t operator()(const kraken::Vector2i &s) const + { + size_t h1 = hash()(s.x); + size_t h2 = hash()(s.y); + return h1 ^ (h2 << 1); + } + }; +} // namespace std + +#endif // KRAKEN_VECTOR2I_H diff --git a/src/matrix2.cpp b/src/matrix2.cpp index 7eecf31..80b1e2b 100644 --- a/src/matrix2.cpp +++ b/src/matrix2.cpp @@ -137,15 +137,16 @@ void Matrix2::scale(float s) { /* Replace matrix with its inverse */ bool Matrix2::invert() { - float det = 1.0f / (c[0] * c[3] + c[1] * c[2]); + float det = c[0] * c[3] - c[1] * c[2]; if (det == 0) { return false; } float invdet = 1.0f / det; + float tmp = c[0]; c[0] = c[3] * invdet; c[1] = -c[1] * invdet; c[2] = -c[2] * invdet; - c[3] = c[0] * invdet; + c[3] = tmp * invdet; return true; } diff --git a/src/matrix2x3.cpp b/src/matrix2x3.cpp new file mode 100644 index 0000000..a89e728 --- /dev/null +++ b/src/matrix2x3.cpp @@ -0,0 +1,225 @@ +// +// matrix23.cpp +// Kraken +// +// Copyright 2018 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#include "../include/kraken-math.h" + +#include + +namespace kraken { + +void Matrix2x3::init() { + // Default constructor - Initialize with an identity matrix + static const float IDENTITY_MATRIX[] = { + 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 + }; + memcpy(c, IDENTITY_MATRIX, sizeof(float) * 6); + +} + +void Matrix2x3::init(float *pMat) { + memcpy(c, pMat, sizeof(float) * 6); +} + +void Matrix2x3::init(const Vector2 &new_axis_x, const Vector2 &new_axis_y, const Vector2 &new_transform) +{ + c[0] = new_axis_x.x; c[1] = new_axis_x.y; + c[2] = new_axis_y.x; c[3] = new_axis_y.y; + c[4] = new_transform.x; c[5] = new_transform.y; +} + +void Matrix2x3::init(const Matrix2x3 &m) { + memcpy(c, m.c, sizeof(float) * 6); +} + +float *Matrix2x3::getPointer() { + return c; +} + +float& Matrix2x3::operator[](unsigned i) { + return c[i]; +} + +float Matrix2x3::operator[](unsigned i) const { + return c[i]; +} + +// Overload comparison operator +bool Matrix2x3::operator==(const Matrix2x3 &m) const { + return memcmp(c, m.c, sizeof(float) * 6) == 0; +} + +// Overload compound multiply operator +Matrix2x3& Matrix2x3::operator*=(const Matrix2x3 &m) { + float temp[6]; + temp[0] = c[0] * m[0] + c[2] * m[1]; + temp[1] = c[1] * m[0] + c[3] * m[1]; + temp[2] = c[0] * m[2] + c[2] * m[3]; + temp[3] = c[1] * m[2] + c[3] * m[3]; + temp[4] = c[0] * m[4] + c[2] * m[5] + c[4]; + temp[5] = c[1] * m[4] + c[3] * m[5] + c[5]; + + memcpy(c, temp, sizeof(float) * 6); + return *this; +} + +// Overload multiply operator +Matrix2x3 Matrix2x3::operator*(const Matrix2x3 &m) const { + Matrix2x3 ret = *this; + ret *= m; + return ret; +} + +/* Perform translation operations on a matrix */ +void Matrix2x3::translate(float x, float y) { + Matrix2x3 newMatrix; // Create new identity matrix + newMatrix.init(); + + newMatrix.transform.x = x; + newMatrix.transform.y = y; + + *this *= newMatrix; +} + +void Matrix2x3::translate(const Vector2 &v) +{ + translate(v.x, v.y); +} + +/* Rotate a matrix by an angle on a X, Y, or Z axis */ +void Matrix2x3::rotate(float angle) { + Matrix2x3 newMatrix; + newMatrix.init(); + newMatrix.c[0] = cos(angle); + newMatrix.c[1] = -sin(angle); + newMatrix.c[2] = -newMatrix.c[1]; + newMatrix.c[3] = newMatrix.c[0]; + + *this *= newMatrix; +} + +/* Scale matrix by separate x, y, and z amounts */ +void Matrix2x3::scale(float x, float y) { + Matrix2x3 newMatrix; // Create new identity matrix + newMatrix.init(); + + newMatrix.c[0] = x; + newMatrix.c[2] = y; + + *this *= newMatrix; +} + +void Matrix2x3::scale(const Vector2 &v) { + scale(v.x, v.y); +} + +/* Scale all dimensions equally */ +void Matrix2x3::scale(float s) { + scale(s,s); +} +/* Replace matrix with its inverse */ +bool Matrix2x3::invert() { + float det = c[0] * c[3] - c[1] * c[2]; + if (det == 0) { + return false; + } + float invdet = 1.0f / det; + float tmp[6]; + tmp[0] = c[3] * invdet; + tmp[1] = -c[1] * invdet; + tmp[2] = -c[2] * invdet; + tmp[3] = c[0] * invdet; + tmp[4] = (c[2] * c[5] - c[3] * c[4]) * invdet; + tmp[5] = (c[1] * c[4] - c[0] * c[5]) * invdet; + memcpy(c, tmp, sizeof(float) * 6); + + return true; +} + +/* Dot Product, returning Vector2 */ +Vector2 Matrix2x3::Dot(const Matrix2x3 &m, const Vector2 &v) { + return Vector2::Create( + v.c[0] * m.c[0] + v.c[1] * m.c[2] + m.c[4], + v.c[0] * m.c[1] + v.c[1] * m.c[3] + m.c[5] + ); +} + +// Dot product without including translation; useful for transforming normals and tangents +Vector2 Matrix2x3::DotNoTranslate(const Matrix2x3 &m, const Vector2 &v) +{ + return Vector2::Create( + v.c[0] * m.c[0] + v.c[1] * m.c[2], + v.c[0] * m.c[1] + v.c[1] * m.c[3] + ); +} + +Matrix2x3 Matrix2x3::Invert(const Matrix2x3 &m) +{ + Matrix2x3 matInvert = m; + matInvert.invert(); + return matInvert; +} + +Matrix2x3 Matrix2x3::Translation(const Vector2 &v) +{ + Matrix2x3 m; + m.init(); + m.transform.x = v.x; + m.transform.y = v.y; + return m; +} + +Matrix2x3 Matrix2x3::Rotation(float angle) +{ + Matrix2x3 m; + m.init(); + m.rotate(angle); + return m; +} + +Matrix2x3 Matrix2x3::Scaling(const Vector2 &v) +{ + Matrix2x3 m; + m.init(); + m.scale(v); + return m; +} + +Matrix2x3 Matrix2x3::Identity() +{ + Matrix2x3 m; + m.init(); + return m; +} + +} // namespace kraken +