PBRT
|
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