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