00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <base/Transform>
00026
00027 using base::Transform;
00028 using base::Matrix4;
00029 using base::Vector3;
00030 using base::Point3;
00031 using base::Quat4;
00032
00033
00034
00035 Transform::Transform(const Vector3& translation)
00036 : isIdentity(translation==Vector3(0,0,0)), isPureTranslationRotation(true),
00037 hasTranslation(translation!=Vector3(0,0,0)), hasRotation(false),
00038 trans(translation) {}
00039
00040 Transform::Transform(const Orient& rotation)
00041 : isIdentity(rotation.equals(Quat4())), isPureTranslationRotation(true),
00042 hasTranslation(false), hasRotation(!rotation.equals(Quat4())),
00043 orient(rotation) {}
00044
00045 Transform::Transform(const Quat4& rotation)
00046 : isIdentity(rotation.equals(Quat4())), isPureTranslationRotation(true),
00047 hasTranslation(false), hasRotation(!rotation.equals(Quat4())),
00048 orient(rotation) {}
00049
00050 Transform::Transform(const Matrix3& rotation)
00051 : isIdentity(false), isPureTranslationRotation(false),
00052 hasTranslation(false), hasRotation(true),
00053 t(rotation) {}
00054
00055 Transform::Transform(const Vector3& translation, const Orient& rotation)
00056 : isIdentity(false), isPureTranslationRotation(true),
00057 hasTranslation(translation!=Vector3(0,0,0)), hasRotation(!rotation.equals(Quat4())),
00058 orient(rotation), trans(translation) {}
00059
00060 Transform::Transform(const Vector3& translation, const Quat4& rotation)
00061 : isIdentity(false), isPureTranslationRotation(true),
00062 hasTranslation(translation!=Vector3(0,0,0)), hasRotation(!rotation.equals(Quat4())),
00063 orient(rotation), trans(translation) {}
00064
00065 Transform::Transform(const Vector3& translation, const Matrix3& rotation)
00066 : isIdentity(false), isPureTranslationRotation(false),
00067 hasTranslation(true), hasRotation(true),
00068 t(rotation)
00069 {
00070 t.setTranslationComponent(translation);
00071 }
00072
00073 Transform::Transform(const Matrix4& t)
00074 : isIdentity(false), isPureTranslationRotation(false), t(t) {}
00075
00076 Transform::Transform(const Transform& tr)
00077 : isIdentity(tr.isIdentity), isPureTranslationRotation(tr.isPureTranslationRotation),
00078 hasTranslation(tr.hasTranslation), hasRotation(tr.hasRotation),
00079 orient(tr.orient), trans(tr.trans), t(tr.t) {}
00080
00081
00082 Transform& Transform::operator=(const Transform& t)
00083 {
00084 isIdentity=t.isIdentity;
00085 isPureTranslationRotation=t.isPureTranslationRotation;
00086 hasTranslation = t.hasTranslation;
00087 hasRotation = t.hasRotation;
00088
00089 if (!isIdentity) {
00090 if (!isPureTranslationRotation)
00091 this->t=t.t;
00092 else {
00093 orient = t.orient;
00094 trans = t.trans;
00095 }
00096 }
00097 return *this;
00098 }
00099
00100
00101 bool Transform::operator==(const Transform& rhs) const
00102 {
00103 if (isIdentity && rhs.isIdentity) return true;
00104
00105 if (isPureTranslationRotation) {
00106 if (hasTranslation) {
00107 if (hasRotation) {
00108 return (orient == rhs.orient) && (trans == rhs.trans);
00109 }
00110 return (trans == rhs.trans);
00111 }
00112 return (orient == rhs.orient);
00113 }
00114 return t == rhs.t;
00115 }
00116
00117
00118 bool Transform::equals(const Transform& rhs, Real epsilon) const throw()
00119 {
00120 if (isIdentity && rhs.isIdentity) return true;
00121
00122 if (isPureTranslationRotation) {
00123 if (hasTranslation) {
00124 if (hasRotation) {
00125 return (orient.equals(rhs.orient,epsilon)) && (trans.equals(rhs.trans,epsilon));
00126 }
00127 return (trans.equals(rhs.trans,epsilon));
00128 }
00129 return (orient.equals(rhs.orient,epsilon));
00130 }
00131 return t.equals(rhs.t,epsilon);
00132 }
00133
00134
00135
00136
00137 Matrix4 Transform::getTransform() const
00138 {
00139 if (isIdentity)
00140 return Matrix4();
00141
00142 if (isPureTranslationRotation) {
00143 Matrix4 tm;
00144 if (hasRotation)
00145 tm = orient.getQuat4();
00146 if (hasTranslation)
00147 tm.setTranslationComponent(trans);
00148 return tm;
00149 }
00150 else
00151 return t;
00152 }
00153
00154
00155 void Transform::setToRotation(const Vector3& axis, Real angle)
00156 {
00157 isIdentity = false;
00158 isPureTranslationRotation = true;
00159 hasTranslation=false;
00160 hasRotation=true;
00161 Quat4 q;
00162 q.setRotation(axis,angle);
00163 orient = q;
00164 }
00165
00166
00167 void Transform::setToRotation(const Quat4& orient)
00168 {
00169 isIdentity = false;
00170 isPureTranslationRotation = true;
00171 hasTranslation=false;
00172 hasRotation=true;
00173 this->orient=orient;
00174 }
00175
00176 void Transform::setToTranslation(const Vector3& trans)
00177 {
00178 isIdentity = false;
00179 isPureTranslationRotation = true;
00180 hasTranslation=true;
00181 hasRotation=false;
00182 this->trans=trans;
00183 }
00184
00185
00186 void Transform::setRotationComponent(const Vector3& axis, Real angle)
00187 {
00188 if (isIdentity || isPureTranslationRotation) {
00189 hasRotation=true;
00190 Quat4 q;
00191 q.setRotation(axis,angle);
00192 orient = q;
00193 if (isIdentity)
00194 hasTranslation=isIdentity=false;
00195 }
00196 else {
00197 Matrix4 r(Quat4(axis,angle));
00198 r.e(4,4)=0;
00199 Matrix4 sm(t);
00200 sm.e(1,1)=sm.e(1,2)=sm.e(1,3)=sm.e(2,1)=sm.e(2,2)=sm.e(2,3)=sm.e(3,1)=sm.e(3,2)=sm.e(3,3)=0;
00201 sm+=r;
00202 t=sm;
00203 }
00204 }
00205
00206
00207 void Transform::setRotationComponent(const Quat4& orient)
00208 {
00209 if (isIdentity || isPureTranslationRotation) {
00210 hasRotation=true;
00211 this->orient=orient;
00212 if (isIdentity)
00213 hasTranslation=isIdentity=false;
00214 }
00215 else {
00216 Matrix4 r(orient);
00217 r.e(4,4)=0;
00218 Matrix4 sm(t);
00219 sm.e(1,1)=sm.e(1,2)=sm.e(1,3)=sm.e(2,1)=sm.e(2,2)=sm.e(2,3)=sm.e(3,1)=sm.e(3,2)=sm.e(3,3)=0;
00220 sm+=r;
00221 t=sm;
00222 }
00223 }
00224
00225
00226 void Transform::setRotationComponent(const Orient& orient)
00227 {
00228 if (isIdentity || isPureTranslationRotation) {
00229 hasRotation=true;
00230 this->orient=orient;
00231 if (isIdentity)
00232 hasTranslation=isIdentity=false;
00233 }
00234 else {
00235 Matrix4 r(orient);
00236 r.e(4,4)=0;
00237 Matrix4 sm(t);
00238 sm.e(1,1)=sm.e(1,2)=sm.e(1,3)=sm.e(2,1)=sm.e(2,2)=sm.e(2,3)=sm.e(3,1)=sm.e(3,2)=sm.e(3,3)=0;
00239 sm+=r;
00240 t=sm;
00241 }
00242 }
00243
00244
00245 void Transform::setRotationComponent(const Matrix3& rotation)
00246 {
00247 if (isIdentity || isPureTranslationRotation) {
00248 hasRotation=true;
00249 this->orient = rotation;
00250 if (isIdentity)
00251 hasTranslation=isIdentity=false;
00252 }
00253 else {
00254 const Matrix3& R(rotation);
00255 t(1,1)=R(1,1); t(1,2)=R(1,2); t(1,3)=R(1,3);
00256 t(2,1)=R(2,1); t(2,2)=R(2,2); t(2,3)=R(2,3);
00257 t(3,1)=R(3,1); t(3,2)=R(3,2); t(3,3)=R(3,3);
00258 }
00259 }
00260
00261
00262 void Transform::setTranslationComponent(const Vector3& trans)
00263 {
00264 if (isIdentity || isPureTranslationRotation) {
00265 hasTranslation=true;
00266 this->trans=trans;
00267 if (isIdentity)
00268 hasRotation=isIdentity=false;
00269 }
00270 else {
00271 t.setTranslationComponent(trans);
00272 }
00273 }
00274
00275
00276 void Transform::setTransform(const Matrix4& m)
00277 {
00278 isIdentity=false;
00279 isPureTranslationRotation=false;
00280 t=m;
00281 }
00282
00283
00284 Transform& Transform::invert()
00285 {
00286 if (isIdentity) return *this;
00287 if (!isPureTranslationRotation)
00288 t.invert();
00289 else {
00290 if (!hasTranslation)
00291 orient.invert();
00292 else {
00293 if (!hasRotation)
00294 trans = -trans;
00295 else {
00296 t = getTransform();
00297 t.invert();
00298 isPureTranslationRotation = false;
00299 hasTranslation = hasRotation = true;
00300 isIdentity = (t.equals(Matrix4(1)));
00301 }
00302 }
00303 }
00304 return *this;
00305 }
00306
00307
00308
00309 void Transform::transformPoint(Point3& p) const
00310 {
00311 if (isIdentity) return;
00312 if (isPureTranslationRotation) {
00313 if (hasRotation) orient.rotatePoint(p);
00314 if (hasTranslation) p+=trans;
00315 }
00316 else
00317 p = t*p;
00318 }
00319
00320 void Transform::transformPoint(Point4& p) const
00321 {
00322 if (isIdentity) return;
00323 if (isPureTranslationRotation) {
00324 if (hasRotation) orient.rotatePoint(p);
00325 if (hasTranslation) p+=trans;
00326 }
00327 else
00328 p=t*p;
00329 }
00330
00331
00332 base::Point3 Transform::rotate(const Point3& p) const
00333 {
00334 if (isIdentity) return p;
00335 if (isPureTranslationRotation) {
00336 if (hasRotation) return orient.rotate(p);
00337 }
00338 else {
00339 Matrix3 R = t;
00340 return R*p;
00341 }
00342 return p;
00343 }
00344
00345
00346 base::Point3 Transform::translate(const Point3& p) const
00347 {
00348 if (isIdentity) return p;
00349 if (isPureTranslationRotation) {
00350 if (hasTranslation) return p+trans;
00351 }
00352 else {
00353 return Point3(p.x+t(1,4),p.y+t(2,4),p.z+t(3,4));
00354 }
00355 return p;
00356 }
00357
00358
00359
00360 Transform& Transform::operator*=(const Transform& rhs)
00361 {
00362 if (rhs.identity()) return *this;
00363
00364 if (isIdentity) {
00365 *this = rhs;
00366 return *this;
00367 }
00368
00369 if (isPureTranslationRotation && rhs.isPureTranslationRotation) {
00370
00371 if (hasTranslation && !hasRotation) {
00372
00373 if (!rhs.containsRotation()) {
00374 trans += rhs.trans;
00375 return *this;
00376 }
00377
00378 Vector3 lhstrans(trans);
00379 *this = rhs;
00380 setTranslationComponent(lhstrans + trans);
00381 return *this;
00382 }
00383
00384 if (hasRotation && !hasTranslation && rhs.containsRotation() && !rhs.containsTranslation()) {
00385 Quat4 thisq(orient.getQuat4());
00386 Quat4 rhsq(rhs.orient.getQuat4());
00387 orient = thisq*rhsq;
00388 return *this;
00389 }
00390
00391 }
00392
00393 this->t = getTransform();
00394 this->t *= rhs.getTransform();
00395 isPureTranslationRotation=false;
00396
00397 return *this;
00398 }
00399
00400
00401 std::ostream& base::operator<<(std::ostream& out, const Transform& t)
00402 {
00403 if (t.identity()) {
00404 out << "T:" << Matrix4();
00405 }
00406 else {
00407 if (t.isTransRotationOnly()) {
00408 out << "r:" << t.getRotation() << " t:" << t.getTranslation();
00409 }
00410 else
00411 out << "T:" << t.getTransform();
00412 }
00413
00414 return out;
00415 }