123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- #pragma once
- #include <iostream>
- #include "Logging.h"
- #include "Mat3.h"
- #include "Vec3.h"
- namespace Framework
- {
- template<typename T>
- //! Eine 4x4 Matrix
- class Mat4
- {
- public:
- T elements[4][4]; //! Die Elemente der Matrix
- //! Kopiert alle Werte einer anderen Matrix
- //! \param r Die andere Matrix
- Mat4& operator=(const Mat4& r)
- {
- memcpy(elements, r.elements, sizeof(elements));
- return *this;
- }
- //! Skalliert die Matrix
- //! \param r der Faktor
- Mat4& operator*=(const T r)
- {
- for (T& e : elements)
- e *= r;
- return *this;
- }
- //! Multipliziert die MAtrix mit einer anderen
- //! \param r Die andere Matrix
- Mat4& operator*=(const Mat4& r)
- {
- return *this = *this * r;
- }
- //! Skalliert die Matrix ohne sie zu verändern
- //! \param r der Faktor
- Mat4 operator*(const T r) const
- {
- Mat4 result = *this;
- return result *= r;
- }
- //! Multipliziert zwei Matrizen
- //! \param r Die andere Matrix
- Mat4 operator*(const Mat4& r) const
- {
- Mat4 result;
- for (int j = 0; j < 4; j++)
- {
- for (int k = 0; k < 4; k++)
- {
- T sum = 0;
- for (int i = 0; i < 4; i++)
- sum += elements[j][i] * r.elements[i][k];
- result.elements[j][k] = sum;
- }
- }
- return result;
- }
- //! Multiplziert die Matrix mit einem Vektor
- //! \param r Der Vektor
- Vec3<T> operator*(const Vec3<T>& r) const
- {
- Vec3<T> result;
- result.x = elements[0][0] * r.x + elements[0][1] * r.y
- + elements[0][2] * r.z + elements[0][3];
- result.y = elements[1][0] * r.x + elements[1][1] * r.y
- + elements[1][2] * r.z + elements[1][3];
- result.z = elements[2][0] * r.x + elements[2][1] * r.y
- + elements[2][2] * r.z + elements[2][3];
- return result;
- }
- Vec3<T> mult0(const Vec3<T>& r) const
- {
- Vec3<T> result;
- result.x = elements[0][0] * r.x + elements[0][1] * r.y
- + elements[0][2] * r.z;
- result.y = elements[1][0] * r.x + elements[1][1] * r.y
- + elements[1][2] * r.z;
- result.z = elements[2][0] * r.x + elements[2][1] * r.y
- + elements[2][2] * r.z;
- return result;
- }
- //! Berechnet die inverse Matrix
- Mat4 getInverse() const
- {
- Mat4 ret;
- ret.elements[0][0]
- = elements[1][1] * elements[2][2] * elements[3][3]
- - elements[1][1] * elements[2][3] * elements[3][2]
- - elements[2][1] * elements[1][2] * elements[3][3]
- + elements[2][1] * elements[1][3] * elements[3][2]
- + elements[3][1] * elements[1][2] * elements[2][3]
- - elements[3][1] * elements[1][3] * elements[2][2];
- ret.elements[1][0]
- = -elements[1][0] * elements[2][2] * elements[3][3]
- + elements[1][0] * elements[2][3] * elements[3][2]
- + elements[2][0] * elements[1][2] * elements[3][3]
- - elements[2][0] * elements[1][3] * elements[3][2]
- - elements[3][0] * elements[1][2] * elements[2][3]
- + elements[3][0] * elements[1][3] * elements[2][2];
- ret.elements[2][0]
- = elements[1][0] * elements[2][1] * elements[3][3]
- - elements[1][0] * elements[2][3] * elements[3][1]
- - elements[2][0] * elements[1][1] * elements[3][3]
- + elements[2][0] * elements[1][3] * elements[3][1]
- + elements[3][0] * elements[1][1] * elements[2][3]
- - elements[3][0] * elements[1][3] * elements[2][1];
- ret.elements[3][0]
- = -elements[1][0] * elements[2][1] * elements[3][2]
- + elements[1][0] * elements[2][2] * elements[3][1]
- + elements[2][0] * elements[1][1] * elements[3][2]
- - elements[2][0] * elements[1][2] * elements[3][1]
- - elements[3][0] * elements[1][1] * elements[2][2]
- + elements[3][0] * elements[1][2] * elements[2][1];
- ret.elements[0][1]
- = -elements[0][1] * elements[2][2] * elements[3][3]
- + elements[0][1] * elements[2][3] * elements[3][2]
- + elements[2][1] * elements[0][2] * elements[3][3]
- - elements[2][1] * elements[0][3] * elements[3][2]
- - elements[3][1] * elements[0][2] * elements[2][3]
- + elements[3][1] * elements[0][3] * elements[2][2];
- ret.elements[1][1]
- = elements[0][0] * elements[2][2] * elements[3][3]
- - elements[0][0] * elements[2][3] * elements[3][2]
- - elements[2][0] * elements[0][2] * elements[3][3]
- + elements[2][0] * elements[0][3] * elements[3][2]
- + elements[3][0] * elements[0][2] * elements[2][3]
- - elements[3][0] * elements[0][3] * elements[2][2];
- ret.elements[2][1]
- = -elements[0][0] * elements[2][1] * elements[3][3]
- + elements[0][0] * elements[2][3] * elements[3][1]
- + elements[2][0] * elements[0][1] * elements[3][3]
- - elements[2][0] * elements[0][3] * elements[3][1]
- - elements[3][0] * elements[0][1] * elements[2][3]
- + elements[3][0] * elements[0][3] * elements[2][1];
- ret.elements[3][1]
- = elements[0][0] * elements[2][1] * elements[3][2]
- - elements[0][0] * elements[2][2] * elements[3][1]
- - elements[2][0] * elements[0][1] * elements[3][2]
- + elements[2][0] * elements[0][2] * elements[3][1]
- + elements[3][0] * elements[0][1] * elements[2][2]
- - elements[3][0] * elements[0][2] * elements[2][1];
- ret.elements[0][2]
- = elements[0][1] * elements[1][2] * elements[3][3]
- - elements[0][1] * elements[1][3] * elements[3][2]
- - elements[1][1] * elements[0][2] * elements[3][3]
- + elements[1][1] * elements[0][3] * elements[3][2]
- + elements[3][1] * elements[0][2] * elements[1][3]
- - elements[3][1] * elements[0][3] * elements[1][2];
- ret.elements[1][2]
- = -elements[0][0] * elements[1][2] * elements[3][3]
- + elements[0][0] * elements[1][3] * elements[3][2]
- + elements[1][0] * elements[0][2] * elements[3][3]
- - elements[1][0] * elements[0][3] * elements[3][2]
- - elements[3][0] * elements[0][2] * elements[1][3]
- + elements[3][0] * elements[0][3] * elements[1][2];
- ret.elements[2][2]
- = elements[0][0] * elements[1][1] * elements[3][3]
- - elements[0][0] * elements[1][3] * elements[3][1]
- - elements[1][0] * elements[0][1] * elements[3][3]
- + elements[1][0] * elements[0][3] * elements[3][1]
- + elements[3][0] * elements[0][1] * elements[1][3]
- - elements[3][0] * elements[0][3] * elements[1][1];
- ret.elements[3][2]
- = -elements[0][0] * elements[1][1] * elements[3][2]
- + elements[0][0] * elements[1][2] * elements[3][1]
- + elements[1][0] * elements[0][1] * elements[3][2]
- - elements[1][0] * elements[0][2] * elements[3][1]
- - elements[3][0] * elements[0][1] * elements[1][2]
- + elements[3][0] * elements[0][2] * elements[1][1];
- ret.elements[0][3]
- = -elements[0][1] * elements[1][2] * elements[2][3]
- + elements[0][1] * elements[1][3] * elements[2][2]
- + elements[1][1] * elements[0][2] * elements[2][3]
- - elements[1][1] * elements[0][3] * elements[2][2]
- - elements[2][1] * elements[0][2] * elements[1][3]
- + elements[2][1] * elements[0][3] * elements[1][2];
- ret.elements[1][3]
- = elements[0][0] * elements[1][2] * elements[2][3]
- - elements[0][0] * elements[1][3] * elements[2][2]
- - elements[1][0] * elements[0][2] * elements[2][3]
- + elements[1][0] * elements[0][3] * elements[2][2]
- + elements[2][0] * elements[0][2] * elements[1][3]
- - elements[2][0] * elements[0][3] * elements[1][2];
- ret.elements[2][3]
- = -elements[0][0] * elements[1][1] * elements[2][3]
- + elements[0][0] * elements[1][3] * elements[2][1]
- + elements[1][0] * elements[0][1] * elements[2][3]
- - elements[1][0] * elements[0][3] * elements[2][1]
- - elements[2][0] * elements[0][1] * elements[1][3]
- + elements[2][0] * elements[0][3] * elements[1][1];
- ret.elements[3][3]
- = elements[0][0] * elements[1][1] * elements[2][2]
- - elements[0][0] * elements[1][2] * elements[2][1]
- - elements[1][0] * elements[0][1] * elements[2][2]
- + elements[1][0] * elements[0][2] * elements[2][1]
- + elements[2][0] * elements[0][1] * elements[1][2]
- - elements[2][0] * elements[0][2] * elements[1][1];
- T det = elements[0][0] * ret.elements[0][0]
- + elements[0][1] * ret.elements[1][0]
- + elements[0][2] * ret.elements[2][0]
- + elements[0][3] * ret.elements[3][0];
- if (det == 0)
- {
- Logging::error() << "Fehler beim erstellen der Inversen Matrix";
- return ret;
- }
- det = 1.0f / det;
- for (int i = 0; i < 16; i++)
- ret.elements[i / 4][i % 4] = ret.elements[i / 4][i % 4] * det;
- return ret;
- }
- //! Erzeugt eine Matrix, die einen Vektor um die Z Achse dreht, wenn sie
- //! mit ihm multipliziert wird \param radian Der Winkel in Bogenmas
- static Mat4 rotationZ(T radian)
- {
- const T cosTheta = (T)lowPrecisionCos(radian);
- const T sinTheta = (T)lowPrecisionSin(radian);
- Mat4 r = {cosTheta,
- -sinTheta,
- 0,
- 0,
- sinTheta,
- cosTheta,
- 0,
- 0,
- 0,
- 0,
- 1,
- 0,
- 0,
- 0,
- 0,
- 1};
- return r;
- }
- //! Erzeugt eine Matrix, die einen Vektor um die X Achse dreht, wenn sie
- //! mit ihm multipliziert wird \param radian Der Winkel in Bogenmas
- static Mat4 rotationX(T radian)
- {
- const T cosTheta = (T)lowPrecisionCos(radian);
- const T sinTheta = (T)lowPrecisionSin(radian);
- Mat4 r = {1,
- 0,
- 0,
- 0,
- 0,
- cosTheta,
- -sinTheta,
- 0,
- 0,
- sinTheta,
- cosTheta,
- 0,
- 0,
- 0,
- 0,
- 1};
- return r;
- }
- //! Erzeugt eine Matrix, die einen Vektor um die Y Achse dreht, wenn sie
- //! mit ihm multipliziert wird \param radian Der Winkel in Bogenmas
- static Mat4 rotationY(T radian)
- {
- const T cosTheta = (T)lowPrecisionCos(radian);
- const T sinTheta = (T)lowPrecisionSin(radian);
- Mat4 r = {cosTheta,
- 0,
- sinTheta,
- 0,
- 0,
- 1,
- 0,
- 0,
- -sinTheta,
- 0,
- cosTheta,
- 0,
- 0,
- 0,
- 0,
- 1};
- return r;
- }
- //! Erzeugt eine Matrix, die einen Vektor Skalliert, wenn sie mit ihm
- //! multipliziert wird \param faktor Der Faktor
- static Mat4 scaling(T faktor)
- {
- Mat4 s = {
- faktor, 0, 0, 0, 0, faktor, 0, 0, 0, 0, faktor, 0, 0, 0, 0, 1};
- return s;
- }
- //! Erzeugt eine Matrix, die einen Vektor Skalliert, wenn sie mit ihm
- //! multipliziert wird \param faktorX Der Faktor für die X Komponente
- //! des Vektors \param faktorY Der Faktor für die Y Komponente des
- //! Vektors \param faktorZ Der Faktor für die Z Komponente des Vektors
- static Mat4 scaling(T faktorX, T faktorY, T faktorZ)
- {
- Mat4 s = {faktorX,
- 0,
- 0,
- 0,
- 0,
- faktorY,
- 0,
- 0,
- 0,
- 0,
- faktorZ,
- 0,
- 0,
- 0,
- 0,
- 1};
- return s;
- }
- //! Erzeugt eine Matrix, die einen Vektor verchiebt, wenn sie mit ihm
- //! multipliziert wird \param offset Die Koordinaten, um die der Vektor
- //! verschoben werden soll
- static Mat4 translation(const Vec3<T> offset)
- {
- Mat4 t = {1,
- 0,
- 0,
- offset.x,
- 0,
- 1,
- 0,
- offset.y,
- 0,
- 0,
- 1,
- offset.z,
- 0,
- 0,
- 0,
- 1};
- return t;
- }
- //! Erzeugt eine Matrix, die einen Vektor auf den Bildschirm Projeziert
- //! \param openingAngle Der Öffnungswinkel der Kamera im Bogenmas
- //! \param bildschirmXY Das Seitenverhältnis des Rechtecks auf dem
- //! Bildschirm, in dem gezeichnet werden soll. (Breite / Höhe) \param
- //! minz Der Mindestabstand zur Kamera, ab dem gezeichnet wird \param
- //! maxZ Der Maximalabstand zur Kamera, ab dem nicht mehr gezeichnet
- //! wird
- static Mat4 projektion(
- float openingAngle, float bildschirmXY, float minZ, float maxZ)
- {
- Mat4 p = {(float)(1 / tan(openingAngle / 2)) / bildschirmXY,
- 0,
- 0,
- 0,
- 0,
- (float)(1 / tan(openingAngle / 2)),
- 0,
- 0,
- 0,
- 0,
- maxZ / (maxZ - minZ),
- -(minZ * maxZ) / (maxZ - minZ),
- 0,
- 0,
- 1,
- 0};
- return p;
- }
- //! Erzeugt eine Matrix, die mit allem Multipliziert werden kann ohne es
- //! zu ändern
- static Mat4 identity()
- {
- Mat4 i = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
- return i;
- }
- //! Gibt eine Rotationsmatrix zurück, so dass vector a wenn man ihn
- //! damit dreht in richtung des vectors b zeigt \param a der vector der
- //! gedreht werden soll \param b der vector zu dem gedreht werden soll
- static Mat4 rotationTo(Vec3<T>& a, Vec3<T>& b)
- {
- Vec3<T> aNorm = Vec3<T>(a).normalize();
- Vec3<T> bNorm = Vec3<T>(b).normalize();
- Vec3<T> v = aNorm.crossProduct(bNorm);
- T s = v.getLengthSq();
- T c = aNorm * bNorm;
- T m = (1 - c) / s;
- Mat3<T> cpm({0, -v.z, v.y, v.z, 0, -v.x, -v.y, v.x, 0});
- Mat3<T> cpm2 = cpm * cpm;
- Mat3<T> res = Mat3<T>::identity() + cpm + cpm2 * m;
- return Mat4({res.elements[0][0],
- res.elements[0][1],
- res.elements[0][2],
- 0,
- res.elements[1][0],
- res.elements[1][1],
- res.elements[1][2],
- 0,
- res.elements[2][0],
- res.elements[2][1],
- res.elements[2][2],
- 0,
- 0,
- 0,
- 0,
- 1});
- }
- };
- } // namespace Framework
|