Reverted incorrect merge (missing files)
[blender.git] / extern / solid / include / MT / Transform.h
1 /*
2  * SOLID - Software Library for Interference Detection
3  * 
4  * Copyright (C) 2001-2003  Dtecta.  All rights reserved.
5  *
6  * This library may be distributed under the terms of the Q Public License
7  * (QPL) as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * This library may be distributed and/or modified under the terms of the
11  * GNU General Public License (GPL) version 2 as published by the Free Software
12  * Foundation and appearing in the file LICENSE.GPL included in the
13  * packaging of this file.
14  *
15  * This library is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * Commercial use or any other use of this library not covered by either 
19  * the QPL or the GPL requires an additional license from Dtecta. 
20  * Please contact info@dtecta.com for enquiries about the terms of commercial
21  * use of this library.
22  */
23
24 #ifndef TRANSFORM_H
25 #define TRANSFORM_H
26
27 #include "Vector3.h"
28 #include "Matrix3x3.h"
29
30 namespace MT {
31
32         template <typename Scalar>
33         class Transform {
34                 enum { 
35                         TRANSLATION = 0x01,
36                         ROTATION    = 0x02,
37                         RIGID       = TRANSLATION | ROTATION,  
38                         SCALING     = 0x04,
39                         LINEAR      = ROTATION | SCALING,
40                         AFFINE      = TRANSLATION | LINEAR
41                 };
42     
43         public:
44                 Transform() {}
45                 
46                 template <typename Scalar2>
47                 explicit Transform(const Scalar2 *m) { setValue(m); }
48
49                 explicit Transform(const Quaternion<Scalar>& q, 
50                                                    const Vector3<Scalar>& c = Vector3<Scalar>(Scalar(0), Scalar(0), Scalar(0))) 
51                         : m_basis(q),
52                           m_origin(c),
53                           m_type(RIGID)
54                 {}
55
56                 explicit Transform(const Matrix3x3<Scalar>& b, 
57                                                    const Vector3<Scalar>& c = Vector3<Scalar>(Scalar(0), Scalar(0), Scalar(0)), 
58                                                    unsigned int type = AFFINE)
59                         : m_basis(b),
60                           m_origin(c),
61                           m_type(type)
62                 {}
63
64                 Vector3<Scalar> operator()(const Vector3<Scalar>& x) const
65                 {
66                         return Vector3<Scalar>(m_basis[0].dot(x) + m_origin[0], 
67                                                                    m_basis[1].dot(x) + m_origin[1], 
68                                                                    m_basis[2].dot(x) + m_origin[2]);
69                 }
70     
71                 Vector3<Scalar> operator*(const Vector3<Scalar>& x) const
72                 {
73                         return (*this)(x);
74                 }
75
76                 Matrix3x3<Scalar>&       getBasis()          { return m_basis; }
77                 const Matrix3x3<Scalar>& getBasis()    const { return m_basis; }
78
79                 Vector3<Scalar>&         getOrigin()         { return m_origin; }
80                 const Vector3<Scalar>&   getOrigin()   const { return m_origin; }
81
82                 Quaternion<Scalar> getRotation() const { return m_basis.getRotation(); }
83                 template <typename Scalar2>
84                 void setValue(const Scalar2 *m) 
85                 {
86                         m_basis.setValue(m);
87                         m_origin.setValue(&m[12]);
88                         m_type = AFFINE;
89                 }
90
91                 template <typename Scalar2>
92                 void getValue(Scalar2 *m) const 
93                 {
94                         m_basis.getValue(m);
95                         m_origin.getValue(&m[12]);
96                         m[15] = Scalar2(1.0);
97                 }
98
99                 void setOrigin(const Vector3<Scalar>& origin) 
100                 { 
101                         m_origin = origin;
102                         m_type |= TRANSLATION;
103                 }
104
105                 void setBasis(const Matrix3x3<Scalar>& basis)
106                 { 
107                         m_basis = basis;
108                         m_type |= LINEAR;
109                 }
110
111                 void setRotation(const Quaternion<Scalar>& q)
112                 {
113                         m_basis.setRotation(q);
114                         m_type = (m_type & ~LINEAR) | ROTATION;
115                 }
116
117         void scale(const Vector3<Scalar>& scaling)
118                 {
119                         m_basis = m_basis.scaled(scaling);
120                         m_type |= SCALING;
121                 }
122     
123                 void setIdentity()
124                 {
125                         m_basis.setIdentity();
126                         m_origin.setValue(Scalar(0.0), Scalar(0.0), Scalar(0.0));
127                         m_type = 0x0;
128                 }
129                 
130                 bool isIdentity() const { return m_type == 0x0; }
131     
132                 Transform<Scalar>& operator*=(const Transform<Scalar>& t) 
133                 {
134                         m_origin += m_basis * t.m_origin;
135                         m_basis *= t.m_basis;
136                         m_type |= t.m_type; 
137                         return *this;
138                 }
139
140                 Transform<Scalar> inverse() const
141                 { 
142                         Matrix3x3<Scalar> inv = (m_type & SCALING) ? 
143                                                     m_basis.inverse() : 
144                                                     m_basis.transpose();
145                         
146                         return Transform<Scalar>(inv, inv * -m_origin, m_type);
147                 }
148
149                 Transform<Scalar> inverseTimes(const Transform<Scalar>& t) const;  
150
151                 Transform<Scalar> operator*(const Transform<Scalar>& t) const;
152
153         private:
154                 
155                 Matrix3x3<Scalar> m_basis;
156                 Vector3<Scalar>   m_origin;
157                 unsigned int      m_type;
158         };
159
160
161         template <typename Scalar>
162         inline Transform<Scalar> 
163         Transform<Scalar>::inverseTimes(const Transform<Scalar>& t) const  
164         {
165                 Vector3<Scalar> v = t.getOrigin() - m_origin;
166                 if (m_type & SCALING) 
167                 {
168                         Matrix3x3<Scalar> inv = m_basis.inverse();
169                         return Transform<Scalar>(inv * t.getBasis(), inv * v, 
170                                                                          m_type | t.m_type);
171                 }
172                 else 
173                 {
174                         return Transform<Scalar>(m_basis.transposeTimes(t.m_basis),
175                                                                          v * m_basis, m_type | t.m_type);
176                 }
177         }
178
179         template <typename Scalar>
180         inline Transform<Scalar> 
181         Transform<Scalar>::operator*(const Transform<Scalar>& t) const
182         {
183                 return Transform<Scalar>(m_basis * t.m_basis, 
184                                                                  (*this)(t.m_origin), 
185                                                                  m_type | t.m_type);
186         }       
187 }
188
189 #endif