mirror of
https://github.com/TTimo/GtkRadiant.git
synced 2025-01-11 04:21:08 +00:00
249 lines
5.2 KiB
C++
249 lines
5.2 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
|