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 const boost::shared_ptr<Matrix4x4> Transform::MAT_IDENTITY =
00031 boost::shared_ptr<Matrix4x4>(new Matrix4x4());
00032
00033
00034 ostream &operator<<(ostream &os, const Transform &t) {
00035 t.m->Print(os);
00036 return os;
00037 }
00038 Transform Translate(const Vector &delta) {
00039 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(1, 0, 0, delta.x,
00040 0, 1, 0, delta.y,
00041 0, 0, 1, delta.z,
00042 0, 0, 0, 1));
00043 boost::shared_ptr<Matrix4x4> minv (new Matrix4x4(1, 0, 0, -delta.x,
00044 0, 1, 0, -delta.y,
00045 0, 0, 1, -delta.z,
00046 0, 0, 0, 1));
00047 return Transform(m, minv);
00048 }
00049 Transform Scale(float x, float y, float z) {
00050 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(x, 0, 0, 0,
00051 0, y, 0, 0,
00052 0, 0, z, 0,
00053 0, 0, 0, 1));
00054 boost::shared_ptr<Matrix4x4> minv (new Matrix4x4(1.f/x, 0, 0, 0,
00055 0, 1.f/y, 0, 0,
00056 0, 0, 1.f/z, 0,
00057 0, 0, 0, 1));
00058 return Transform(m, minv);
00059 }
00060 Transform RotateX(float angle) {
00061 float sin_t = sinf(Radians(angle));
00062 float cos_t = cosf(Radians(angle));
00063 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(1, 0, 0, 0,
00064 0, cos_t, -sin_t, 0,
00065 0, sin_t, cos_t, 0,
00066 0, 0, 0, 1));
00067 return Transform(m, m->Transpose());
00068 }
00069 Transform RotateY(float angle) {
00070 float sin_t = sinf(Radians(angle));
00071 float cos_t = cosf(Radians(angle));
00072 boost::shared_ptr<Matrix4x4> m (new Matrix4x4( cos_t, 0, sin_t, 0,
00073 0, 1, 0, 0,
00074 -sin_t, 0, cos_t, 0,
00075 0, 0, 0, 1));
00076 return Transform(m, m->Transpose());
00077 }
00078
00079 Transform RotateZ(float angle) {
00080 float sin_t = sinf(Radians(angle));
00081 float cos_t = cosf(Radians(angle));
00082 boost::shared_ptr<Matrix4x4> m (new Matrix4x4(cos_t, -sin_t, 0, 0,
00083 sin_t, cos_t, 0, 0,
00084 0, 0, 1, 0,
00085 0, 0, 0, 1));
00086 return Transform(m, m->Transpose());
00087 }
00088 Transform Rotate(float angle, const Vector &axis) {
00089 Vector a = Normalize(axis);
00090 float s = sinf(Radians(angle));
00091 float c = cosf(Radians(angle));
00092 float m[4][4];
00093
00094 m[0][0] = a.x * a.x + (1.f - a.x * a.x) * c;
00095 m[0][1] = a.x * a.y * (1.f - c) - a.z * s;
00096 m[0][2] = a.x * a.z * (1.f - c) + a.y * s;
00097 m[0][3] = 0;
00098
00099 m[1][0] = a.x * a.y * (1.f - c) + a.z * s;
00100 m[1][1] = a.y * a.y + (1.f - a.y * a.y) * c;
00101 m[1][2] = a.y * a.z * (1.f - c) - a.x * s;
00102 m[1][3] = 0;
00103
00104 m[2][0] = a.x * a.z * (1.f - c) - a.y * s;
00105 m[2][1] = a.y * a.z * (1.f - c) + a.x * s;
00106 m[2][2] = a.z * a.z + (1.f - a.z * a.z) * c;
00107 m[2][3] = 0;
00108
00109 m[3][0] = 0;
00110 m[3][1] = 0;
00111 m[3][2] = 0;
00112 m[3][3] = 1;
00113
00114 boost::shared_ptr<Matrix4x4> o (new Matrix4x4(m));
00115 return Transform(o, o->Transpose());
00116 }
00117 Transform LookAt(const Point &pos, const Point &look, const Vector &up) {
00118 float m[4][4];
00119
00120 m[0][3] = pos.x;
00121 m[1][3] = pos.y;
00122 m[2][3] = pos.z;
00123 m[3][3] = 1;
00124 Vector dir = Normalize(look - pos);
00125 Vector right = Normalize(Cross(dir, up));
00126 Vector newUp = Cross(right, dir);
00127 m[0][0] = right.x;
00128 m[1][0] = right.y;
00129 m[2][0] = right.z;
00130 m[3][0] = 0.;
00131 m[0][1] = newUp.x;
00132 m[1][1] = newUp.y;
00133 m[2][1] = newUp.z;
00134 m[3][1] = 0.;
00135 m[0][2] = dir.x;
00136 m[1][2] = dir.y;
00137 m[2][2] = dir.z;
00138 m[3][2] = 0.;
00139 boost::shared_ptr<Matrix4x4> camToWorld (new Matrix4x4(m));
00140 return Transform(camToWorld->Inverse(), camToWorld);
00141 }
00142 bool Transform::HasScale() const {
00143
00144 float det = fabsf(m->m[0][0] * (m->m[1][1] * m->m[2][2] - m->m[1][2] * m->m[2][1])) -
00145 (m->m[0][1] * (m->m[1][0] * m->m[2][2] - m->m[1][2] * m->m[2][0])) +
00146 (m->m[0][2] * (m->m[1][0] * m->m[2][1] - m->m[1][1] * m->m[2][0]));
00147 return (det < .999f || det > 1.001f);
00148
00149
00150 }
00151 BBox Transform::operator()(const BBox &b) const {
00152 const Transform &M = *this;
00153 BBox ret( M(Point(b.pMin.x, b.pMin.y, b.pMin.z)));
00154 ret = Union(ret,M(Point(b.pMax.x, b.pMin.y, b.pMin.z)));
00155 ret = Union(ret,M(Point(b.pMin.x, b.pMax.y, b.pMin.z)));
00156 ret = Union(ret,M(Point(b.pMin.x, b.pMin.y, b.pMax.z)));
00157 ret = Union(ret,M(Point(b.pMin.x, b.pMax.y, b.pMax.z)));
00158 ret = Union(ret,M(Point(b.pMax.x, b.pMax.y, b.pMin.z)));
00159 ret = Union(ret,M(Point(b.pMax.x, b.pMin.y, b.pMax.z)));
00160 ret = Union(ret,M(Point(b.pMax.x, b.pMax.y, b.pMax.z)));
00161 return ret;
00162 }
00163 Transform Transform::operator*(const Transform &t2) const {
00164 boost::shared_ptr<Matrix4x4> m1 = Matrix4x4::Mul(m, t2.m);
00165 boost::shared_ptr<Matrix4x4> m2 = Matrix4x4::Mul(t2.mInv, mInv);
00166 return Transform(m1, m2);
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
00198
00199
00200 void TransformAccordingNormal(const Normal &nn, const Vector &woL, Vector *woW)
00201 {
00202 Vector sn, tn;
00203 float zz=sqrtf(1.f - nn.z * nn.z);
00204 sn.z = 0.f;
00205 if (fabs(zz) < 1e-6f)
00206 {
00207 sn.x = 1.f;
00208 sn.y = 0.f;
00209 } else {
00210 sn.x = nn.y / zz;
00211 sn.y = -nn.x / zz;
00212 }
00213 tn = Cross(nn, sn);
00214 *woW = woL.x * sn + woL.y * tn + woL.z * Vector(nn);
00215 }
00216
00217 Transform Orthographic(float znear, float zfar)
00218 {
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
00226 float inv_denom = 1.f/(1.f - n / f);
00227 boost::shared_ptr<Matrix4x4> persp(
00228 new Matrix4x4(1, 0, 0, 0,
00229 0, 1, 0, 0,
00230 0, 0, inv_denom, -n*inv_denom,
00231 0, 0, 1, 0));
00232
00233 float invTanAng = 1.f / tanf(Radians(fov) / 2.f);
00234 return Scale(invTanAng, invTanAng, 1) * Transform(persp);
00235 }
00236
00237 }
00238