Skip to content

Commit cf39d6b

Browse files
author
Sascha Brandt
committed
Added SQT class
1 parent b99c7f6 commit cf39d6b

File tree

2 files changed

+278
-1
lines changed

2 files changed

+278
-1
lines changed

CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ include(GNUInstallDirs)
1919
set(CMAKE_INSTALL_CMAKECONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/Geometry)
2020

2121
# Add the library
22-
add_library(Geometry
22+
add_library(Geometry SHARED
2323
BoundingSphere.cpp
2424
BoxHelper.cpp
2525
BoxIntersection.cpp
@@ -49,6 +49,7 @@ set_property(TARGET Geometry PROPERTY PUBLIC_HEADER
4949
RayBoxIntersection.h
5050
Rect.h
5151
Sphere.h
52+
SQT.h
5253
SRT.h
5354
Tetrahedron.h
5455
Tools.h

SQT.h

+276
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
/*
2+
This file is part of the Geometry library.
3+
Copyright (C) 2007-2012 Benjamin Eikel <[email protected]>
4+
Copyright (C) 2007-2012 Claudius Jähn <[email protected]>
5+
Copyright (C) 2007-2012 Ralf Petring <[email protected]>
6+
Copyright (C) 2020 Sascha Brandt <[email protected]>
7+
8+
This library is subject to the terms of the Mozilla Public License, v. 2.0.
9+
You should have received a copy of the MPL along with this library; see the
10+
file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
11+
*/
12+
#ifndef GEOMETRY_SQT_H
13+
#define GEOMETRY_SQT_H
14+
15+
#include "Angle.h"
16+
#include "Interpolation.h"
17+
#include "Quaternion.h"
18+
#include "Matrix3x3.h"
19+
#include "Vec3.h"
20+
#include "SRT.h"
21+
#include <array>
22+
#include <istream>
23+
#include <ostream>
24+
25+
namespace Geometry {
26+
27+
/**
28+
* SQT - scale, quaternion and translate.
29+
* A more compact qay to store scale, rotation & translation.
30+
*
31+
* @note internally the values are stored as translate, scale, quaternion to get a more GPU friendly memory layout (2 x vec4).
32+
*
33+
* [SQT]
34+
*/
35+
template <typename T_>
36+
class _SQT {
37+
public:
38+
typedef T_ value_t;
39+
typedef _Quaternion<value_t> quaternion_t;
40+
typedef _Angle<value_t> angle_t;
41+
typedef _Vec3<value_t> vec3_t;
42+
43+
private:
44+
//! Translation
45+
vec3_t t;
46+
//! Scale
47+
value_t s;
48+
//! Rotation
49+
quaternion_t q;
50+
51+
public:
52+
/**
53+
* @name Mainvec3_t
54+
*/
55+
//@{
56+
/**
57+
* [ctor]
58+
*/
59+
_SQT() : t(), s(static_cast<value_t>(1.0)), q() {
60+
}
61+
/**
62+
* [ctor] interpolation between sqt1 and sqt2, according to the factor blend (should be between 0 and 1);
63+
*/
64+
_SQT(const _SQT<value_t> & sqt1, const _SQT<value_t> & sqt2, float blend)
65+
: t(sqt1.t, sqt2.t, blend),
66+
s(Interpolation::linear(sqt1.s, sqt2.s, blend)),
67+
q(Interpolation::linear(sqt1.q, sqt2.q, blend)){
68+
}
69+
70+
//! Create an SQT by specifying all components explicitly.
71+
_SQT(const vec3_t & translation, const quaternion_t & rotation, value_t scaling)
72+
: t(translation), s(scaling), q(rotation) {
73+
q.normOrthoLize();
74+
}
75+
76+
/**
77+
* [ctor] Create an SQT from an SRT
78+
*/
79+
_SQT(const _SRT<value_t> & srt)
80+
: t(srt.getTranslation()),
81+
s(srt.getScale()),
82+
q(quaternion_t::matrixToQuaternion(srt.getRotation())) {
83+
}
84+
85+
/**
86+
* [ctor] pos, dir, up [,scale]
87+
* \note dir and up are normalized automatically.
88+
*/
89+
_SQT(vec3_t _pos, const vec3_t & _dir, const vec3_t & _up, value_t _scale = 1.0) : _SQT(_SRT<value_t>(_pos, _dir, _up, _scale)) {
90+
}
91+
92+
/*! [ x,y,z, scale, rx,ry,rz,rw ]
93+
\see toArray() */
94+
_SQT(const std::array<value_t, 8> & arr)
95+
: t(arr[0], arr[1], arr[2]),
96+
s(arr[3]),
97+
q(Quaternion(arr[4], arr[5], arr[6], arr[7])) {
98+
}
99+
100+
/**
101+
* @name Information
102+
*/
103+
//@{
104+
value_t getScale() const {
105+
return s;
106+
}
107+
const vec3_t & getTranslation() const {
108+
return t;
109+
}
110+
const quaternion_t & getRotation() const {
111+
return q;
112+
}
113+
const _Matrix3x3<value_t> & getRotationMatrix() const {
114+
return q.toMatrix();
115+
}
116+
_SRT<value_t> toSRT() const {
117+
return _SRT<value_t>(t, q.toMatrix(), s);
118+
}
119+
//@}
120+
121+
/**
122+
* @name Modification
123+
*/
124+
//@{
125+
void reset() {
126+
q.set(static_cast<value_t>(0.0), static_cast<value_t>(0.0), static_cast<value_t>(0.0), static_cast<value_t>(1.0));
127+
t.setValue(static_cast<value_t>(0.0));
128+
s = 1.0;
129+
}
130+
void setScale(value_t x) {
131+
s = x;
132+
}
133+
void scale(value_t x) {
134+
s *= x;
135+
}
136+
137+
void resetRotation() {
138+
q.set(static_cast<value_t>(0.0), static_cast<value_t>(0.0), static_cast<value_t>(0.0), static_cast<value_t>(1.0));
139+
}
140+
void setRotation(const quaternion_t & x) {
141+
q = x;
142+
}
143+
void setRotation(const vec3_t & dir, const vec3_t & up) {
144+
_Matrix3x3<value_t> m;
145+
m.setRotation(dir, up);
146+
q = quaternion_t::matrixToQuaternion(m);
147+
}
148+
149+
void setTranslation(const vec3_t & x) {
150+
t = x;
151+
}
152+
void translate(const vec3_t & v) {
153+
t += v;
154+
}
155+
void translateLocal(const vec3_t & v) {
156+
t += q.rotatePoint(v * s);
157+
}
158+
159+
void rotateLocal(const angle_t & angle, const vec3_t & axis) {
160+
quaternion_t q2;
161+
q2.makeRotate(angle, axis);
162+
q *= q2;
163+
}
164+
void rotateLocal_rad(float rad, const vec3_t & axis) {
165+
rotateLocal(angle_t::rad(rad), axis);
166+
}
167+
void rotateLocal_deg(float deg, const vec3_t & axis) {
168+
rotateLocal(angle_t::deg(deg), axis);
169+
}
170+
171+
void rotateRel(const angle_t & angle, const vec3_t & axis) {
172+
quaternion_t q2;
173+
q2.makeRotate(angle, axis);
174+
q = q2 * q;
175+
}
176+
177+
void rotateRel_rad(value_t rad, const vec3_t & axis) {
178+
rotateRel(angle_t::rad(rad), axis);
179+
}
180+
void rotateRel_deg(value_t deg, const vec3_t & axis) {
181+
rotateRel(angle_t::deg(deg), axis);
182+
}
183+
//@}
184+
185+
/**
186+
* @name Creation
187+
*/
188+
//@{
189+
const vec3_t operator*(const vec3_t & v) const {
190+
return q.rotatePoint(v * s) + t;
191+
}
192+
const _SQT<value_t> operator*(const _SQT<value_t> & sqt) const {
193+
_SQT<value_t> e;
194+
e.s = s * sqt.s;
195+
e.t = q.rotatePoint(sqt.t * e.s) + t;
196+
e.q = q * sqt.q;
197+
return e;
198+
}
199+
200+
/*! Like a multiplication, but applies the rotation of this sqt to translation
201+
of the given sqt which results in the same behaviour as
202+
( Matrix4x4 (*this) * Matrix4x4(sqt) )._toSQT() */
203+
_SQT<value_t> getTransformation(const _SQT<value_t> & sqt) const {
204+
const vec3_t pos((*this) * sqt.getTranslation());
205+
const vec3_t dir((*this) * (sqt.getDirVector() + sqt.getTranslation()) - pos);
206+
const vec3_t up((*this) * (sqt.getUpVector() + sqt.getTranslation()) - pos);
207+
return _SQT<value_t>(pos, dir, up, dir.length() * sqt.getScale());
208+
}
209+
_SQT<value_t> inverse() const {
210+
_SQT<value_t> e;
211+
e.s = 1 / s;
212+
e.q = q.inverse();
213+
e.t = e.q.rotatePoint(t * (-e.s));
214+
return e;
215+
}
216+
//@}
217+
218+
/**
219+
* @name Comparators
220+
*/
221+
//@{
222+
/*! compares this with other componentwise
223+
@param other the object to compare with
224+
@param epsilon the maximum allowed difference between the component pairs
225+
@return true iff any the absolute difference between any pai of components is larger than epsilon */
226+
bool equals(const _SQT & other, value_t epsilon) const {
227+
return t.equals(other.t, epsilon) && q.equals(other.q, epsilon) && std::abs(s - other.s) <= epsilon;
228+
}
229+
bool operator==(const _SQT<value_t> & sqt) const {
230+
return sqt.t == (*this).t && sqt.q == (*this).q && sqt.s == (*this).s;
231+
}
232+
bool operator!=(const _SQT<value_t> & sqt) const {
233+
return !((*this) == sqt);
234+
}
235+
//@}
236+
237+
/**
238+
* @name Conversion
239+
*/
240+
//@{
241+
void toArray(value_t fa[8]) const {
242+
fa[0] = static_cast<value_t>(t.getX());
243+
fa[1] = static_cast<value_t>(t.getY());
244+
fa[2] = static_cast<value_t>(t.getZ());
245+
fa[3] = static_cast<value_t>(s);
246+
fa[4] = static_cast<value_t>(q.x());
247+
fa[5] = static_cast<value_t>(q.y());
248+
fa[6] = static_cast<value_t>(q.z());
249+
fa[7] = static_cast<value_t>(q.w());
250+
}
251+
252+
std::array<value_t, 8> toArray() const {
253+
std::array<value_t, 8> arr;
254+
arr[0] = t.x(), arr[1] = t.y(), arr[2] = t.z();
255+
arr[3] = s;
256+
arr[4] = q.x(), arr[5] = q.y(), arr[6] = q.z(), arr[7] = q.w();
257+
return arr;
258+
}
259+
//@}
260+
261+
//! @name Serialization
262+
//@{
263+
friend std::ostream & operator<<(std::ostream & out, const _SQT & sqt) {
264+
return out << sqt.t << ' ' << sqt.s << ' ' << sqt.q;
265+
}
266+
friend std::istream & operator>>(std::istream & in, _SQT & sqt) {
267+
return in >> sqt.t >> sqt.s >> sqt.q;
268+
}
269+
//@}
270+
};
271+
typedef _SQT<float> SQT;
272+
typedef _SQT<float> SQTf;
273+
typedef _SQT<double> SQTd;
274+
}
275+
276+
#endif /* GEOMETRY_SQT_H */

0 commit comments

Comments
 (0)