/* * SOLID - Software Library for Interference Detection * * Copyright (C) 2001-2003 Dtecta. All rights reserved. * * This library may be distributed under the terms of the Q Public License * (QPL) as defined by Trolltech AS of Norway and appearing in the file * LICENSE.QPL included in the packaging of this file. * * This library may be distributed and/or modified under the terms of the * GNU General Public License (GPL) version 2 as published by the Free Software * Foundation and appearing in the file LICENSE.GPL included in the * packaging of this file. * * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Commercial use or any other use of this library not covered by either * the QPL or the GPL requires an additional license from Dtecta. * Please contact info@dtecta.com for enquiries about the terms of commercial * use of this library. */ #ifndef TRANSFORM_H #define TRANSFORM_H #include "Vector3.h" #include "Matrix3x3.h" namespace MT { template class Transform { enum { TRANSLATION = 0x01, ROTATION = 0x02, RIGID = TRANSLATION | ROTATION, SCALING = 0x04, LINEAR = ROTATION | SCALING, AFFINE = TRANSLATION | LINEAR }; public: Transform() {} template explicit Transform(const Scalar2 *m) { setValue(m); } explicit Transform(const Quaternion& q, const Vector3& c = Vector3(Scalar(0), Scalar(0), Scalar(0))) : m_basis(q), m_origin(c), m_type(RIGID) {} explicit Transform(const Matrix3x3& b, const Vector3& c = Vector3(Scalar(0), Scalar(0), Scalar(0)), unsigned int type = AFFINE) : m_basis(b), m_origin(c), m_type(type) {} Vector3 operator()(const Vector3& x) const { return Vector3(m_basis[0].dot(x) + m_origin[0], m_basis[1].dot(x) + m_origin[1], m_basis[2].dot(x) + m_origin[2]); } Vector3 operator*(const Vector3& x) const { return (*this)(x); } Matrix3x3& getBasis() { return m_basis; } const Matrix3x3& getBasis() const { return m_basis; } Vector3& getOrigin() { return m_origin; } const Vector3& getOrigin() const { return m_origin; } Quaternion getRotation() const { return m_basis.getRotation(); } template void setValue(const Scalar2 *m) { m_basis.setValue(m); m_origin.setValue(&m[12]); m_type = AFFINE; } template void getValue(Scalar2 *m) const { m_basis.getValue(m); m_origin.getValue(&m[12]); m[15] = Scalar2(1.0); } void setOrigin(const Vector3& origin) { m_origin = origin; m_type |= TRANSLATION; } void setBasis(const Matrix3x3& basis) { m_basis = basis; m_type |= LINEAR; } void setRotation(const Quaternion& q) { m_basis.setRotation(q); m_type = (m_type & ~LINEAR) | ROTATION; } void scale(const Vector3& scaling) { m_basis = m_basis.scaled(scaling); m_type |= SCALING; } void setIdentity() { m_basis.setIdentity(); m_origin.setValue(Scalar(0.0), Scalar(0.0), Scalar(0.0)); m_type = 0x0; } bool isIdentity() const { return m_type == 0x0; } Transform& operator*=(const Transform& t) { m_origin += m_basis * t.m_origin; m_basis *= t.m_basis; m_type |= t.m_type; return *this; } Transform inverse() const { Matrix3x3 inv = (m_type & SCALING) ? m_basis.inverse() : m_basis.transpose(); return Transform(inv, inv * -m_origin, m_type); } Transform inverseTimes(const Transform& t) const; Transform operator*(const Transform& t) const; private: Matrix3x3 m_basis; Vector3 m_origin; unsigned int m_type; }; template inline Transform Transform::inverseTimes(const Transform& t) const { Vector3 v = t.getOrigin() - m_origin; if (m_type & SCALING) { Matrix3x3 inv = m_basis.inverse(); return Transform(inv * t.getBasis(), inv * v, m_type | t.m_type); } else { return Transform(m_basis.transposeTimes(t.m_basis), v * m_basis, m_type | t.m_type); } } template inline Transform Transform::operator*(const Transform& t) const { return Transform(m_basis * t.m_basis, (*this)(t.m_origin), m_type | t.m_type); } } #endif