00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_XRB_TRANSFORM2_HPP_)
00012 #define _XRB_TRANSFORM2_HPP_
00013
00014 #include "xrb.hpp"
00015
00016 #include "xrb_matrix2.hpp"
00017 #include "xrb_simpletransform2.hpp"
00018 #include "xrb_vector.hpp"
00019
00020 namespace Xrb
00021 {
00022
00023 template <typename T>
00024 class Transform2
00025 {
00026 public:
00027
00028 static Transform2<T> const ms_identity;
00029
00030
00031
00032
00033
00034 inline Transform2 (bool post_translate)
00035 {
00036 m_post_translate = post_translate;
00037 Dirtify();
00038 }
00039 inline Transform2 (
00040 Vector<T, 2> const &translation,
00041 Vector<T, 2> const &scale_factors,
00042 T angle,
00043 bool post_translate)
00044 {
00045 m_translation = translation;
00046 m_scale_factors = scale_factors;
00047 m_angle = angle;
00048 m_post_translate = post_translate;
00049 Dirtify();
00050 }
00051 inline Transform2 (
00052 SimpleTransform2<T> const &source,
00053 bool post_translate)
00054 {
00055 m_translation = source.m_translation;
00056 m_scale_factors = source.m_scale_factors;
00057 m_angle = static_cast<T>(0);
00058 m_post_translate = post_translate;
00059 Dirtify();
00060 }
00061 inline Transform2 (Transform2<T> const &source)
00062 {
00063 m_translation = source.m_translation;
00064 m_scale_factors = source.m_scale_factors;
00065 m_angle = source.m_angle;
00066 m_post_translate = source.m_post_translate;
00067 Dirtify();
00068 }
00069 inline Transform2 (
00070 Transform2<T> const &source,
00071 bool post_translate)
00072 {
00073 m_translation = source.m_translation;
00074 m_scale_factors = source.m_scale_factors;
00075 m_angle = source.m_angle;
00076 m_post_translate = post_translate;
00077 Dirtify();
00078 }
00079 inline ~Transform2 () { }
00080
00081
00082
00083
00084
00085 inline void operator = (Transform2<T> const &source)
00086 {
00087 m_translation = source.m_translation;
00088 m_scale_factors = source.m_scale_factors;
00089 m_angle = source.m_angle;
00090
00091 Dirtify();
00092 }
00093
00094
00095
00096
00097
00098 inline Vector<T, 2> const &Translation () const
00099 {
00100 return m_translation;
00101 }
00102 inline Vector<T, 2> const &ScaleFactors () const
00103 {
00104 return m_scale_factors;
00105 }
00106 inline T ScaleFactor () const
00107 {
00108 ASSERT1(m_scale_factors[Dim::X] == m_scale_factors[Dim::Y]);
00109 return m_scale_factors[Dim::X];
00110 }
00111 inline T Angle () const
00112 {
00113 return m_angle;
00114 }
00115 inline bool PostTranslate () const
00116 {
00117 return m_post_translate;
00118 }
00119
00120 inline Matrix2<T> const &Transformation () const
00121 {
00122 RecalculateTransformIfNecessary();
00123 ASSERT1(!m_cached_transform_is_dirty);
00124 return m_cached_transform;
00125 }
00126 inline Matrix2<T> TransformationInverse () const
00127 {
00128 RecalculateTransformIfNecessary();
00129 ASSERT1(!m_cached_transform_is_dirty);
00130 return m_cached_transform.Inverse();
00131 }
00132
00133 inline T Determinant () const
00134 {
00135 RecalculateScalingAndRotationIfNecessary();
00136 return m_cached_scaling_and_rotation.Determinant();
00137 }
00138
00139 inline bool IsDirty () const
00140 {
00141 return m_cached_transform_is_dirty;
00142 }
00143 inline bool ScalingAndRotationIsDirty () const
00144 {
00145 return m_cached_scaling_and_rotation_is_dirty;
00146 }
00147
00148
00149
00150
00151
00152 inline void SetTranslation (Vector<T, 2> const &translation)
00153 {
00154 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(translation[Dim::X]));
00155 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(translation[Dim::Y]));
00156 m_translation = translation;
00157 m_cached_transform_is_dirty = true;
00158 }
00159 inline void SetScaleFactors (Vector<T, 2> const &scale_factors)
00160 {
00161 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(scale_factors[Dim::X]));
00162 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(scale_factors[Dim::Y]));
00163 m_scale_factors = scale_factors;
00164 Dirtify();
00165 }
00166 inline void SetScaleFactor (T scale_factor)
00167 {
00168 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(scale_factor));
00169 m_scale_factors.FillWith(scale_factor);
00170 Dirtify();
00171 }
00172 inline void SetAngle (T angle)
00173 {
00174 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(angle));
00175 m_angle = angle;
00176 Dirtify();
00177 }
00178 inline void SetPostTranslate (bool post_translate)
00179 {
00180 m_post_translate = post_translate;
00181 Dirtify();
00182 }
00183
00184 inline void Translate (Vector<T, 2> const &translation)
00185 {
00186 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(translation[Dim::X]));
00187 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(translation[Dim::Y]));
00188 m_translation += translation;
00189 m_cached_transform_is_dirty = true;
00190 }
00191 inline void Scale (Vector<T, 2> const &scale_factors)
00192 {
00193 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(scale_factors[Dim::X]));
00194 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(scale_factors[Dim::Y]));
00195 m_scale_factors *= scale_factors;
00196 Dirtify();
00197 }
00198 inline void Scale (T scale_factor)
00199 {
00200 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(scale_factor));
00201 m_scale_factors *= scale_factor;
00202 Dirtify();
00203 }
00204 inline void Rotate (T angle)
00205 {
00206 ASSERT_NAN_SANITY_CHECK(Math::IsFinite(angle));
00207 m_angle += angle;
00208 Dirtify();
00209 }
00210
00211 inline void ResetTranslation ()
00212 {
00213 m_translation = Vector<T, 2>::ms_zero;
00214 m_cached_transform_is_dirty = true;
00215 }
00216 inline void ResetScale ()
00217 {
00218 m_scale_factors.FillWith(static_cast<T>(1));
00219 Dirtify();
00220 }
00221 inline void ResetAngle ()
00222 {
00223 m_angle = static_cast<T>(0);
00224 Dirtify();
00225 }
00226
00227
00228
00229
00230
00231 inline void Dirtify () const
00232 {
00233 m_cached_scaling_and_rotation_is_dirty = true;
00234 m_cached_transform_is_dirty = true;
00235 }
00236
00237 void Fprint (
00238 FILE *fptr,
00239 char const *component_printf_format,
00240 bool add_newline = true) const
00241 {
00242 ASSERT1(fptr != NULL);
00243 ASSERT1(component_printf_format != NULL);
00244
00245 if (m_post_translate)
00246 {
00247 fprintf(fptr, "Transform2: scale factors (");
00248 fprintf(fptr, component_printf_format, m_scale_factors[Dim::X]);
00249 fprintf(fptr, ", ");
00250 fprintf(fptr, component_printf_format, m_scale_factors[Dim::Y]);
00251 fprintf(fptr, "), angle (");
00252 fprintf(fptr, component_printf_format, m_angle);
00253 fprintf(fptr, "), translation (");
00254 fprintf(fptr, component_printf_format, m_translation[Dim::X]);
00255 fprintf(fptr, ", ");
00256 fprintf(fptr, component_printf_format, m_translation[Dim::Y]);
00257 fprintf(fptr, "), %c", add_newline ? '\n' : '\0');
00258 }
00259 else
00260 {
00261 fprintf(fptr, "Transform2: translation (");
00262 fprintf(fptr, component_printf_format, m_translation[Dim::X]);
00263 fprintf(fptr, ", ");
00264 fprintf(fptr, component_printf_format, m_translation[Dim::Y]);
00265 fprintf(fptr, "), scale factors (");
00266 fprintf(fptr, component_printf_format, m_scale_factors[Dim::X]);
00267 fprintf(fptr, ", ");
00268 fprintf(fptr, component_printf_format, m_scale_factors[Dim::Y]);
00269 fprintf(fptr, "), angle (");
00270 fprintf(fptr, component_printf_format, m_angle);
00271 fprintf(fptr, ")%c", add_newline ? '\n' : '\0');
00272 }
00273 }
00274
00275 inline void RecalculateTransformIfNecessary () const
00276 {
00277 if (m_cached_transform_is_dirty)
00278 {
00279 if (m_cached_scaling_and_rotation_is_dirty)
00280 RecalculateScalingAndRotation();
00281 ASSERT1(!m_cached_scaling_and_rotation_is_dirty);
00282
00283 if (m_post_translate)
00284 {
00285 m_cached_transform = m_cached_scaling_and_rotation;
00286 m_cached_transform.Translate(m_translation);
00287 }
00288 else
00289 {
00290 m_cached_transform = Matrix2<T>::ms_identity;
00291 m_cached_transform.Translate(m_translation);
00292 m_cached_transform *= m_cached_scaling_and_rotation;
00293 }
00294
00295 m_cached_transform_is_dirty = false;
00296 }
00297 }
00298 inline void RecalculateTransform () const
00299 {
00300 ASSERT1(m_cached_transform_is_dirty);
00301 if (m_cached_scaling_and_rotation_is_dirty)
00302 RecalculateScalingAndRotation();
00303 ASSERT1(!m_cached_scaling_and_rotation_is_dirty);
00304
00305 if (m_post_translate)
00306 {
00307 m_cached_transform = m_cached_scaling_and_rotation;
00308 m_cached_transform.Translate(m_translation);
00309 }
00310 else
00311 {
00312 m_cached_transform = Matrix2<T>::ms_identity;
00313 m_cached_transform.Translate(m_translation);
00314 m_cached_transform *= m_cached_scaling_and_rotation;
00315 }
00316
00317 m_cached_transform_is_dirty = false;
00318 }
00319 inline void RecalculateTransformWithoutScalingAndRotation () const
00320 {
00321 ASSERT1(m_cached_transform_is_dirty);
00322 ASSERT1(!m_cached_scaling_and_rotation_is_dirty);
00323
00324 if (m_post_translate)
00325 {
00326 m_cached_transform = m_cached_scaling_and_rotation;
00327 m_cached_transform.Translate(m_translation);
00328 }
00329 else
00330 {
00331 m_cached_transform = Matrix2<T>::ms_identity;
00332 m_cached_transform.Translate(m_translation);
00333 m_cached_transform *= m_cached_scaling_and_rotation;
00334 }
00335
00336 m_cached_transform_is_dirty = false;
00337 }
00338
00339 private:
00340
00341 void RecalculateScalingAndRotationIfNecessary () const
00342 {
00343 if (m_cached_scaling_and_rotation_is_dirty)
00344 {
00345
00346 m_cached_scaling_and_rotation = Matrix2<T>::ms_identity;
00347 m_cached_scaling_and_rotation.Scale(m_scale_factors);
00348 m_cached_scaling_and_rotation.Rotate(m_angle);
00349
00350 m_cached_scaling_and_rotation_is_dirty = false;
00351 }
00352 }
00353 void RecalculateScalingAndRotation () const
00354 {
00355 ASSERT1(m_cached_scaling_and_rotation_is_dirty);
00356
00357
00358 m_cached_scaling_and_rotation = Matrix2<T>::ms_identity;
00359 m_cached_scaling_and_rotation.Scale(m_scale_factors);
00360 m_cached_scaling_and_rotation.Rotate(m_angle);
00361
00362 m_cached_scaling_and_rotation_is_dirty = false;
00363 }
00364
00365 Vector<T, 2> m_translation;
00366 Vector<T, 2> m_scale_factors;
00367
00368 T m_angle;
00369 bool m_post_translate;
00370
00371 mutable Matrix2<T> m_cached_transform;
00372 mutable bool m_cached_transform_is_dirty;
00373
00374 mutable Matrix2<T> m_cached_scaling_and_rotation;
00375 mutable bool m_cached_scaling_and_rotation_is_dirty;
00376 };
00377
00383 template <typename T>
00384 Transform2<T> const Transform2<T>::ms_identity(
00385 Vector<T, 2>(static_cast<T>(0), static_cast<T>(0)),
00386 Vector<T, 2>(static_cast<T>(1), static_cast<T>(1)),
00387 static_cast<T>(0),
00388 true);
00389
00390
00391
00392
00393
00394
00395
00399 typedef Transform2<Float> FloatTransform2;
00400
00407 void Fprint (FILE *fptr, FloatTransform2 const &transform, bool add_newline = true);
00408
00409 }
00410
00411 #endif // !defined(_XRB_TRANSFORM2_HPP_)
00412