1 | /** |
---|
2 | @file CoordinateFrame.h |
---|
3 | |
---|
4 | @maintainer Morgan McGuire, matrix@graphics3d.com |
---|
5 | |
---|
6 | @created 2001-03-04 |
---|
7 | @edited 2006-04-07 |
---|
8 | |
---|
9 | Copyright 2000-2006, Morgan McGuire. |
---|
10 | All rights reserved. |
---|
11 | */ |
---|
12 | |
---|
13 | #ifndef G3D_COORDINATEFRAME_H |
---|
14 | #define G3D_COORDINATEFRAME_H |
---|
15 | |
---|
16 | #include "G3D/platform.h" |
---|
17 | #include "G3D/Vector3.h" |
---|
18 | #include "G3D/Vector4.h" |
---|
19 | #include "G3D/Matrix3.h" |
---|
20 | #include "G3D/Array.h" |
---|
21 | #include <math.h> |
---|
22 | #include <string> |
---|
23 | #include <stdio.h> |
---|
24 | #include <cstdarg> |
---|
25 | #include <assert.h> |
---|
26 | |
---|
27 | namespace G3D { |
---|
28 | |
---|
29 | /** |
---|
30 | A rigid body RT (rotation-translation) transformation. |
---|
31 | |
---|
32 | CoordinateFrame abstracts a 4x4 matrix that maps object space to world space: |
---|
33 | |
---|
34 | v_world = C * v_object |
---|
35 | |
---|
36 | CoordinateFrame::rotation is the upper 3x3 submatrix, CoordinateFrame::translation |
---|
37 | is the right 3x1 column. The 4th row is always [0 0 0 1], so it isn't stored. |
---|
38 | So you don't have to remember which way the multiplication and transformation work, |
---|
39 | it provides explicit toWorldSpace and toObjectSpace methods. Also, points, vectors |
---|
40 | (directions), and surface normals transform differently, so they have separate methods. |
---|
41 | |
---|
42 | Some helper functions transform whole primitives like boxes in and out of object space. |
---|
43 | |
---|
44 | Convert to Matrix4 using CoordinateFrame::toMatrix4. You <I>can</I> construct a CoordinateFrame |
---|
45 | from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more |
---|
46 | general than a CoordinateFrame, some information may be lost. |
---|
47 | |
---|
48 | See also: G3D::Matrix4, G3D::Quat |
---|
49 | */ |
---|
50 | class CoordinateFrame { |
---|
51 | public: |
---|
52 | |
---|
53 | /** |
---|
54 | Takes object space points to world space. |
---|
55 | */ |
---|
56 | Matrix3 rotation; |
---|
57 | |
---|
58 | /** |
---|
59 | Takes object space points to world space. |
---|
60 | */ |
---|
61 | Vector3 translation; |
---|
62 | |
---|
63 | /** |
---|
64 | The direction an object "looks" relative to its own axes. |
---|
65 | @deprecated This is always -1 and will be fixed at that value in future releases. |
---|
66 | */ |
---|
67 | static const float zLookDirection; |
---|
68 | |
---|
69 | inline bool operator==(const CoordinateFrame& other) const { |
---|
70 | return (translation == other.translation) && (rotation == other.rotation); |
---|
71 | } |
---|
72 | |
---|
73 | inline bool operator!=(const CoordinateFrame& other) const { |
---|
74 | return !(*this == other); |
---|
75 | } |
---|
76 | |
---|
77 | bool fuzzyEq(const CoordinateFrame& other) const; |
---|
78 | |
---|
79 | bool fuzzyIsIdentity() const; |
---|
80 | |
---|
81 | bool isIdentity() const; |
---|
82 | |
---|
83 | /** |
---|
84 | Initializes to the identity coordinate frame. |
---|
85 | */ |
---|
86 | inline CoordinateFrame() : |
---|
87 | rotation(Matrix3::identity()), translation(Vector3::zero()) { |
---|
88 | } |
---|
89 | |
---|
90 | CoordinateFrame(const Vector3& _translation) : |
---|
91 | rotation(Matrix3::identity()), translation(_translation) { |
---|
92 | } |
---|
93 | |
---|
94 | CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) : |
---|
95 | rotation(rotation), translation(translation) { |
---|
96 | } |
---|
97 | |
---|
98 | CoordinateFrame(const Matrix3 &rotation) : |
---|
99 | rotation(rotation), translation(Vector3::zero()) { |
---|
100 | } |
---|
101 | |
---|
102 | CoordinateFrame(const CoordinateFrame &other) : |
---|
103 | rotation(other.rotation), translation(other.translation) {} |
---|
104 | |
---|
105 | /** |
---|
106 | Computes the inverse of this coordinate frame. |
---|
107 | */ |
---|
108 | inline CoordinateFrame inverse() const { |
---|
109 | CoordinateFrame out; |
---|
110 | out.rotation = rotation.transpose(); |
---|
111 | out.translation = -out.rotation * translation; |
---|
112 | return out; |
---|
113 | } |
---|
114 | |
---|
115 | inline ~CoordinateFrame() {} |
---|
116 | |
---|
117 | /** See also Matrix4::approxCoordinateFrame */ |
---|
118 | class Matrix4 toMatrix4() const; |
---|
119 | |
---|
120 | /** |
---|
121 | Produces an XML serialization of this coordinate frame. |
---|
122 | */ |
---|
123 | std::string toXML() const; |
---|
124 | |
---|
125 | /** |
---|
126 | Returns the heading of the lookVector as an angle in radians relative to |
---|
127 | the world -z axis. That is, a counter-clockwise heading where north (-z) |
---|
128 | is 0 and west (-x) is PI/2. |
---|
129 | |
---|
130 | Note that the heading ignores the Y axis, so an inverted |
---|
131 | object has an inverted heading. |
---|
132 | */ |
---|
133 | inline float getHeading() const { |
---|
134 | Vector3 look = rotation.getColumn(2); |
---|
135 | float angle = -(float) atan2(-look.x, look.z); |
---|
136 | return angle; |
---|
137 | } |
---|
138 | |
---|
139 | /** |
---|
140 | Takes the coordinate frame into object space. |
---|
141 | this->inverse() * c |
---|
142 | */ |
---|
143 | inline CoordinateFrame toObjectSpace(const CoordinateFrame& c) const { |
---|
144 | return this->inverse() * c; |
---|
145 | } |
---|
146 | |
---|
147 | inline Vector4 toObjectSpace(const Vector4& v) const { |
---|
148 | return this->inverse().toWorldSpace(v); |
---|
149 | } |
---|
150 | |
---|
151 | inline Vector4 toWorldSpace(const Vector4& v) const { |
---|
152 | return Vector4(rotation * Vector3(v.x, v.y, v.z) + translation * v.w, v.w); |
---|
153 | } |
---|
154 | |
---|
155 | /** |
---|
156 | Transforms the point into world space. |
---|
157 | */ |
---|
158 | inline Vector3 pointToWorldSpace(const Vector3& v) const { |
---|
159 | return Vector3( |
---|
160 | rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0], |
---|
161 | rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1], |
---|
162 | rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]); |
---|
163 | } |
---|
164 | |
---|
165 | /** |
---|
166 | Transforms the point into object space. |
---|
167 | */ |
---|
168 | inline Vector3 pointToObjectSpace(const Vector3& v) const { |
---|
169 | float p[3]; |
---|
170 | p[0] = v[0] - translation[0]; |
---|
171 | p[1] = v[1] - translation[1]; |
---|
172 | p[2] = v[2] - translation[2]; |
---|
173 | return Vector3( |
---|
174 | rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2], |
---|
175 | rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2], |
---|
176 | rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]); |
---|
177 | } |
---|
178 | |
---|
179 | /** |
---|
180 | Transforms the vector into world space (no translation). |
---|
181 | */ |
---|
182 | inline Vector3 vectorToWorldSpace(const Vector3& v) const { |
---|
183 | return rotation * v; |
---|
184 | } |
---|
185 | |
---|
186 | inline Vector3 normalToWorldSpace(const Vector3& v) const { |
---|
187 | return rotation * v; |
---|
188 | } |
---|
189 | |
---|
190 | class Ray toObjectSpace(const Ray& r) const; |
---|
191 | |
---|
192 | Ray toWorldSpace(const Ray& r) const; |
---|
193 | |
---|
194 | /** |
---|
195 | Transforms the vector into object space (no translation). |
---|
196 | */ |
---|
197 | inline Vector3 vectorToObjectSpace(const Vector3 &v) const { |
---|
198 | // Multiply on the left (same as rotation.transpose() * v) |
---|
199 | return v * rotation; |
---|
200 | } |
---|
201 | |
---|
202 | inline Vector3 normalToObjectSpace(const Vector3 &v) const { |
---|
203 | // Multiply on the left (same as rotation.transpose() * v) |
---|
204 | return v * rotation; |
---|
205 | } |
---|
206 | |
---|
207 | void pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const; |
---|
208 | |
---|
209 | void normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const; |
---|
210 | |
---|
211 | void vectorToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const; |
---|
212 | |
---|
213 | void pointToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const; |
---|
214 | |
---|
215 | void normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const; |
---|
216 | |
---|
217 | void vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const; |
---|
218 | |
---|
219 | class Box toWorldSpace(const class AABox& b) const; |
---|
220 | |
---|
221 | class Box toWorldSpace(const class Box& b) const; |
---|
222 | |
---|
223 | class Cylinder toWorldSpace(const class Cylinder& b) const; |
---|
224 | |
---|
225 | class Capsule toWorldSpace(const class Capsule& b) const; |
---|
226 | |
---|
227 | class Plane toWorldSpace(const class Plane& p) const; |
---|
228 | |
---|
229 | class Sphere toWorldSpace(const class Sphere& b) const; |
---|
230 | |
---|
231 | class Triangle toWorldSpace(const class Triangle& t) const; |
---|
232 | |
---|
233 | class Box toObjectSpace(const AABox& b) const; |
---|
234 | |
---|
235 | class Box toObjectSpace(const Box& b) const; |
---|
236 | |
---|
237 | class Plane toObjectSpace(const Plane& p) const; |
---|
238 | |
---|
239 | class Sphere toObjectSpace(const Sphere& b) const; |
---|
240 | |
---|
241 | Triangle toObjectSpace(const Triangle& t) const; |
---|
242 | |
---|
243 | /** Compose: create the transformation that is <I>other</I> followed by <I>this</I>.*/ |
---|
244 | CoordinateFrame operator*(const CoordinateFrame &other) const { |
---|
245 | return CoordinateFrame(rotation * other.rotation, |
---|
246 | pointToWorldSpace(other.translation)); |
---|
247 | } |
---|
248 | |
---|
249 | CoordinateFrame operator+(const Vector3& v) const { |
---|
250 | return CoordinateFrame(rotation, translation + v); |
---|
251 | } |
---|
252 | |
---|
253 | CoordinateFrame operator-(const Vector3& v) const { |
---|
254 | return CoordinateFrame(rotation, translation - v); |
---|
255 | } |
---|
256 | |
---|
257 | void lookAt(const Vector3& target); |
---|
258 | |
---|
259 | void lookAt( |
---|
260 | const Vector3& target, |
---|
261 | Vector3 up); |
---|
262 | |
---|
263 | /** @deprecated See lookVector */ |
---|
264 | inline Vector3 getLookVector() const { |
---|
265 | return rotation.getColumn(2) * zLookDirection; |
---|
266 | } |
---|
267 | |
---|
268 | /** The direction this camera is looking (its negative z axis)*/ |
---|
269 | inline Vector3 lookVector() const { |
---|
270 | return rotation.getColumn(2) * zLookDirection; |
---|
271 | } |
---|
272 | |
---|
273 | /** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */ |
---|
274 | class Ray lookRay() const; |
---|
275 | |
---|
276 | /** Up direction for this camera (its y axis). */ |
---|
277 | inline Vector3 upVector() const { |
---|
278 | return rotation.getColumn(1); |
---|
279 | } |
---|
280 | |
---|
281 | /** |
---|
282 | If a viewer looks along the look vector, this is the viewer's "left" |
---|
283 | @deprecated leftVector |
---|
284 | */ |
---|
285 | inline Vector3 getLeftVector() const { |
---|
286 | return -rotation.getColumn(0); |
---|
287 | } |
---|
288 | |
---|
289 | /** @deprecated See rightVector */ |
---|
290 | inline Vector3 getRightVector() const { |
---|
291 | return rotation.getColumn(0); |
---|
292 | } |
---|
293 | |
---|
294 | /** |
---|
295 | If a viewer looks along the look vector, this is the viewer's "left". |
---|
296 | Useful for strafing motions and building alternative coordinate frames. |
---|
297 | */ |
---|
298 | inline Vector3 leftVector() const { |
---|
299 | return -rotation.getColumn(0); |
---|
300 | } |
---|
301 | |
---|
302 | inline Vector3 rightVector() const { |
---|
303 | return rotation.getColumn(0); |
---|
304 | } |
---|
305 | |
---|
306 | /** |
---|
307 | Linearly interpolates between two coordinate frames, using |
---|
308 | Quat::slerp for the rotations. |
---|
309 | */ |
---|
310 | CoordinateFrame lerp( |
---|
311 | const CoordinateFrame& other, |
---|
312 | float alpha) const; |
---|
313 | |
---|
314 | }; |
---|
315 | |
---|
316 | } // namespace |
---|
317 | |
---|
318 | #endif |
---|