00001
00014 #ifndef _TRANSFORM_H
00015 #define _TRANSFORM_H
00016
00017
00018 #include <Matrix.H>
00019
00020
00021 namespace xchen
00022 {
00024 class Transform {
00025 enum { TRANSFORM_POINT, TRANSFORM_VECTOR, INV_TRANSFORM_POINT, INV_TRANSFORM_VECTOR, TRANSFORM_NORMAL };
00026 public:
00027 Transform();
00028
00029 void SetIdentity() { M.SetIdentity(); validCache() = false; }
00030
00031 void ShearXY(double a, double b);
00032 void ShearXZ(double a, double b);
00033 void ShearYZ(double a, double b);
00034
00035 void Translate(double x, double y, double z);
00036 void Translate(const dVector3D& v) { Translate(v[0], v[1], v[2]); }
00037 void TranslateX(double x) { Translate(x, 0, 0); }
00038 void TranslateY(double y) { Translate(0, y, 0); }
00039 void TranslateZ(double z) { Translate(0, 0, z); }
00040
00041 void Rotate(double dx, double dy, double dz, double angle);
00042 void RotateX(double x);
00043 void RotateY(double y);
00044 void RotateZ(double z);
00045
00046 void Rotate2Frame(const class Frame&);
00047
00048 void Scale(double sx, double sy, double sz);
00049 void ScaleX(double x) { Scale(x, 1, 1); }
00050 void ScaleY(double y) { Scale(1, y, 1); }
00051 void ScaleZ(double z) { Scale(1, 1, z); }
00052
00053 void Rotate(const dVector3D& v, double angle) { Rotate(v[0], v[1], v[2], angle); }
00054 void Scale(const dVector3D& v) { Scale(v[0], v[1], v[2]); }
00055
00056 void RotateTo(const dVector3D& from, const dVector3D& to) { Rotate(from^to, from.Angle(to)); }
00057
00058 void GetGLMatrix(double* m) const { M.GetColumnMajorData(m); }
00059 double* GetGLMatrix() const { double *m = new double[16]; GetGLMatrix(m); return m; }
00060 const HMatrix& GetMatrix() const { return M; }
00061
00062 double GetMeasureScale() const { return measure_scale; }
00063
00064 dVector4D operator()(dVector4D const& p) const { return M * p; }
00065 dVector4D operator*(dVector4D const& p) const { return M * p; }
00066
00067
00068
00069 void TransformPoint(dVector3D& p) const { transform(p, TRANSFORM_POINT); }
00070 void TransformVector(dVector3D& v) const { transform(v, TRANSFORM_VECTOR); }
00071 void TransformNormal(dVector3D& n) const { transform(n, TRANSFORM_NORMAL); }
00072
00073 void InvTransformPoint(dVector3D& p) const { transform(p, INV_TRANSFORM_POINT); }
00074 void InvTransformVector(dVector3D& v) const { transform(v, INV_TRANSFORM_VECTOR); }
00075
00076 friend ostream& operator << (ostream& os, const Transform& trans);
00077
00078 private:
00079 void transform(dVector3D& p, int trans) const;
00080
00081 HMatrix M, invM, itM;
00082 bool valid_cache;
00083 bool& validCache() const { return (bool&) valid_cache; }
00084
00085 double measure_scale;
00086
00087 HMatrix m;
00088 };
00089
00090
00091
00092 inline void Transform :: transform(dVector3D& p, int trans) const
00093 {
00094 dVector4D p2(p);
00095
00096 if(trans == TRANSFORM_POINT || trans == INV_TRANSFORM_POINT)
00097 p2[3] = 1.0;
00098
00099 const HMatrix* m = &M;
00100
00101 if( (trans == TRANSFORM_NORMAL || trans == INV_TRANSFORM_POINT || trans == INV_TRANSFORM_VECTOR) &&
00102 (! validCache() ) )
00103 {
00104 Transform* This = (Transform*) this;
00105 M.GetInverse(&This->invM);
00106 M.GetTranspose(&This->itM);
00107 This->validCache() = true;
00108 }
00109
00110 if(trans == TRANSFORM_NORMAL)
00111 m = &itM;
00112 else if(trans == INV_TRANSFORM_POINT || trans == INV_TRANSFORM_VECTOR)
00113 m = &invM;
00114
00115 dVector4D p3 = (*m) * p2;
00116 assert( approx_eq(p3[3], p2[3]) );
00117
00118 p = dVector3D(p3);
00119 }
00120
00121 inline Transform :: Transform() : valid_cache(false), measure_scale(1.0)
00122 {
00123 M.SetIdentity();
00124 }
00125
00126
00127
00128
00129
00130 inline Transform scale(double s)
00131 {
00132 Transform tr; tr.Scale(s,s,s); return tr;
00133 }
00134
00135 inline Transform rotateX(double ang)
00136 {
00137 Transform tr; tr.RotateX(ang); return tr;
00138 }
00139
00140 inline Transform rotateY(double ang)
00141 {
00142 Transform tr; tr.RotateY(ang); return tr;
00143 }
00144
00145 inline Transform rotateZ(double ang)
00146 {
00147 Transform tr; tr.RotateZ(ang); return tr;
00148 }
00149
00150 inline Transform tX(double d)
00151 {
00152 Transform tr; tr.TranslateX(d); return tr;
00153 }
00154 inline Transform tY(double d)
00155 {
00156 Transform tr; tr.TranslateY(d); return tr;
00157 }
00158 inline Transform tZ(double d)
00159 {
00160 Transform tr; tr.TranslateZ(d); return tr;
00161 }
00162
00163
00164 #define sc scale
00165 #define rX rotateX
00166 #define rY rotateY
00167 #define rZ rotateZ
00168
00169
00170 }
00171
00172
00173 #endif