zeus/include/zeus/CTransform.hpp

233 lines
7.1 KiB
C++
Raw Permalink Normal View History

2018-10-06 20:39:40 -07:00
#pragma once
2015-04-19 13:39:16 -07:00
#include <cstdint>
#include <cstdio>
2016-03-04 15:03:26 -08:00
#include "zeus/CMatrix3f.hpp"
#include "zeus/CMatrix4f.hpp"
#include "zeus/CUnitVector.hpp"
#include "zeus/CVector3f.hpp"
#include "zeus/Global.hpp"
2015-04-19 13:39:16 -07:00
2018-12-07 17:16:50 -08:00
namespace zeus {
class CTransform {
2015-04-19 13:39:16 -07:00
public:
2019-02-23 23:15:32 -08:00
constexpr CTransform() : basis(false) {}
2018-12-07 17:16:50 -08:00
2019-02-23 23:15:32 -08:00
constexpr CTransform(const CMatrix3f& basis, const CVector3f& offset = {})
: basis(basis), origin(offset) {}
2015-07-29 14:59:03 -07:00
2018-12-07 17:16:50 -08:00
/* Column constructor */
2019-02-23 23:15:32 -08:00
constexpr CTransform(const CVector3f& c0, const CVector3f& c1, const CVector3f& c2, const CVector3f& c3)
2018-12-07 17:16:50 -08:00
: basis(c0, c1, c2), origin(c3) {}
[[nodiscard]] bool operator==(const CTransform& other) const {
return origin == other.origin && basis == other.basis;
}
[[nodiscard]] bool operator!=(const CTransform& other) const { return !operator==(other); }
2018-12-07 17:16:50 -08:00
[[nodiscard]] CTransform operator*(const CTransform& rhs) const {
2018-12-07 17:16:50 -08:00
return CTransform(basis * rhs.basis, origin + (basis * rhs.origin));
}
[[nodiscard]] CTransform inverse() const {
2018-12-07 17:16:50 -08:00
CMatrix3f inv = basis.inverted();
return CTransform(inv, inv * -origin);
}
[[nodiscard]] static CTransform Translate(const CVector3f& position) { return {CMatrix3f(), position}; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] static CTransform Translate(float x, float y, float z) { return Translate({x, y, z}); }
2018-12-07 17:16:50 -08:00
[[nodiscard]] CTransform operator+(const CVector3f& other) const { return CTransform(basis, origin + other); }
2018-12-07 17:16:50 -08:00
CTransform& operator+=(const CVector3f& other) {
origin += other;
return *this;
}
CTransform operator-(const CVector3f& other) const { return CTransform(basis, origin - other); }
2018-12-07 17:16:50 -08:00
CTransform& operator-=(const CVector3f& other) {
origin -= other;
return *this;
}
[[nodiscard]] CVector3f rotate(const CVector3f& vec) const { return basis * vec; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] static CTransform RotateX(float theta) {
const float sinT = std::sin(theta);
const float cosT = std::cos(theta);
2018-12-07 21:23:50 -08:00
return CTransform(CMatrix3f(simd<float>{1.f, 0.f, 0.f, 0.f}, simd<float>{0.f, cosT, sinT, 0.f},
2018-12-07 17:16:50 -08:00
simd<float>{0.f, -sinT, cosT, 0.f}));
}
[[nodiscard]] static CTransform RotateY(float theta) {
const float sinT = std::sin(theta);
const float cosT = std::cos(theta);
2018-12-07 21:23:50 -08:00
return CTransform(CMatrix3f(simd<float>{cosT, 0.f, -sinT, 0.f}, simd<float>{0.f, 1.f, 0.f, 0.f},
2018-12-07 17:16:50 -08:00
simd<float>{sinT, 0.f, cosT, 0.f}));
}
[[nodiscard]] static CTransform RotateZ(float theta) {
const float sinT = std::sin(theta);
const float cosT = std::cos(theta);
2018-12-07 21:23:50 -08:00
return CTransform(CMatrix3f(simd<float>{cosT, sinT, 0.f, 0.f}, simd<float>{-sinT, cosT, 0.f, 0.f},
2018-12-07 17:16:50 -08:00
simd<float>{0.f, 0.f, 1.f, 0.f}));
}
void rotateLocalX(float theta) {
float sinT = std::sin(theta);
float cosT = std::cos(theta);
zeus::CVector3f b2 = basis[2] * sinT;
zeus::CVector3f b1 = basis[1] * sinT;
zeus::CVector3f cosV(cosT);
basis[1] *= cosV;
basis[2] *= cosV;
basis[1] += b2;
basis[2] -= b1;
}
void rotateLocalY(float theta) {
float sinT = std::sin(theta);
float cosT = std::cos(theta);
zeus::CVector3f b0 = basis[0] * sinT;
zeus::CVector3f b2 = basis[2] * sinT;
zeus::CVector3f cosV(cosT);
basis[0] *= cosV;
basis[2] *= cosV;
basis[2] += b0;
basis[0] -= b2;
}
void rotateLocalZ(float theta) {
float sinT = std::sin(theta);
float cosT = std::cos(theta);
zeus::CVector3f b0 = basis[0] * sinT;
zeus::CVector3f b1 = basis[1] * sinT;
zeus::CVector3f cosV(cosT);
basis[0] *= cosV;
basis[1] *= cosV;
basis[0] += b1;
basis[1] -= b0;
}
[[nodiscard]] CVector3f transposeRotate(const CVector3f& in) const {
2018-12-07 17:16:50 -08:00
return CVector3f(basis[0].dot(in), basis[1].dot(in), basis[2].dot(in));
}
void scaleBy(float factor) {
CTransform xfrm(CMatrix3f(CVector3f(factor, factor, factor)));
*this = *this * xfrm;
}
[[nodiscard]] static CTransform Scale(const CVector3f& factor) {
2018-12-07 21:23:50 -08:00
return CTransform(CMatrix3f(simd<float>{factor.x(), 0.f, 0.f, 0.f}, simd<float>{0.f, factor.y(), 0.f, 0.f},
2018-12-07 17:16:50 -08:00
simd<float>{0.f, 0.f, factor.z(), 0.f}));
}
[[nodiscard]] static CTransform Scale(float x, float y, float z) {
2018-12-07 21:23:50 -08:00
return CTransform(
CMatrix3f(simd<float>{x, 0.f, 0.f, 0.f}, simd<float>{0.f, y, 0.f, 0.f}, simd<float>{0.f, 0.f, z, 0.f}));
2018-12-07 17:16:50 -08:00
}
[[nodiscard]] static CTransform Scale(float factor) {
2018-12-07 21:23:50 -08:00
return CTransform(CMatrix3f(simd<float>{factor, 0.f, 0.f, 0.f}, simd<float>{0.f, factor, 0.f, 0.f},
2018-12-07 17:16:50 -08:00
simd<float>{0.f, 0.f, factor, 0.f}));
}
[[nodiscard]] CTransform multiplyIgnoreTranslation(const CTransform& rhs) const {
2019-03-24 01:06:25 -07:00
return CTransform(basis * rhs.basis, origin + rhs.origin);
2018-12-07 17:16:50 -08:00
}
[[nodiscard]] CTransform getRotation() const {
2018-12-07 17:16:50 -08:00
CTransform ret = *this;
ret.origin.zeroOut();
return ret;
}
2018-12-07 21:23:50 -08:00
void setRotation(const CMatrix3f& mat) { basis = mat; }
2018-12-07 17:16:50 -08:00
2018-12-07 21:23:50 -08:00
void setRotation(const CTransform& xfrm) { setRotation(xfrm.basis); }
2018-12-07 17:16:50 -08:00
/**
* @brief buildMatrix3f Returns the stored matrix
* buildMatrix3f is here for compliance with Retro's Math API
* @return The Matrix (Neo, you are the one)
*/
[[nodiscard]] const CMatrix3f& buildMatrix3f() const { return basis; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] CVector3f operator*(const CVector3f& other) const { return origin + basis * other; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] CMatrix4f toMatrix4f() const {
2018-12-07 17:16:50 -08:00
CMatrix4f ret(basis[0], basis[1], basis[2], origin);
ret[0][3] = 0.0f;
ret[1][3] = 0.0f;
ret[2][3] = 0.0f;
ret[3][3] = 1.0f;
return ret;
}
[[nodiscard]] CVector3f upVector() const { return basis.m[2]; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] CVector3f frontVector() const { return basis.m[1]; }
2018-12-07 17:16:50 -08:00
[[nodiscard]] CVector3f rightVector() const { return basis.m[0]; }
2018-12-07 17:16:50 -08:00
void orthonormalize() {
basis[0].normalize();
basis[2] = basis[0].cross(basis[1]);
basis[2].normalize();
basis[1] = basis[2].cross(basis[0]);
}
void printMatrix() const {
2018-12-07 21:23:50 -08:00
printf(
"%f %f %f %f\n"
"%f %f %f %f\n"
"%f %f %f %f\n"
"%f %f %f %f\n",
basis[0][0], basis[1][0], basis[2][0], origin[0], basis[0][1], basis[1][1], basis[2][1], origin[1], basis[0][2],
basis[1][2], basis[2][2], origin[2], 0.f, 0.f, 0.f, 1.f);
2018-12-07 17:16:50 -08:00
}
[[nodiscard]] static CTransform MakeRotationsBasedOnY(const CUnitVector3f& uVec) {
2018-12-07 17:16:50 -08:00
uint32_t i;
if (uVec.y() < uVec.x() || uVec.z() < uVec.y() || uVec.z() < uVec.x())
i = 2;
else
i = 1;
2019-02-23 23:15:32 -08:00
CVector3f v;
2018-12-07 17:16:50 -08:00
v[i] = 1.f;
CUnitVector3f newUVec(uVec.cross(v));
2019-02-23 23:15:32 -08:00
return {newUVec, uVec, uVec.cross(newUVec), CVector3f()};
2018-12-07 17:16:50 -08:00
}
CMatrix3f basis;
CVector3f origin;
2015-04-19 13:39:16 -07:00
};
[[nodiscard]] inline CTransform CTransformFromScaleVector(const CVector3f& scale) {
return CTransform(CMatrix3f(scale));
}
2018-12-07 17:16:50 -08:00
[[nodiscard]] CTransform CTransformFromEditorEuler(const CVector3f& eulerVec);
2018-12-07 17:16:50 -08:00
[[nodiscard]] CTransform CTransformFromEditorEulers(const CVector3f& eulerVec, const CVector3f& origin);
2018-12-07 17:16:50 -08:00
[[nodiscard]] CTransform CTransformFromAxisAngle(const CVector3f& axis, float angle);
2018-12-07 17:16:50 -08:00
[[nodiscard]] CTransform lookAt(const CVector3f& pos, const CVector3f& lookPos, const CVector3f& up = skUp);
2018-12-07 21:23:50 -08:00
} // namespace zeus