00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "transform.h"
00025 #include "shape.h"
00026
00027 namespace lux
00028 {
00029
00030
00031 ostream &operator<<(ostream &os, const Transform &t) {
00032 t.m->Print(os);
00033 return os;
00034 }
00035 Transform Translate(const Vector &delta) {
00036 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(1, 0, 0, delta.x,
00037 0, 1, 0, delta.y,
00038 0, 0, 1, delta.z,
00039 0, 0, 0, 1));
00040 boost::shared_ptr<Matrix4x4> minv (new Matrix4x4(1, 0, 0, -delta.x,
00041 0, 1, 0, -delta.y,
00042 0, 0, 1, -delta.z,
00043 0, 0, 0, 1));
00044 return Transform(m, minv);
00045 }
00046 Transform Scale(float x, float y, float z) {
00047 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(x, 0, 0, 0,
00048 0, y, 0, 0,
00049 0, 0, z, 0,
00050 0, 0, 0, 1));
00051 boost::shared_ptr<Matrix4x4> minv (new Matrix4x4(1.f/x, 0, 0, 0,
00052 0, 1.f/y, 0, 0,
00053 0, 0, 1.f/z, 0,
00054 0, 0, 0, 1));
00055 return Transform(m, minv);
00056 }
00057 Transform RotateX(float angle) {
00058 float sin_t = sinf(Radians(angle));
00059 float cos_t = cosf(Radians(angle));
00060 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(1, 0, 0, 0,
00061 0, cos_t, -sin_t, 0,
00062 0, sin_t, cos_t, 0,
00063 0, 0, 0, 1));
00064 return Transform(m, m->Transpose());
00065 }
00066 Transform RotateY(float angle) {
00067 float sin_t = sinf(Radians(angle));
00068 float cos_t = cosf(Radians(angle));
00069 boost::shared_ptr<Matrix4x4> m (new Matrix4x4( cos_t, 0, sin_t, 0,
00070 0, 1, 0, 0,
00071 -sin_t, 0, cos_t, 0,
00072 0, 0, 0, 1));
00073 return Transform(m, m->Transpose());
00074 }
00075
00076 Transform RotateZ(float angle) {
00077 float sin_t = sinf(Radians(angle));
00078 float cos_t = cosf(Radians(angle));
00079 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(cos_t, -sin_t, 0, 0,
00080 sin_t, cos_t, 0, 0,
00081 0, 0, 1, 0,
00082 0, 0, 0, 1));
00083 return Transform(m, m->Transpose());
00084 }
00085 Transform Rotate(float angle, const Vector &axis) {
00086 Vector a = Normalize(axis);
00087 float s = sinf(Radians(angle));
00088 float c = cosf(Radians(angle));
00089 float m[4][4];
00090
00091 m[0][0] = a.x * a.x + (1.f - a.x * a.x) * c;
00092 m[0][1] = a.x * a.y * (1.f - c) - a.z * s;
00093 m[0][2] = a.x * a.z * (1.f - c) + a.y * s;
00094 m[0][3] = 0;
00095
00096 m[1][0] = a.x * a.y * (1.f - c) + a.z * s;
00097 m[1][1] = a.y * a.y + (1.f - a.y * a.y) * c;
00098 m[1][2] = a.y * a.z * (1.f - c) - a.x * s;
00099 m[1][3] = 0;
00100
00101 m[2][0] = a.x * a.z * (1.f - c) - a.y * s;
00102 m[2][1] = a.y * a.z * (1.f - c) + a.x * s;
00103 m[2][2] = a.z * a.z + (1.f - a.z * a.z) * c;
00104 m[2][3] = 0;
00105
00106 m[3][0] = 0;
00107 m[3][1] = 0;
00108 m[3][2] = 0;
00109 m[3][3] = 1;
00110
00111 boost::shared_ptr<Matrix4x4> o (new Matrix4x4(m));
00112 return Transform(o, o->Transpose());
00113 }
00114 Transform LookAt(const Point &pos, const Point &look, const Vector &up) {
00115 float m[4][4];
00116
00117 m[0][3] = pos.x;
00118 m[1][3] = pos.y;
00119 m[2][3] = pos.z;
00120 m[3][3] = 1;
00121 Vector dir = Normalize(look - pos);
00122 Vector right = Normalize(Cross(dir, up));
00123 Vector newUp = Cross(right, dir);
00124 m[0][0] = right.x;
00125 m[1][0] = right.y;
00126 m[2][0] = right.z;
00127 m[3][0] = 0.;
00128 m[0][1] = newUp.x;
00129 m[1][1] = newUp.y;
00130 m[2][1] = newUp.z;
00131 m[3][1] = 0.;
00132 m[0][2] = dir.x;
00133 m[1][2] = dir.y;
00134 m[2][2] = dir.z;
00135 m[3][2] = 0.;
00136 boost::shared_ptr<Matrix4x4> camToWorld (new Matrix4x4(m));
00137 return Transform(camToWorld->Inverse(), camToWorld);
00138 }
00139 bool Transform::HasScale() const {
00140 #if 0
00141 float det = fabsf(m->m[0][0] * (m->m[1][1] * m->m[2][2] - m->m[1][2] * m->m[2][1])) -
00142 (m->m[0][1] * (m->m[1][0] * m->m[2][2] - m->m[1][2] * m->m[2][0])) +
00143 (m->m[0][2] * (m->m[1][0] * m->m[2][1] - m->m[1][1] * m->m[2][0]));
00144 return (det < .999f || det > 1.001f);
00145 #endif
00146 return false;
00147 }
00148 BBox Transform::operator()(const BBox &b) const {
00149 const Transform &M = *this;
00150 BBox ret( M(Point(b.pMin.x, b.pMin.y, b.pMin.z)));
00151 ret = Union(ret,M(Point(b.pMax.x, b.pMin.y, b.pMin.z)));
00152 ret = Union(ret,M(Point(b.pMin.x, b.pMax.y, b.pMin.z)));
00153 ret = Union(ret,M(Point(b.pMin.x, b.pMin.y, b.pMax.z)));
00154 ret = Union(ret,M(Point(b.pMin.x, b.pMax.y, b.pMax.z)));
00155 ret = Union(ret,M(Point(b.pMax.x, b.pMax.y, b.pMin.z)));
00156 ret = Union(ret,M(Point(b.pMax.x, b.pMin.y, b.pMax.z)));
00157 ret = Union(ret,M(Point(b.pMax.x, b.pMax.y, b.pMax.z)));
00158 return ret;
00159 }
00160 Transform Transform::operator*(const Transform &t2) const {
00161 boost::shared_ptr<Matrix4x4> m1 = Matrix4x4::Mul(m, t2.m);
00162 boost::shared_ptr<Matrix4x4> m2 = Matrix4x4::Mul(t2.mInv, mInv);
00163 return Transform(m1, m2);
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 void TransformAccordingNormal(const Normal &nn, const Vector &woL, Vector *woW)
00198 {
00199 Vector sn,tn;
00200 float zz=sqrt(1-nn.z*nn.z);
00201 sn.z = 0;
00202 if (fabs(zz)<1e-6)
00203 {
00204 sn.x = 1;
00205 sn.y = 0;
00206 }
00207 else
00208 {
00209 sn.x = nn.y/zz;
00210 sn.y = -nn.x/zz;
00211 }
00212 tn = Cross(nn, sn);
00213 woW->x = sn.x * woL.x + tn.x * woL.y + nn.x * woL.z;
00214 woW->y = sn.y * woL.x + tn.y * woL.y + nn.y * woL.z;
00215 woW->z = sn.z * woL.x + tn.z * woL.y + nn.z * woL.z;
00216 };
00217
00218 Transform Orthographic(float znear, float zfar) {
00219 return Scale(1.f, 1.f, 1.f / (zfar-znear)) *
00220 Translate(Vector(0.f, 0.f, -znear));
00221 }
00222
00223 Transform Perspective(float fov, float n, float f) {
00224
00225 float inv_denom = 1.f/(f-n);
00226 boost::shared_ptr<Matrix4x4> persp (
00227 new Matrix4x4(1, 0, 0, 0,
00228 0, 1, 0, 0,
00229 0, 0, f*inv_denom, -f*n*inv_denom,
00230 0, 0, 1, 0));
00231
00232 float invTanAng = 1.f / tanf(Radians(fov) / 2.f);
00233 return Scale(invTanAng, invTanAng, 1) *
00234 Transform(persp);
00235 }
00236
00237 }
00238