PBRT
/home/felix/UBC/projects/AdaptiveLightfieldSampling/pbrt_v2/src/core/transform.h
00001 
00002 /*
00003     pbrt source code Copyright(c) 1998-2012 Matt Pharr and Greg Humphreys.
00004 
00005     This file is part of pbrt.
00006 
00007     Redistribution and use in source and binary forms, with or without
00008     modification, are permitted provided that the following conditions are
00009     met:
00010 
00011     - Redistributions of source code must retain the above copyright
00012       notice, this list of conditions and the following disclaimer.
00013 
00014     - Redistributions in binary form must reproduce the above copyright
00015       notice, this list of conditions and the following disclaimer in the
00016       documentation and/or other materials provided with the distribution.
00017 
00018     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00019     IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00020     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00021     PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00022     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00023     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030  */
00031 
00032 #if defined(_MSC_VER)
00033 #pragma once
00034 #endif
00035 
00036 #ifndef PBRT_CORE_TRANSFORM_H
00037 #define PBRT_CORE_TRANSFORM_H
00038 
00039 // core/transform.h*
00040 #include "pbrt.h"
00041 #include "geometry.h"
00042 #include "quaternion.h"
00043 
00044 // Matrix4x4 Declarations
00045 struct Matrix4x4 {
00046     // Matrix4x4 Public Methods
00047     Matrix4x4() {
00048         m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.f;
00049         m[0][1] = m[0][2] = m[0][3] = m[1][0] =
00050              m[1][2] = m[1][3] = m[2][0] = m[2][1] = m[2][3] =
00051              m[3][0] = m[3][1] = m[3][2] = 0.f;
00052     }
00053     Matrix4x4(float mat[4][4]);
00054     Matrix4x4(float t00, float t01, float t02, float t03,
00055               float t10, float t11, float t12, float t13,
00056               float t20, float t21, float t22, float t23,
00057               float t30, float t31, float t32, float t33);
00058     bool operator==(const Matrix4x4 &m2) const {
00059         for (int i = 0; i < 4; ++i)
00060             for (int j = 0; j < 4; ++j)
00061                 if (m[i][j] != m2.m[i][j]) return false;
00062         return true;
00063     }
00064     bool operator!=(const Matrix4x4 &m2) const {
00065         for (int i = 0; i < 4; ++i)
00066             for (int j = 0; j < 4; ++j)
00067                 if (m[i][j] != m2.m[i][j]) return true;
00068         return false;
00069     }
00070     friend Matrix4x4 Transpose(const Matrix4x4 &);
00071     void Print(FILE *f) const {
00072         fprintf(f, "[ ");
00073         for (int i = 0; i < 4; ++i) {
00074             fprintf(f, "  [ ");
00075             for (int j = 0; j < 4; ++j)  {
00076                 fprintf(f, "%f", m[i][j]);
00077                 if (j != 3) fprintf(f, ", ");
00078             }
00079             fprintf(f, " ]\n");
00080         }
00081         fprintf(f, " ] ");
00082     }
00083     static Matrix4x4 Mul(const Matrix4x4 &m1, const Matrix4x4 &m2) {
00084         Matrix4x4 r;
00085         for (int i = 0; i < 4; ++i)
00086             for (int j = 0; j < 4; ++j)
00087                 r.m[i][j] = m1.m[i][0] * m2.m[0][j] +
00088                             m1.m[i][1] * m2.m[1][j] +
00089                             m1.m[i][2] * m2.m[2][j] +
00090                             m1.m[i][3] * m2.m[3][j];
00091         return r;
00092     }
00093     friend Matrix4x4 Inverse(const Matrix4x4 &);
00094     float m[4][4];
00095 };
00096 
00097 
00098 
00099 // Transform Declarations
00100 class Transform {
00101 public:
00102     // Transform Public Methods
00103     Transform() { }
00104     Transform(const float mat[4][4]) {
00105         m = Matrix4x4(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
00106                       mat[1][0], mat[1][1], mat[1][2], mat[1][3],
00107                       mat[2][0], mat[2][1], mat[2][2], mat[2][3],
00108                       mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
00109         mInv = Inverse(m);
00110     }
00111     Transform(const Matrix4x4 &mat)
00112         : m(mat), mInv(Inverse(mat)) {
00113     }
00114     Transform(const Matrix4x4 &mat, const Matrix4x4 &minv)
00115        : m(mat), mInv(minv) {
00116     }
00117     void Print(FILE *f) const;
00118     friend Transform Inverse(const Transform &t) {
00119         return Transform(t.mInv, t.m);
00120     }
00121     friend Transform Transpose(const Transform &t) {
00122         return Transform(Transpose(t.m), Transpose(t.mInv));
00123     }
00124     bool operator==(const Transform &t) const {
00125         return t.m == m && t.mInv == mInv;
00126     }
00127     bool operator!=(const Transform &t) const {
00128         return t.m != m || t.mInv != mInv;
00129     }
00130     bool operator<(const Transform &t2) const {
00131         for (uint32_t i = 0; i < 4; ++i)
00132             for (uint32_t j = 0; j < 4; ++j) {
00133                 if (m.m[i][j] < t2.m.m[i][j]) return true;
00134                 if (m.m[i][j] > t2.m.m[i][j]) return false;
00135             }
00136         return false;
00137     }
00138     bool IsIdentity() const {
00139         return (m.m[0][0] == 1.f && m.m[0][1] == 0.f &&
00140                 m.m[0][2] == 0.f && m.m[0][3] == 0.f &&
00141                 m.m[1][0] == 0.f && m.m[1][1] == 1.f &&
00142                 m.m[1][2] == 0.f && m.m[1][3] == 0.f &&
00143                 m.m[2][0] == 0.f && m.m[2][1] == 0.f &&
00144                 m.m[2][2] == 1.f && m.m[2][3] == 0.f &&
00145                 m.m[3][0] == 0.f && m.m[3][1] == 0.f &&
00146                 m.m[3][2] == 0.f && m.m[3][3] == 1.f);
00147     }
00148     const Matrix4x4 &GetMatrix() const { return m; }
00149     const Matrix4x4 &GetInverseMatrix() const { return mInv; }
00150     bool HasScale() const {
00151         float la2 = (*this)(Vector(1,0,0)).LengthSquared();
00152         float lb2 = (*this)(Vector(0,1,0)).LengthSquared();
00153         float lc2 = (*this)(Vector(0,0,1)).LengthSquared();
00154 #define NOT_ONE(x) ((x) < .999f || (x) > 1.001f)
00155         return (NOT_ONE(la2) || NOT_ONE(lb2) || NOT_ONE(lc2));
00156 #undef NOT_ONE
00157     }
00158     inline Point operator()(const Point &pt) const;
00159     inline void operator()(const Point &pt, Point *ptrans) const;
00160     inline Vector operator()(const Vector &v) const;
00161     inline void operator()(const Vector &v, Vector *vt) const;
00162     inline Normal operator()(const Normal &) const;
00163     inline void operator()(const Normal &, Normal *nt) const;
00164     inline Ray operator()(const Ray &r) const;
00165     inline void operator()(const Ray &r, Ray *rt) const;
00166     inline RayDifferential operator()(const RayDifferential &r) const;
00167     inline void operator()(const RayDifferential &r, RayDifferential *rt) const;
00168     BBox operator()(const BBox &b) const;
00169     Transform operator*(const Transform &t2) const;
00170     bool SwapsHandedness() const;
00171 private:
00172     // Transform Private Data
00173     Matrix4x4 m, mInv;
00174     friend class AnimatedTransform;
00175     friend struct Quaternion;
00176 };
00177 
00178 
00179 Transform Translate(const Vector &delta);
00180 Transform Scale(float x, float y, float z);
00181 Transform RotateX(float angle);
00182 Transform RotateY(float angle);
00183 Transform RotateZ(float angle);
00184 Transform Rotate(float angle, const Vector &axis);
00185 Transform LookAt(const Point &pos, const Point &look, const Vector &up);
00186 bool SolveLinearSystem2x2(const float A[2][2], const float B[2],
00187     float *x0, float *x1);
00188 Transform Orthographic(float znear, float zfar);
00189 Transform Perspective(float fov, float znear, float zfar);
00190 
00191 // Transform Inline Functions
00192 inline Point Transform::operator()(const Point &pt) const {
00193     float x = pt.x, y = pt.y, z = pt.z;
00194     float xp = m.m[0][0]*x + m.m[0][1]*y + m.m[0][2]*z + m.m[0][3];
00195     float yp = m.m[1][0]*x + m.m[1][1]*y + m.m[1][2]*z + m.m[1][3];
00196     float zp = m.m[2][0]*x + m.m[2][1]*y + m.m[2][2]*z + m.m[2][3];
00197     float wp = m.m[3][0]*x + m.m[3][1]*y + m.m[3][2]*z + m.m[3][3];
00198     Assert(wp != 0);
00199     if (wp == 1.) return Point(xp, yp, zp);
00200     else          return Point(xp, yp, zp)/wp;
00201 }
00202 
00203 
00204 inline void Transform::operator()(const Point &pt,
00205                                   Point *ptrans) const {
00206     float x = pt.x, y = pt.y, z = pt.z;
00207     ptrans->x = m.m[0][0]*x + m.m[0][1]*y + m.m[0][2]*z + m.m[0][3];
00208     ptrans->y = m.m[1][0]*x + m.m[1][1]*y + m.m[1][2]*z + m.m[1][3];
00209     ptrans->z = m.m[2][0]*x + m.m[2][1]*y + m.m[2][2]*z + m.m[2][3];
00210     float w   = m.m[3][0]*x + m.m[3][1]*y + m.m[3][2]*z + m.m[3][3];
00211     if (w != 1.) *ptrans /= w;
00212 }
00213 
00214 
00215 inline Vector Transform::operator()(const Vector &v) const {
00216   float x = v.x, y = v.y, z = v.z;
00217   return Vector(m.m[0][0]*x + m.m[0][1]*y + m.m[0][2]*z,
00218                 m.m[1][0]*x + m.m[1][1]*y + m.m[1][2]*z,
00219                 m.m[2][0]*x + m.m[2][1]*y + m.m[2][2]*z);
00220 }
00221 
00222 
00223 inline void Transform::operator()(const Vector &v,
00224         Vector *vt) const {
00225   float x = v.x, y = v.y, z = v.z;
00226   vt->x = m.m[0][0] * x + m.m[0][1] * y + m.m[0][2] * z;
00227   vt->y = m.m[1][0] * x + m.m[1][1] * y + m.m[1][2] * z;
00228   vt->z = m.m[2][0] * x + m.m[2][1] * y + m.m[2][2] * z;
00229 }
00230 
00231 
00232 inline Normal Transform::operator()(const Normal &n) const {
00233     float x = n.x, y = n.y, z = n.z;
00234     return Normal(mInv.m[0][0]*x + mInv.m[1][0]*y + mInv.m[2][0]*z,
00235                   mInv.m[0][1]*x + mInv.m[1][1]*y + mInv.m[2][1]*z,
00236                   mInv.m[0][2]*x + mInv.m[1][2]*y + mInv.m[2][2]*z);
00237 }
00238 
00239 
00240 inline void Transform::operator()(const Normal &n,
00241         Normal *nt) const {
00242     float x = n.x, y = n.y, z = n.z;
00243     nt->x = mInv.m[0][0] * x + mInv.m[1][0] * y +
00244         mInv.m[2][0] * z;
00245     nt->y = mInv.m[0][1] * x + mInv.m[1][1] * y +
00246         mInv.m[2][1] * z;
00247     nt->z = mInv.m[0][2] * x + mInv.m[1][2] * y +
00248         mInv.m[2][2] * z;
00249 }
00250 
00251 
00252 inline Ray Transform::operator()(const Ray &r) const {
00253     Ray ret = r;
00254     (*this)(ret.o, &ret.o);
00255     (*this)(ret.d, &ret.d);
00256     return ret;
00257 }
00258 
00259 
00260 inline void Transform::operator()(const Ray &r, Ray *rt) const {
00261     (*this)(r.o, &rt->o);
00262     (*this)(r.d, &rt->d);
00263     if (rt != &r) {
00264         rt->mint = r.mint;
00265         rt->maxt = r.maxt;
00266         rt->time = r.time;
00267         rt->depth = r.depth;
00268     }
00269 }
00270 
00271 
00272 
00273 inline void Transform::operator()(const RayDifferential &r, RayDifferential *rt) const {
00274     (*this)(Ray(r), rt);
00275     rt->hasDifferentials = r.hasDifferentials;
00276     (*this)(r.rxOrigin, &rt->rxOrigin);
00277     (*this)(r.ryOrigin, &rt->ryOrigin);
00278     (*this)(r.rxDirection, &rt->rxDirection);
00279     (*this)(r.ryDirection, &rt->ryDirection);
00280 }
00281 
00282 
00283 
00284 inline RayDifferential Transform::operator()(const RayDifferential &r) const {
00285     RayDifferential ret;
00286     (*this)(Ray(r), &ret);
00287     ret.hasDifferentials = r.hasDifferentials;
00288     (*this)(r.rxOrigin, &ret.rxOrigin);
00289     (*this)(r.ryOrigin, &ret.ryOrigin);
00290     (*this)(r.rxDirection, &ret.rxDirection);
00291     (*this)(r.ryDirection, &ret.ryDirection);
00292     return ret;
00293 }
00294 
00295 
00296 
00297 
00298 // AnimatedTransform Declarations
00299 class AnimatedTransform {
00300 public:
00301     // AnimatedTransform Public Methods
00302     AnimatedTransform(const Transform *transform1, float time1,
00303                       const Transform *transform2, float time2)
00304         : startTime(time1), endTime(time2),
00305           startTransform(transform1), endTransform(transform2),
00306           actuallyAnimated(*startTransform != *endTransform) {
00307         Decompose(startTransform->m, &T[0], &R[0], &S[0]);
00308         Decompose(endTransform->m, &T[1], &R[1], &S[1]);
00309     }
00310     static void Decompose(const Matrix4x4 &m, Vector *T, Quaternion *R, Matrix4x4 *S);
00311     void Interpolate(float time, Transform *t) const;
00312     void operator()(const Ray &r, Ray *tr) const;
00313     void operator()(const RayDifferential &r, RayDifferential *tr) const;
00314     Point operator()(float time, const Point &p) const;
00315     Vector operator()(float time, const Vector &v) const;
00316     Ray operator()(const Ray &r) const;
00317     BBox MotionBounds(const BBox &b, bool useInverse) const;
00318     bool HasScale() const { return startTransform->HasScale() || endTransform->HasScale(); }
00319 private:
00320     // AnimatedTransform Private Data
00321     const float startTime, endTime;
00322     const Transform *startTransform, *endTransform;
00323     const bool actuallyAnimated;
00324     Vector T[2];
00325     Quaternion R[2];
00326     Matrix4x4 S[2];
00327 };
00328 
00329 
00330 
00331 #endif // PBRT_CORE_TRANSFORM_H