mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2025-01-25 10:51:36 +00:00
215 lines
4.4 KiB
C++
215 lines
4.4 KiB
C++
|
|
#if !defined ( INCLUDED_TRANSFORMLIB_H )
|
|
#define INCLUDED_TRANSFORMLIB_H
|
|
|
|
class Matrix4;
|
|
|
|
/// \brief A transform node.
|
|
class Transformable
|
|
{
|
|
public:
|
|
static const char* getTypeName(){
|
|
return "Transformable";
|
|
}
|
|
/// \brief Returns the transform which maps the node's local-space into the local-space of its parent node.
|
|
virtual const Matrix4& localToParent() const = 0;
|
|
};
|
|
|
|
#include "math/matrix.h"
|
|
#include "math/quaternion.h"
|
|
|
|
|
|
/// \brief A transform node which has no effect.
|
|
class IdentityTransform : public Transformable
|
|
{
|
|
public:
|
|
/// \brief Returns the identity matrix.
|
|
const Matrix4& localToParent() const {
|
|
return g_matrix4_identity;
|
|
}
|
|
};
|
|
|
|
/// \brief A transform node which stores a generic transformation matrix.
|
|
class MatrixTransform : public Transformable
|
|
{
|
|
Matrix4 m_localToParent;
|
|
public:
|
|
MatrixTransform() : m_localToParent( g_matrix4_identity ){
|
|
}
|
|
|
|
Matrix4& localToParent(){
|
|
return m_localToParent;
|
|
}
|
|
/// \brief Returns the stored local->parent transform.
|
|
const Matrix4& localToParent() const {
|
|
return m_localToParent;
|
|
}
|
|
};
|
|
|
|
|
|
namespace Transform
|
|
{
|
|
class Translation
|
|
{
|
|
Vector3 m_value;
|
|
public:
|
|
Translation()
|
|
: m_value( 0, 0, 0 ){
|
|
}
|
|
const Vector3& get() const {
|
|
return m_value;
|
|
}
|
|
void set( const Vector3& value ){
|
|
m_value = value;
|
|
}
|
|
void translate( const Vector3& value ){
|
|
m_value[0] += value[0];
|
|
m_value[1] += value[1];
|
|
m_value[2] += value[2];
|
|
}
|
|
};
|
|
|
|
class Rotation
|
|
{
|
|
Quaternion m_value;
|
|
public:
|
|
Rotation()
|
|
: m_value( c_quaternion_identity ){
|
|
}
|
|
const Quaternion& get() const {
|
|
return m_value;
|
|
}
|
|
void set( const Quaternion& value ){
|
|
m_value = value;
|
|
}
|
|
void rotate( const Quaternion& value ){
|
|
quaternion_multiply_by_quaternion( m_value, value );
|
|
quaternion_normalise( m_value );
|
|
}
|
|
};
|
|
|
|
class Scale
|
|
{
|
|
Vector3 m_value;
|
|
public:
|
|
Scale()
|
|
: m_value( 1, 1, 1 ){
|
|
}
|
|
const Vector3& get() const {
|
|
return m_value;
|
|
}
|
|
void set( const Vector3& value ){
|
|
m_value = value;
|
|
}
|
|
void scale( const Vector3& value ){
|
|
m_value[0] *= value[0];
|
|
m_value[1] *= value[1];
|
|
m_value[2] *= value[2];
|
|
}
|
|
};
|
|
}
|
|
|
|
/// \brief A transform node composed of separate translation, rotation and scale transforms.
|
|
///
|
|
/// - Each component transform can be individually modified at any time.
|
|
/// - The transforms are applied in the order: Scale, Rotate, Translate.
|
|
/// - The transformation matrix produced is guaranteed to be affine and orthogonal.
|
|
class ComponentTransform : public Transformable
|
|
{
|
|
Transform::Translation m_translation;
|
|
Transform::Rotation m_rotation;
|
|
Transform::Scale m_scale;
|
|
mutable Matrix4 m_transform;
|
|
mutable bool m_changed;
|
|
|
|
void changed() const {
|
|
m_changed = true;
|
|
}
|
|
void evaluate() const {
|
|
if ( m_changed ) {
|
|
m_changed = false;
|
|
|
|
Matrix4 rotation( matrix4_rotation_for_quaternion_quantised( m_rotation.get() ) );
|
|
|
|
m_transform.xx() = rotation.xx() * m_scale.get().x();
|
|
m_transform.xy() = rotation.xy() * m_scale.get().x();
|
|
m_transform.xz() = rotation.xz() * m_scale.get().x();
|
|
m_transform.xw() = 0;
|
|
|
|
m_transform.yx() = rotation.yx() * m_scale.get().y();
|
|
m_transform.yy() = rotation.yy() * m_scale.get().y();
|
|
m_transform.yz() = rotation.yz() * m_scale.get().y();
|
|
m_transform.yw() = 0;
|
|
|
|
m_transform.zx() = rotation.zx() * m_scale.get().z();
|
|
m_transform.zy() = rotation.zy() * m_scale.get().z();
|
|
m_transform.zz() = rotation.zz() * m_scale.get().z();
|
|
m_transform.zw() = 0;
|
|
|
|
m_transform.tx() = m_translation.get().x();
|
|
m_transform.ty() = m_translation.get().y();
|
|
m_transform.tz() = m_translation.get().z();
|
|
m_transform.tw() = 1;
|
|
}
|
|
}
|
|
public:
|
|
ComponentTransform()
|
|
: m_changed( true ){
|
|
}
|
|
const Matrix4& localToParent() const {
|
|
evaluate();
|
|
return m_transform;
|
|
}
|
|
|
|
const Vector3& getTranslation(){
|
|
return m_translation.get();
|
|
}
|
|
const Quaternion& getRotation(){
|
|
return m_rotation.get();
|
|
}
|
|
const Vector3& getScale(){
|
|
return m_scale.get();
|
|
}
|
|
|
|
void setTranslation( const Vector3& value ){
|
|
m_translation.set( value );
|
|
changed();
|
|
}
|
|
void setRotation( const Quaternion& value ){
|
|
m_rotation.set( value );
|
|
changed();
|
|
}
|
|
void setScale( const Vector3& value ){
|
|
m_scale.set( value );
|
|
changed();
|
|
}
|
|
|
|
void translate( const Vector3& translation ){
|
|
m_translation.translate( translation );
|
|
changed();
|
|
}
|
|
void rotate( const Quaternion& rotation ){
|
|
m_rotation.rotate( rotation );
|
|
changed();
|
|
}
|
|
void scale( const Vector3& scale ){
|
|
m_scale.scale( scale );
|
|
changed();
|
|
}
|
|
|
|
void identity_translate(){
|
|
m_translation = Transform::Translation();
|
|
changed();
|
|
}
|
|
void identity_rotate(){
|
|
m_rotation = Transform::Rotation();
|
|
changed();
|
|
}
|
|
void identity_scale(){
|
|
m_scale = Transform::Scale();
|
|
changed();
|
|
}
|
|
};
|
|
|
|
|
|
#endif
|