Browse Source

Trade: allow SceneField::Transformation to be a 3x2 or a 4x3 matrix.

Another thought I had was about allowing a 2x2 / 3x3 matrix to be used
for rotation, but there's the ambiguity with it possibly containing
scaling / shear / whatever, which would then cause EXPLODING HEADACHES
when converting to quaternions / complex numbers.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
e056ad3c99
  1. 24
      src/Magnum/Trade/SceneData.cpp
  2. 10
      src/Magnum/Trade/SceneData.h
  3. 68
      src/Magnum/Trade/Test/SceneDataTest.cpp

24
src/Magnum/Trade/SceneData.cpp

@ -644,11 +644,15 @@ SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong object
const SceneFieldType fieldType = _fields[transformationField]._fieldType; const SceneFieldType fieldType = _fields[transformationField]._fieldType;
if(fieldType == SceneFieldType::Matrix3x3 || if(fieldType == SceneFieldType::Matrix3x3 ||
fieldType == SceneFieldType::Matrix3x3d || fieldType == SceneFieldType::Matrix3x3d ||
fieldType == SceneFieldType::Matrix3x2 ||
fieldType == SceneFieldType::Matrix3x2d ||
fieldType == SceneFieldType::DualComplex || fieldType == SceneFieldType::DualComplex ||
fieldType == SceneFieldType::DualComplexd) fieldType == SceneFieldType::DualComplexd)
_dimensions = 2; _dimensions = 2;
else if(fieldType == SceneFieldType::Matrix4x4 || else if(fieldType == SceneFieldType::Matrix4x4 ||
fieldType == SceneFieldType::Matrix4x4d || fieldType == SceneFieldType::Matrix4x4d ||
fieldType == SceneFieldType::Matrix4x3 ||
fieldType == SceneFieldType::Matrix4x3d ||
fieldType == SceneFieldType::DualQuaternion || fieldType == SceneFieldType::DualQuaternion ||
fieldType == SceneFieldType::DualQuaterniond) fieldType == SceneFieldType::DualQuaterniond)
_dimensions = 3; _dimensions = 3;
@ -1200,6 +1204,18 @@ template<class Source, class Destination> void convertTransformation(const Conta
destination[i] = Destination{sourceT[i].toMatrix()}; destination[i] = Destination{sourceT[i].toMatrix()};
} }
/* Expands 2x3 to 3x3, 4x3 to 4x4, while potentially also converting floats to
doubles */
/** @todo also have some optimized batched API for this? doing a strided copy
and a fill seemed silly as that would cause the whole memory go through
cache twice */
template<class Source, class Destination> void expandTransformationMatrix(const Containers::StridedArrayView1D<const void>& source, const Containers::StridedArrayView1D<Destination>& destination) {
CORRADE_INTERNAL_ASSERT(source.size() == destination.size());
const auto sourceT = Containers::arrayCast<const Source>(source);
for(std::size_t i = 0; i != sourceT.size(); ++i)
destination[i] = Destination{Math::RectangularMatrix<Source::Cols, Source::Rows, Float>{sourceT[i]}};
}
/** @todo these (or the float variants at least) should eventually be replaced /** @todo these (or the float variants at least) should eventually be replaced
with optimized batched APIs (applyTranslationsInto() updating just the with optimized batched APIs (applyTranslationsInto() updating just the
last matrix column etc.) */ last matrix column etc.) */
@ -1299,6 +1315,10 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
Utility::copy(Containers::arrayCast<const Matrix3>(fieldData), destination); Utility::copy(Containers::arrayCast<const Matrix3>(fieldData), destination);
} else if(field._fieldType == SceneFieldType::Matrix3x3d) { } else if(field._fieldType == SceneFieldType::Matrix3x3d) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 9), destination1f); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 9), destination1f);
} else if(field._fieldType == SceneFieldType::Matrix3x2) {
expandTransformationMatrix<Matrix3x2>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Matrix3x2d) {
expandTransformationMatrix<Matrix3x2d>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualComplex) { } else if(field._fieldType == SceneFieldType::DualComplex) {
convertTransformation<DualComplex>(fieldData, destination); convertTransformation<DualComplex>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualComplexd) { } else if(field._fieldType == SceneFieldType::DualComplexd) {
@ -1525,6 +1545,10 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
Utility::copy(Containers::arrayCast<const Matrix4>(fieldData), destination); Utility::copy(Containers::arrayCast<const Matrix4>(fieldData), destination);
} else if(field._fieldType == SceneFieldType::Matrix4x4d) { } else if(field._fieldType == SceneFieldType::Matrix4x4d) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 16), destination1f); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 16), destination1f);
} else if(field._fieldType == SceneFieldType::Matrix4x3) {
expandTransformationMatrix<Matrix4x3>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Matrix4x3d) {
expandTransformationMatrix<Matrix4x3d>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualQuaternion) { } else if(field._fieldType == SceneFieldType::DualQuaternion) {
convertTransformation<DualQuaternion>(fieldData, destination); convertTransformation<DualQuaternion>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualQuaterniond) { } else if(field._fieldType == SceneFieldType::DualQuaterniond) {

10
src/Magnum/Trade/SceneData.h

@ -127,9 +127,15 @@ enum class SceneField: UnsignedInt {
* Transformation. Type is usually @ref SceneFieldType::Matrix3x3 for 2D * Transformation. Type is usually @ref SceneFieldType::Matrix3x3 for 2D
* and @ref SceneFieldType::Matrix4x4 for 3D, but can be also any of * and @ref SceneFieldType::Matrix4x4 for 3D, but can be also any of
* @relativeref{SceneFieldType,Matrix3x3d}, * @relativeref{SceneFieldType,Matrix3x3d},
* @relativeref{SceneFieldType,Matrix3x2} or
* @relativeref{SceneFieldType,Matrix3x2d} (with the bottom row implicitly
* assumed to be @f$ \begin{pmatrix} 0 & 0 & 1 \end{pmatrix} @f$),
* @relativeref{SceneFieldType,DualComplex} or * @relativeref{SceneFieldType,DualComplex} or
* @relativeref{SceneFieldType,DualComplexd} for 2D and * @relativeref{SceneFieldType,DualComplexd} for 2D and
* @relativeref{SceneFieldType,Matrix4x4d}, * @relativeref{SceneFieldType,Matrix4x4d},
* @relativeref{SceneFieldType,Matrix4x3} or
* @relativeref{SceneFieldType,Matrix4x3d} (with the bottom row implicitly
* assumed to be @f$ \begin{pmatrix} 0 & 0 & 0 & 1 \end{pmatrix} @f$),
* @relativeref{SceneFieldType,DualQuaternion} or * @relativeref{SceneFieldType,DualQuaternion} or
* @relativeref{SceneFieldType,DualQuaterniond} for 3D. An object should * @relativeref{SceneFieldType,DualQuaterniond} for 3D. An object should
* have only one transformation, altough this isn't enforced in any way, * have only one transformation, altough this isn't enforced in any way,
@ -2490,6 +2496,10 @@ namespace Implementation {
type == SceneFieldType::Matrix3x3d || type == SceneFieldType::Matrix3x3d ||
type == SceneFieldType::Matrix4x4 || type == SceneFieldType::Matrix4x4 ||
type == SceneFieldType::Matrix4x4d || type == SceneFieldType::Matrix4x4d ||
type == SceneFieldType::Matrix3x2 ||
type == SceneFieldType::Matrix3x2d ||
type == SceneFieldType::Matrix4x3 ||
type == SceneFieldType::Matrix4x3d ||
type == SceneFieldType::DualComplex || type == SceneFieldType::DualComplex ||
type == SceneFieldType::DualComplexd || type == SceneFieldType::DualComplexd ||
type == SceneFieldType::DualQuaternion || type == SceneFieldType::DualQuaternion ||

68
src/Magnum/Trade/Test/SceneDataTest.cpp

@ -335,6 +335,8 @@ SceneDataTest::SceneDataTest() {
addTests({&SceneDataTest::parentsIntoArrayInvalidSizeOrOffset, addTests({&SceneDataTest::parentsIntoArrayInvalidSizeOrOffset,
&SceneDataTest::transformations2DAsArray<Matrix3>, &SceneDataTest::transformations2DAsArray<Matrix3>,
&SceneDataTest::transformations2DAsArray<Matrix3d>, &SceneDataTest::transformations2DAsArray<Matrix3d>,
&SceneDataTest::transformations2DAsArray<Matrix3x2>,
&SceneDataTest::transformations2DAsArray<Matrix3x2d>,
&SceneDataTest::transformations2DAsArray<DualComplex>, &SceneDataTest::transformations2DAsArray<DualComplex>,
&SceneDataTest::transformations2DAsArray<DualComplexd>, &SceneDataTest::transformations2DAsArray<DualComplexd>,
&SceneDataTest::transformations2DAsArrayTRS<Float, Float, Double>, &SceneDataTest::transformations2DAsArrayTRS<Float, Float, Double>,
@ -349,6 +351,8 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::transformations2DIntoArrayInvalidSizeOrOffsetTRS, &SceneDataTest::transformations2DIntoArrayInvalidSizeOrOffsetTRS,
&SceneDataTest::transformations3DAsArray<Matrix4>, &SceneDataTest::transformations3DAsArray<Matrix4>,
&SceneDataTest::transformations3DAsArray<Matrix4d>, &SceneDataTest::transformations3DAsArray<Matrix4d>,
&SceneDataTest::transformations3DAsArray<Matrix4x3>,
&SceneDataTest::transformations3DAsArray<Matrix4x3d>,
&SceneDataTest::transformations3DAsArray<DualQuaternion>, &SceneDataTest::transformations3DAsArray<DualQuaternion>,
&SceneDataTest::transformations3DAsArray<DualQuaterniond>, &SceneDataTest::transformations3DAsArray<DualQuaterniond>,
&SceneDataTest::transformations3DAsArrayTRS<Float, Double, Double>, &SceneDataTest::transformations3DAsArrayTRS<Float, Double, Double>,
@ -1779,8 +1783,12 @@ _c(Vector3)
_c(Vector3d) _c(Vector3d)
_c(Matrix3) _c(Matrix3)
_c(Matrix3d) _c(Matrix3d)
_c(Matrix3x2)
_c(Matrix3x2d)
_c(Matrix4) _c(Matrix4)
_c(Matrix4d) _c(Matrix4d)
_c(Matrix4x3)
_c(Matrix4x3d)
_c(Complex) _c(Complex)
_c(Complexd) _c(Complexd)
_c(Quaternion) _c(Quaternion)
@ -1805,8 +1813,10 @@ template<class T> void SceneDataTest::constructMismatchedTRSDimensionality() {
#endif #endif
SceneFieldData transformationMatrices2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix3<T>>::type(), nullptr}; SceneFieldData transformationMatrices2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix3<T>>::type(), nullptr};
SceneFieldData transformationRectangularMatrices2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix3x2<T>>::type(), nullptr};
SceneFieldData transformations2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::DualComplex<T>>::type(), nullptr}; SceneFieldData transformations2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::DualComplex<T>>::type(), nullptr};
SceneFieldData transformationMatrices3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix4<T>>::type(), nullptr}; SceneFieldData transformationMatrices3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix4<T>>::type(), nullptr};
SceneFieldData transformationRectangularMatrices3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix4x3<T>>::type(), nullptr};
SceneFieldData transformations3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::DualQuaternion<T>>::type(), nullptr}; SceneFieldData transformations3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::DualQuaternion<T>>::type(), nullptr};
SceneFieldData translations2D{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector2<T>>::type(), nullptr}; SceneFieldData translations2D{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector2<T>>::type(), nullptr};
SceneFieldData translations3D{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector3<T>>::type(), nullptr}; SceneFieldData translations3D{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector3<T>>::type(), nullptr};
@ -1821,6 +1831,10 @@ template<class T> void SceneDataTest::constructMismatchedTRSDimensionality() {
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, translations3D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, translations3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, rotations3D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, rotations3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, scalings3D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, scalings3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationRectangularMatrices2D, translations3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationRectangularMatrices2D, rotations3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationRectangularMatrices2D, scalings3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, translations3D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, translations3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, rotations3D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, rotations3D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, scalings3D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, scalings3D}};
@ -1831,6 +1845,10 @@ template<class T> void SceneDataTest::constructMismatchedTRSDimensionality() {
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, translations2D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, translations2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, rotations2D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, rotations2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, scalings2D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, scalings2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationRectangularMatrices3D, translations2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationRectangularMatrices3D, rotations2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationRectangularMatrices3D, scalings2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, translations2D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, translations2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, rotations2D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, rotations2D}};
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, scalings2D}}; SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, scalings2D}};
@ -1841,6 +1859,10 @@ template<class T> void SceneDataTest::constructMismatchedTRSDimensionality() {
"Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n" "Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n"
"Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n" "Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n"
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n" "Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n"
"Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n"
"Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n"
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n"
"Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n" "Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n"
"Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n" "Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n"
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n" "Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n"
@ -1851,6 +1873,10 @@ template<class T> void SceneDataTest::constructMismatchedTRSDimensionality() {
"Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n" "Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n"
"Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n" "Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n"
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n" "Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n"
"Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n"
"Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n"
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n"
"Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n" "Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n"
"Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n" "Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n"
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n" "Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n"
@ -2429,10 +2455,21 @@ void SceneDataTest::parentsIntoArrayInvalidSizeOrOffset() {
"Trade::SceneData::parentsInto(): offset 4 out of bounds for a field of size 3\n"); "Trade::SceneData::parentsInto(): offset 4 out of bounds for a field of size 3\n");
} }
template<class T> struct TransformationTypeFor {
typedef T Type;
};
template<class T> struct TransformationTypeFor<Math::Matrix3x2<T>> {
typedef Math::Matrix3<T> Type;
};
template<class T> struct TransformationTypeFor<Math::Matrix4x3<T>> {
typedef Math::Matrix4<T> Type;
};
template<class T> void SceneDataTest::transformations2DAsArray() { template<class T> void SceneDataTest::transformations2DAsArray() {
setTestCaseTemplateName(NameTraits<T>::name()); setTestCaseTemplateName(NameTraits<T>::name());
typedef typename T::Type U; typedef typename T::Type U;
typedef typename TransformationTypeFor<T>::Type TT;
struct Transformation { struct Transformation {
UnsignedInt object; UnsignedInt object;
@ -2451,12 +2488,12 @@ template<class T> void SceneDataTest::transformations2DAsArray() {
{NoInit, 4, transformations}, {NoInit, 4, transformations},
{NoInit, 2, components} {NoInit, 2, components}
}; };
transformations[0] = {1, T::translation({U(3.0), U(2.0)})}; transformations[0] = {1, T{TT::translation({U(3.0), U(2.0)})}};
transformations[1] = {0, T::rotation(Math::Deg<U>(35.0))}; transformations[1] = {0, T{TT::rotation(Math::Deg<U>(35.0))}};
transformations[2] = {4, T::translation({U(1.5), U(2.5)})* transformations[2] = {4, T{TT::translation({U(1.5), U(2.5)})*
T::rotation(Math::Deg<U>(-15.0))}; TT::rotation(Math::Deg<U>(-15.0))}};
transformations[3] = {5, T::rotation(Math::Deg<U>(-15.0))* transformations[3] = {5, T{TT::rotation(Math::Deg<U>(-15.0))*
T::translation({U(1.5), U(2.5)})}; TT::translation({U(1.5), U(2.5)})}};
/* Object number 4 additionally has a scaling component (which isn't /* Object number 4 additionally has a scaling component (which isn't
representable with dual complex numbers). It currently doesn't get added representable with dual complex numbers). It currently doesn't get added
to the transformations returned from transformations2DInto() but that to the transformations returned from transformations2DInto() but that
@ -2980,6 +3017,7 @@ template<class T> void SceneDataTest::transformations3DAsArray() {
setTestCaseTemplateName(NameTraits<T>::name()); setTestCaseTemplateName(NameTraits<T>::name());
typedef typename T::Type U; typedef typename T::Type U;
typedef typename TransformationTypeFor<T>::Type TT;
struct Transformation { struct Transformation {
UnsignedInt object; UnsignedInt object;
@ -2998,15 +3036,15 @@ template<class T> void SceneDataTest::transformations3DAsArray() {
{NoInit, 4, transformations}, {NoInit, 4, transformations},
{NoInit, 2, components} {NoInit, 2, components}
}; };
transformations[0] = {1, T::translation({U(3.0), U(2.0), U(-0.5)})}; transformations[0] = {1, T{TT::translation({U(3.0), U(2.0), U(-0.5)})}};
transformations[1] = {0, T::rotation(Math::Deg<U>(35.0), transformations[1] = {0, T{TT::rotation(Math::Deg<U>(35.0),
Math::Vector3<U>::yAxis())}; Math::Vector3<U>::yAxis())}};
transformations[2] = {4, T::translation({U(1.5), U(2.5), U(0.75)})* transformations[2] = {4, T{TT::translation({U(1.5), U(2.5), U(0.75)})*
T::rotation(Math::Deg<U>(-15.0), TT::rotation(Math::Deg<U>(-15.0),
Math::Vector3<U>::xAxis())}; Math::Vector3<U>::xAxis())}};
transformations[3] = {5, T::rotation(Math::Deg<U>(-15.0), transformations[3] = {5, T{TT::rotation(Math::Deg<U>(-15.0),
Math::Vector3<U>::xAxis())* Math::Vector3<U>::xAxis())*
T::translation({U(1.5), U(2.5), U(0.75)})}; TT::translation({U(1.5), U(2.5), U(0.75)})}};
/* Object number 4 additionally has a scaling component (which isn't /* Object number 4 additionally has a scaling component (which isn't
representable with dual quaternions). It currently doesn't get added representable with dual quaternions). It currently doesn't get added
to the transformations returned from transformations2DInto() but that to the transformations returned from transformations2DInto() but that

Loading…
Cancel
Save