From 7fc321ebb85886fc2e278a6344ab50c29bc6ebaa Mon Sep 17 00:00:00 2001 From: "Kearwood \"Kip\" Gilbert" Date: Tue, 27 Mar 2018 16:48:24 -0700 Subject: [PATCH] Implemented kraken::Matrix2 --- CMakeLists.txt | 2 + include/kraken-math.h | 1 + include/matrix2.h | 106 ++++++++++++++++++++++ src/matrix2.cpp | 205 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 314 insertions(+) create mode 100644 include/matrix2.h create mode 100644 src/matrix2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 43fea47..91d3204 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set(PUBLIC_HEADERS include/aabb.h include/hitinfo.h include/kraken-math.h + include/matrix2.h include/matrix4.h include/quaternion.h include/scalar.h @@ -23,6 +24,7 @@ set(SRCS src/aabb.cpp src/hitinfo.cpp src/krhelpers.cpp + src/matrix2.cpp src/matrix4.cpp src/quaternion.cpp src/scalar.cpp diff --git a/include/kraken-math.h b/include/kraken-math.h index bb9cb78..ea2384c 100644 --- a/include/kraken-math.h +++ b/include/kraken-math.h @@ -36,6 +36,7 @@ #include "vector3.h" #include "vector4.h" #include "vector2i.h" +#include "matrix2.h" #include "matrix4.h" #include "quaternion.h" #include "aabb.h" diff --git a/include/matrix2.h b/include/matrix2.h new file mode 100644 index 0000000..07eecd5 --- /dev/null +++ b/include/matrix2.h @@ -0,0 +1,106 @@ +// +// Matrix2.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" + +#ifndef KRAKEN_MATRIX2_H +#define KRAKEN_MATRIX2_H + +namespace kraken { + +class Matrix2 { +public: + + union { + struct { + Vector2 axis_x, axis_y; + }; + // Matrix components, in column-major order + float c[4]; + }; + + // Default initializer - Creates an identity matrix + void init(); + + void init(float *pMat); + + void init(const Vector2 &new_axis_x, const Vector2 &new_axis_y); + + void init(const Matrix2 &m); + + // Overload comparison operator + bool operator==(const Matrix2 &m) const; + + // Overload compound multiply operator + Matrix2& operator*=(const Matrix2 &m); + + float& operator[](unsigned i); + float operator[](unsigned i) const; + + // Overload multiply operator + //Matrix4& operator*(const Matrix4 &m); + Matrix2 operator*(const Matrix2 &m) const; + + float *getPointer(); + + void scale(float x, float y); + void scale(const Vector2 &v); + void scale(float s); + void rotate(float angle); + bool invert(); + void transpose(); + + static Matrix2 Invert(const Matrix2 &m); + static Matrix2 Transpose(const Matrix2 &m); + static Vector2 Dot(const Matrix2 &m, const Vector2 &v); + + static Matrix2 Rotation(float); + static Matrix2 Scaling(const Vector2 &v); + static Matrix2 Identity(); +}; +static_assert(std::is_pod::value, "kraken::Matrix2 must be a POD type."); + +} // namespace kraken + +namespace std { + template<> + struct hash { + public: + size_t operator()(const kraken::Matrix2 &s) const + { + size_t h1 = hash()(s.axis_x); + size_t h2 = hash()(s.axis_y); + return h1 ^ (h2 << 1); + } + }; +} // namespace std + +#endif // KRAKEN_MATRIX2_H diff --git a/src/matrix2.cpp b/src/matrix2.cpp new file mode 100644 index 0000000..7eecf31 --- /dev/null +++ b/src/matrix2.cpp @@ -0,0 +1,205 @@ +// +// matrix2.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 Matrix2::init() { + // Default constructor - Initialize with an identity matrix + static const float IDENTITY_MATRIX[] = { + 1.0, 0.0, + 0.0, 1.0 + }; + memcpy(c, IDENTITY_MATRIX, sizeof(float) * 4); + +} + +void Matrix2::init(float *pMat) { + memcpy(c, pMat, sizeof(float) * 4); +} + +void Matrix2::init(const Vector2 &new_axis_x, const Vector2 &new_axis_y) +{ + c[0] = new_axis_x.x; c[1] = new_axis_x.y; + c[2] = new_axis_y.x; c[3] = new_axis_y.y; +} + +void Matrix2::init(const Matrix2 &m) { + memcpy(c, m.c, sizeof(float) * 4); +} + +float *Matrix2::getPointer() { + return c; +} + +float& Matrix2::operator[](unsigned i) { + return c[i]; +} + +float Matrix2::operator[](unsigned i) const { + return c[i]; +} + +// Overload comparison operator +bool Matrix2::operator==(const Matrix2 &m) const { + return memcmp(c, m.c, sizeof(float) * 4) == 0; +} + +// Overload compound multiply operator +Matrix2& Matrix2::operator*=(const Matrix2 &m) { + float temp[4]; + + int x,y; + + for (x=0; x < 2; x++) + { + for(y=0; y < 2; y++) + { + temp[y + (x*2)] = (c[x*2] * m.c[y]) + + (c[x*2+1] * m.c[y+2]); + } + } + + memcpy(c, temp, sizeof(float) * 4); + return *this; +} + +// Overload multiply operator +Matrix2 Matrix2::operator*(const Matrix2 &m) const { + Matrix2 ret = *this; + ret *= m; + return ret; +} + +/* Rotate a matrix by an angle on a X, Y, or Z axis */ +void Matrix2::rotate(float angle) { + + Matrix2 newMatrix; // Create new identity matrix + 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 Matrix2::scale(float x, float y) { + Matrix2 newMatrix; // Create new identity matrix + newMatrix.init(); + + newMatrix.c[0] = x; + newMatrix.c[3] = y; + + *this *= newMatrix; +} + +void Matrix2::scale(const Vector2 &v) { + scale(v.x, v.y); +} + +/* Scale all dimensions equally */ +void Matrix2::scale(float s) { + scale(s,s); +} + +/* Replace matrix with its inverse */ +bool Matrix2::invert() { + float det = 1.0f / (c[0] * c[3] + c[1] * c[2]); + if (det == 0) { + return false; + } + float invdet = 1.0f / det; + c[0] = c[3] * invdet; + c[1] = -c[1] * invdet; + c[2] = -c[2] * invdet; + c[3] = c[0] * invdet; + + return true; +} + +void Matrix2::transpose() { + float tmp = c[1]; + c[1] = c[2]; + c[2] = tmp; +} + +/* Dot Product, returning Vector2 */ +Vector2 Matrix2::Dot(const Matrix2 &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] + ); +} + +Matrix2 Matrix2::Invert(const Matrix2 &m) +{ + Matrix2 matInvert = m; + matInvert.invert(); + return matInvert; +} + +Matrix2 Matrix2::Transpose(const Matrix2 &m) +{ + Matrix2 matTranspose = m; + matTranspose.transpose(); + return matTranspose; +} + +Matrix2 Matrix2::Rotation(float angle) +{ + Matrix2 m; + m.init(); + m.rotate(angle); + return m; +} + +Matrix2 Matrix2::Scaling(const Vector2 &v) +{ + Matrix2 m; + m.init(); + m.scale(v); + return m; +} + +Matrix2 Matrix2::Identity() +{ + Matrix2 m; + m.init(); + return m; +} + +} // namespace kraken +