00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #if defined(_MSC_VER)
00025 #pragma once
00026 #endif
00027
00028 #ifndef PBRT_CORE_TRANSFORM_H
00029 #define PBRT_CORE_TRANSFORM_H
00030
00031
00032 #include "pbrt.h"
00033 #include "geometry.h"
00034 #include "quaternion.h"
00035
00036
00037 struct Matrix4x4 {
00038
00039 Matrix4x4() {
00040 m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.f;
00041 m[0][1] = m[0][2] = m[0][3] = m[1][0] =
00042 m[1][2] = m[1][3] = m[2][0] = m[2][1] = m[2][3] =
00043 m[3][0] = m[3][1] = m[3][2] = 0.f;
00044 }
00045 Matrix4x4(float mat[4][4]);
00046 Matrix4x4(float t00, float t01, float t02, float t03,
00047 float t10, float t11, float t12, float t13,
00048 float t20, float t21, float t22, float t23,
00049 float t30, float t31, float t32, float t33);
00050 bool operator==(const Matrix4x4 &m2) const {
00051 for (int i = 0; i < 4; ++i)
00052 for (int j = 0; j < 4; ++j)
00053 if (m[i][j] != m2.m[i][j]) return false;
00054 return true;
00055 }
00056 bool operator!=(const Matrix4x4 &m2) const {
00057 for (int i = 0; i < 4; ++i)
00058 for (int j = 0; j < 4; ++j)
00059 if (m[i][j] != m2.m[i][j]) return true;
00060 return false;
00061 }
00062 friend Matrix4x4 Transpose(const Matrix4x4 &);
00063 void Print(FILE *f) const {
00064 fprintf(f, "[ ");
00065 for (int i = 0; i < 4; ++i) {
00066 fprintf(f, " [ ");
00067 for (int j = 0; j < 4; ++j) {
00068 fprintf(f, "%f", m[i][j]);
00069 if (j != 3) fprintf(f, ", ");
00070 }
00071 fprintf(f, " ]\n");
00072 }
00073 fprintf(f, " ] ");
00074 }
00075 static Matrix4x4 Mul(const Matrix4x4 &m1, const Matrix4x4 &m2) {
00076 Matrix4x4 r;
00077 for (int i = 0; i < 4; ++i)
00078 for (int j = 0; j < 4; ++j)
00079 r.m[i][j] = m1.m[i][0] * m2.m[0][j] +
00080 m1.m[i][1] * m2.m[1][j] +
00081 m1.m[i][2] * m2.m[2][j] +
00082 m1.m[i][3] * m2.m[3][j];
00083 return r;
00084 }
00085 friend Matrix4x4 Inverse(const Matrix4x4 &);
00086 float m[4][4];
00087 };
00088
00089
00090
00091
00092 class Transform {
00093 public:
00094
00095 Transform() { }
00096 Transform(const float mat[4][4]) {
00097 m = Matrix4x4(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
00098 mat[1][0], mat[1][1], mat[1][2], mat[1][3],
00099 mat[2][0], mat[2][1], mat[2][2], mat[2][3],
00100 mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
00101 mInv = Inverse(m);
00102 }
00103 Transform(const Matrix4x4 &mat)
00104 : m(mat), mInv(Inverse(mat)) {
00105 }
00106 Transform(const Matrix4x4 &mat, const Matrix4x4 &minv)
00107 : m(mat), mInv(minv) {
00108 }
00109 void Print(FILE *f) const;
00110 friend Transform Inverse(const Transform &t) {
00111 return Transform(t.mInv, t.m);
00112 }
00113 bool operator==(const Transform &t) const {
00114 return t.m == m && t.mInv == mInv;
00115 }
00116 bool operator!=(const Transform &t) const {
00117 return t.m != m || t.mInv != mInv;
00118 }
00119 bool operator<(const Transform &t2) const {
00120 for (uint32_t i = 0; i < 4; ++i)
00121 for (uint32_t j = 0; j < 4; ++j) {
00122 if (m.m[i][j] < t2.m.m[i][j]) return true;
00123 if (m.m[i][j] > t2.m.m[i][j]) return false;
00124 }
00125 return false;
00126 }
00127 bool IsIdentity() const {
00128 return (m.m[0][0] == 1.f && m.m[0][1] == 0.f &&
00129 m.m[0][2] == 0.f && m.m[0][3] == 0.f &&
00130 m.m[1][0] == 0.f && m.m[1][1] == 1.f &&
00131 m.m[1][2] == 0.f && m.m[1][3] == 0.f &&
00132 m.m[2][0] == 0.f && m.m[2][1] == 0.f &&
00133 m.m[2][2] == 1.f && m.m[2][3] == 0.f &&
00134 m.m[3][0] == 0.f && m.m[3][1] == 0.f &&
00135 m.m[3][2] == 0.f && m.m[3][3] == 1.f);
00136 }
00137 const Matrix4x4 &GetMatrix() const { return m; }
00138 const Matrix4x4 &GetInverseMatrix() const { return mInv; }
00139 bool HasScale() const {
00140 float la2 = (*this)(Vector(1,0,0)).LengthSquared();
00141 float lb2 = (*this)(Vector(0,1,0)).LengthSquared();
00142 float lc2 = (*this)(Vector(0,0,1)).LengthSquared();
00143 #define NOT_ONE(x) ((x) < .999f || (x) > 1.001f)
00144 return (NOT_ONE(la2) || NOT_ONE(lb2) || NOT_ONE(lc2));
00145 #undef NOT_ONE
00146 }
00147 inline Point operator()(const Point &pt) const;
00148 inline void operator()(const Point &pt, Point *ptrans) const;
00149 inline Vector operator()(const Vector &v) const;
00150 inline void operator()(const Vector &v, Vector *vt) const;
00151 inline Normal operator()(const Normal &) const;
00152 inline void operator()(const Normal &, Normal *nt) const;
00153 inline Ray operator()(const Ray &r) const;
00154 inline void operator()(const Ray &r, Ray *rt) const;
00155 inline RayDifferential operator()(const RayDifferential &r) const;
00156 inline void operator()(const RayDifferential &r, RayDifferential *rt) const;
00157 BBox operator()(const BBox &b) const;
00158 Transform operator*(const Transform &t2) const;
00159 bool SwapsHandedness() const;
00160 private:
00161
00162 Matrix4x4 m, mInv;
00163 friend class AnimatedTransform;
00164 friend struct Quaternion;
00165 };
00166
00167
00168 Transform Translate(const Vector &delta);
00169 Transform Scale(float x, float y, float z);
00170 Transform RotateX(float angle);
00171 Transform RotateY(float angle);
00172 Transform RotateZ(float angle);
00173 Transform Rotate(float angle, const Vector &axis);
00174 Transform LookAt(const Point &pos, const Point &look, const Vector &up);
00175 bool SolveLinearSystem2x2(const float A[2][2], const float B[2],
00176 float *x0, float *x1);
00177 Transform Orthographic(float znear, float zfar);
00178 Transform Perspective(float fov, float znear, float zfar);
00179
00180
00181 inline Point Transform::operator()(const Point &pt) const {
00182 float x = pt.x, y = pt.y, z = pt.z;
00183 float xp = m.m[0][0]*x + m.m[0][1]*y + m.m[0][2]*z + m.m[0][3];
00184 float yp = m.m[1][0]*x + m.m[1][1]*y + m.m[1][2]*z + m.m[1][3];
00185 float zp = m.m[2][0]*x + m.m[2][1]*y + m.m[2][2]*z + m.m[2][3];
00186 float wp = m.m[3][0]*x + m.m[3][1]*y + m.m[3][2]*z + m.m[3][3];
00187 Assert(wp != 0);
00188 if (wp == 1.) return Point(xp, yp, zp);
00189 else return Point(xp, yp, zp)/wp;
00190 }
00191
00192
00193 inline void Transform::operator()(const Point &pt,
00194 Point *ptrans) const {
00195 float x = pt.x, y = pt.y, z = pt.z;
00196 ptrans->x = m.m[0][0]*x + m.m[0][1]*y + m.m[0][2]*z + m.m[0][3];
00197 ptrans->y = m.m[1][0]*x + m.m[1][1]*y + m.m[1][2]*z + m.m[1][3];
00198 ptrans->z = m.m[2][0]*x + m.m[2][1]*y + m.m[2][2]*z + m.m[2][3];
00199 float w = m.m[3][0]*x + m.m[3][1]*y + m.m[3][2]*z + m.m[3][3];
00200 if (w != 1.) *ptrans /= w;
00201 }
00202
00203
00204 inline Vector Transform::operator()(const Vector &v) const {
00205 float x = v.x, y = v.y, z = v.z;
00206 return Vector(m.m[0][0]*x + m.m[0][1]*y + m.m[0][2]*z,
00207 m.m[1][0]*x + m.m[1][1]*y + m.m[1][2]*z,
00208 m.m[2][0]*x + m.m[2][1]*y + m.m[2][2]*z);
00209 }
00210
00211
00212 inline void Transform::operator()(const Vector &v,
00213 Vector *vt) const {
00214 float x = v.x, y = v.y, z = v.z;
00215 vt->x = m.m[0][0] * x + m.m[0][1] * y + m.m[0][2] * z;
00216 vt->y = m.m[1][0] * x + m.m[1][1] * y + m.m[1][2] * z;
00217 vt->z = m.m[2][0] * x + m.m[2][1] * y + m.m[2][2] * z;
00218 }
00219
00220
00221 inline Normal Transform::operator()(const Normal &n) const {
00222 float x = n.x, y = n.y, z = n.z;
00223 return Normal(mInv.m[0][0]*x + mInv.m[1][0]*y + mInv.m[2][0]*z,
00224 mInv.m[0][1]*x + mInv.m[1][1]*y + mInv.m[2][1]*z,
00225 mInv.m[0][2]*x + mInv.m[1][2]*y + mInv.m[2][2]*z);
00226 }
00227
00228
00229 inline void Transform::operator()(const Normal &n,
00230 Normal *nt) const {
00231 float x = n.x, y = n.y, z = n.z;
00232 nt->x = mInv.m[0][0] * x + mInv.m[1][0] * y +
00233 mInv.m[2][0] * z;
00234 nt->y = mInv.m[0][1] * x + mInv.m[1][1] * y +
00235 mInv.m[2][1] * z;
00236 nt->z = mInv.m[0][2] * x + mInv.m[1][2] * y +
00237 mInv.m[2][2] * z;
00238 }
00239
00240
00241 inline Ray Transform::operator()(const Ray &r) const {
00242 Ray ret = r;
00243 (*this)(ret.o, &ret.o);
00244 (*this)(ret.d, &ret.d);
00245 return ret;
00246 }
00247
00248
00249 inline void Transform::operator()(const Ray &r, Ray *rt) const {
00250 (*this)(r.o, &rt->o);
00251 (*this)(r.d, &rt->d);
00252 if (rt != &r) {
00253 rt->mint = r.mint;
00254 rt->maxt = r.maxt;
00255 rt->time = r.time;
00256 rt->depth = r.depth;
00257 }
00258 }
00259
00260
00261
00262 inline void Transform::operator()(const RayDifferential &r, RayDifferential *rt) const {
00263 (*this)(Ray(r), rt);
00264 rt->hasDifferentials = r.hasDifferentials;
00265 (*this)(r.rxOrigin, &rt->rxOrigin);
00266 (*this)(r.ryOrigin, &rt->ryOrigin);
00267 (*this)(r.rxDirection, &rt->rxDirection);
00268 (*this)(r.ryDirection, &rt->ryDirection);
00269 }
00270
00271
00272
00273 inline RayDifferential Transform::operator()(const RayDifferential &r) const {
00274 RayDifferential ret;
00275 (*this)(Ray(r), &ret);
00276 ret.hasDifferentials = r.hasDifferentials;
00277 (*this)(r.rxOrigin, &ret.rxOrigin);
00278 (*this)(r.ryOrigin, &ret.ryOrigin);
00279 (*this)(r.rxDirection, &ret.rxDirection);
00280 (*this)(r.ryDirection, &ret.ryDirection);
00281 return ret;
00282 }
00283
00284
00285
00286
00287
00288 class AnimatedTransform {
00289 public:
00290
00291 AnimatedTransform(const Transform *transform1, float time1,
00292 const Transform *transform2, float time2)
00293 : startTime(time1), endTime(time2),
00294 startTransform(transform1), endTransform(transform2),
00295 actuallyAnimated(*startTransform != *endTransform) {
00296 Decompose(startTransform->m, &T[0], &R[0], &S[0]);
00297 Decompose(endTransform->m, &T[1], &R[1], &S[1]);
00298 }
00299 static void Decompose(const Matrix4x4 &m, Vector *T, Quaternion *R, Matrix4x4 *S);
00300 void Interpolate(float time, Transform *t) const;
00301 void InterpolateInverse(float time, Transform *t) const;
00302 void operator()(const Ray &r, Ray *tr) const;
00303 void operator()(const RayDifferential &r, RayDifferential *tr) const;
00304 Point operator()(float time, const Point &p) const;
00305 Vector operator()(float time, const Vector &v) const;
00306 Ray operator()(const Ray &r) const;
00307 BBox MotionBounds(const BBox &b, bool useInverse) const;
00308 bool HasScale() const { return startTransform->HasScale() || endTransform->HasScale(); }
00309 private:
00310
00311 const float startTime, endTime;
00312 const Transform *startTransform, *endTransform;
00313 const bool actuallyAnimated;
00314 Vector T[2];
00315 Quaternion R[2];
00316 Matrix4x4 S[2];
00317 };
00318
00319
00320
00321 #endif // PBRT_CORE_TRANSFORM_H