remove RSA's md4.c, replace by DP's
[xonotic/netradiant.git] / libs / transformlib.h
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #if !defined (INCLUDED_TRANSFORMLIB_H)
23 #define INCLUDED_TRANSFORMLIB_H
24
25 #include "generic/constant.h"
26 #include "math/matrix.h"
27 #include "math/quaternion.h"
28
29
30 /// \brief A transform node.
31 class TransformNode
32 {
33 public:
34   STRING_CONSTANT(Name, "TransformNode");
35   /// \brief Returns the transform which maps the node's local-space into the local-space of its parent node.
36   virtual const Matrix4& localToParent() const  = 0;
37 };
38
39 /// \brief A transform node which has no effect.
40 class IdentityTransform : public TransformNode
41 {
42 public:
43   /// \brief Returns the identity matrix.
44   const Matrix4& localToParent() const
45   {
46     return g_matrix4_identity;
47   }
48 };
49
50 /// \brief A transform node which stores a generic transformation matrix.
51 class MatrixTransform : public TransformNode
52 {
53   Matrix4 m_localToParent;
54 public:
55   MatrixTransform() : m_localToParent(g_matrix4_identity)
56   {
57   }
58
59   Matrix4& localToParent()
60   {
61     return m_localToParent;
62   }
63   /// \brief Returns the stored local->parent transform.
64   const Matrix4& localToParent() const
65   {
66     return m_localToParent;
67   }
68 };
69
70
71 #include "generic/callback.h"
72
73 typedef Vector3 Translation;
74 typedef Quaternion Rotation;
75 typedef Vector3 Scale;
76
77 inline Matrix4 matrix4_transform_for_components(const Translation& translation, const Rotation& rotation, const Scale& scale)
78 {
79   Matrix4 result(matrix4_rotation_for_quaternion_quantised(rotation));
80   vector4_to_vector3(result.x()) *= scale.x();
81   vector4_to_vector3(result.y()) *= scale.y();
82   vector4_to_vector3(result.z()) *= scale.z();
83   result.tx() = translation.x();
84   result.ty() = translation.y();
85   result.tz() = translation.z();
86   return result;
87 }
88
89 typedef bool TransformModifierType;
90 const TransformModifierType TRANSFORM_PRIMITIVE = false;
91 const TransformModifierType TRANSFORM_COMPONENT = true;
92
93 /// \brief A transformable scene-graph instance.
94 ///
95 /// A transformable instance may be translated, rotated or scaled.
96 /// The state of the instanced node's geometrical representation
97 /// will be the product of its geometry and the transforms of each
98 /// of its instances, applied in the order they appear in a graph
99 /// traversal.
100 /// Freezing the transform on an instance will cause its transform
101 /// to be permanently applied to the geometry of the node.
102 class Transformable
103 {
104 public:
105   STRING_CONSTANT(Name, "Transformable");
106
107   virtual void setType(TransformModifierType type) = 0;
108   virtual void setTranslation(const Translation& value) = 0;
109   virtual void setRotation(const Rotation& value) = 0;
110   virtual void setScale(const Scale& value) = 0;
111   virtual void freezeTransform() = 0;
112 };
113
114 const Translation c_translation_identity = Translation(0, 0, 0);
115 const Rotation c_rotation_identity = c_quaternion_identity;
116 const Scale c_scale_identity = Scale(1, 1, 1);
117
118
119 class TransformModifier : public Transformable
120 {
121   Translation m_translation;
122   Rotation m_rotation;
123   Scale m_scale;
124   Callback m_changed;
125   Callback m_apply;
126   TransformModifierType m_type;
127 public:
128
129   TransformModifier(const Callback& changed, const Callback& apply) :
130     m_translation(c_translation_identity),
131     m_rotation(c_quaternion_identity),
132     m_scale(c_scale_identity),
133     m_changed(changed),
134     m_apply(apply),
135     m_type(TRANSFORM_PRIMITIVE)
136   {
137   }
138   void setType(TransformModifierType type)
139   {
140     m_type = type;
141   }
142   TransformModifierType getType() const
143   {
144     return m_type;
145   }
146   void setTranslation(const Translation& value)
147   {
148     m_translation = value;
149     m_changed();
150   }
151   void setRotation(const Rotation& value)
152   {
153     m_rotation = value;
154     m_changed();
155   }
156   void setScale(const Scale& value)
157   {
158     m_scale = value;
159     m_changed();
160   }
161   void freezeTransform()
162   {
163     if(m_translation != c_translation_identity
164       || m_rotation != c_rotation_identity
165       || m_scale != c_scale_identity)
166     {
167       m_apply();
168       m_translation = c_translation_identity;
169       m_rotation = c_rotation_identity;
170       m_scale = c_scale_identity;
171       m_changed();
172     }
173   }
174   const Translation& getTranslation() const
175   {
176     return m_translation;
177   }
178   const Rotation& getRotation() const
179   {
180     return m_rotation;
181   }
182   const Scale& getScale() const
183   {
184     return m_scale;
185   }
186   Matrix4 calculateTransform() const
187   {
188     return matrix4_transform_for_components(getTranslation(), getRotation(), getScale());
189   }
190 };
191
192
193 #endif