| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- // zlib open source license
- //
- // Copyright (c) 2017 to 2019 David Forsgren Piuva
- //
- // 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 DFPSR_GEOMETRY_TRANSFORM3D
- #define DFPSR_GEOMETRY_TRANSFORM3D
- #include "FVector.h"
- #include "FMatrix3x3.h"
- namespace dsr {
- struct Transform3D {
- FVector3D position;
- FMatrix3x3 transform;
- Transform3D() : position(0.0f, 0.0f, 0.0f), transform(FVector3D(1.0f, 0.0f, 0.0f), FVector3D(0.0f, 1.0f, 0.0f), FVector3D(0.0f, 0.0f, 1.0f)) {}
- Transform3D(const FVector3D &position, const FMatrix3x3 &transform) :
- position(position),
- transform(transform) {}
- // Transform the point by multiplying with the 3x3 matrix and adding the translation
- FVector3D transformPoint(const FVector3D &p) const {
- return this->transform.transform(p) + this->position;
- }
- // Transform the vector by multiplying with the 3x3 matrix
- FVector3D transformVector(const FVector3D &p) const {
- return this->transform.transform(p);
- }
- // Transform the a vector by multiplying with the transpose of the 3x3 matrix
- // The transpose is the inverse for axis aligned normalized matrices
- // Precondition: The transform must be normalized and axis aligned (Allows rotation but no shear nor scaling)
- FVector3D transformPointTransposedInverse(const FVector3D &p) const {
- return this->transform.transformTransposed(p - this->position);
- }
- };
- inline Transform3D operator*(const Transform3D &left, const Transform3D &right) {
- return Transform3D(right.transformPoint(left.position), left.transform * right.transform);
- }
- // The determinant of a transform is the volume of a cube transformed by the matrix.
- // Inside-out transforms have a negative volume. (mirrored by negating one axis or swapping two)
- inline float determinant(const Transform3D& m) {
- return determinant(m.transform);
- }
- inline Transform3D inverseUsingInvDet(const Transform3D& m, float invDet) {
- Transform3D result;
- result.transform.xAxis.x = invDet * (m.transform.yAxis.y * m.transform.zAxis.z - m.transform.yAxis.z * m.transform.zAxis.y);
- result.transform.xAxis.y = -invDet * (m.transform.xAxis.y * m.transform.zAxis.z - m.transform.xAxis.z * m.transform.zAxis.y);
- result.transform.xAxis.z = invDet * (m.transform.xAxis.y * m.transform.yAxis.z - m.transform.xAxis.z * m.transform.yAxis.y);
- result.transform.yAxis.x = -invDet * (m.transform.yAxis.x * m.transform.zAxis.z - m.transform.yAxis.z * m.transform.zAxis.x);
- result.transform.yAxis.y = invDet * (m.transform.xAxis.x * m.transform.zAxis.z - m.transform.xAxis.z * m.transform.zAxis.x);
- result.transform.yAxis.z = -invDet * (m.transform.xAxis.x * m.transform.yAxis.z - m.transform.xAxis.z * m.transform.yAxis.x);
- result.transform.zAxis.x = invDet * (m.transform.yAxis.x * m.transform.zAxis.y - m.transform.yAxis.y * m.transform.zAxis.x);
- result.transform.zAxis.y = -invDet * (m.transform.xAxis.x * m.transform.zAxis.y - m.transform.xAxis.y * m.transform.zAxis.x);
- result.transform.zAxis.z = invDet * (m.transform.xAxis.x * m.transform.yAxis.y - m.transform.xAxis.y * m.transform.yAxis.x);
- result.position.x = -(m.position.x * result.transform.xAxis.x + m.position.y * result.transform.yAxis.x + m.position.z * result.transform.zAxis.x);
- result.position.y = -(m.position.x * result.transform.xAxis.y + m.position.y * result.transform.yAxis.y + m.position.z * result.transform.zAxis.y);
- result.position.z = -(m.position.x * result.transform.xAxis.z + m.position.y * result.transform.yAxis.z + m.position.z * result.transform.zAxis.z);
- return result;
- }
- inline Transform3D inverse(const Transform3D& m) {
- return inverseUsingInvDet(m, 1.0f / determinant(m));
- }
- inline String& string_toStreamIndented(String& target, const Transform3D& source, const ReadableString& indentation) {
- string_append(target, indentation, U"XAxis(", source.transform.xAxis, U"), YAxis(", source.transform.yAxis, U"), ZAxis(", source.transform.zAxis, U"), Position(", source.position, U")");
- return target;
- }
- }
- #endif
|