00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "transform.h"
00026 #include "shape.h"
00027
00028 ostream &operator<<(ostream &os, const Transform &t) {
00029 t.m->Print(os);
00030 return os;
00031 }
00032 COREDLL Transform Translate(const Vector &delta) {
00033 Matrix4x4 *m, *minv;
00034 m = new Matrix4x4(1, 0, 0, delta.x,
00035 0, 1, 0, delta.y,
00036 0, 0, 1, delta.z,
00037 0, 0, 0, 1);
00038 minv = new Matrix4x4(1, 0, 0, -delta.x,
00039 0, 1, 0, -delta.y,
00040 0, 0, 1, -delta.z,
00041 0, 0, 0, 1);
00042 return Transform(m, minv);
00043 }
00044 COREDLL Transform Scale(float x, float y, float z) {
00045 Matrix4x4 *m, *minv;
00046 m = new Matrix4x4(x, 0, 0, 0,
00047 0, y, 0, 0,
00048 0, 0, z, 0,
00049 0, 0, 0, 1);
00050 minv = new Matrix4x4(1.f/x, 0, 0, 0,
00051 0, 1.f/y, 0, 0,
00052 0, 0, 1.f/z, 0,
00053 0, 0, 0, 1);
00054 return Transform(m, minv);
00055 }
00056 Transform RotateX(float angle) {
00057 float sin_t = sinf(Radians(angle));
00058 float cos_t = cosf(Radians(angle));
00059 Matrix4x4 *m = new Matrix4x4(1, 0, 0, 0,
00060 0, cos_t, -sin_t, 0,
00061 0, sin_t, cos_t, 0,
00062 0, 0, 0, 1);
00063 return Transform(m, m->Transpose());
00064 }
00065 Transform RotateY(float angle) {
00066 float sin_t = sinf(Radians(angle));
00067 float cos_t = cosf(Radians(angle));
00068 Matrix4x4 *m = new Matrix4x4( cos_t, 0, sin_t, 0,
00069 0, 1, 0, 0,
00070 -sin_t, 0, cos_t, 0,
00071 0, 0, 0, 1);
00072 return Transform(m, m->Transpose());
00073 }
00074
00075 Transform RotateZ(float angle) {
00076 float sin_t = sinf(Radians(angle));
00077 float cos_t = cosf(Radians(angle));
00078 Matrix4x4 *m = new Matrix4x4(cos_t, -sin_t, 0, 0,
00079 sin_t, cos_t, 0, 0,
00080 0, 0, 1, 0,
00081 0, 0, 0, 1);
00082 return Transform(m, m->Transpose());
00083 }
00084 Transform Rotate(float angle, const Vector &axis) {
00085 Vector a = Normalize(axis);
00086 float s = sinf(Radians(angle));
00087 float c = cosf(Radians(angle));
00088 float m[4][4];
00089
00090 m[0][0] = a.x * a.x + (1.f - a.x * a.x) * c;
00091 m[0][1] = a.x * a.y * (1.f - c) - a.z * s;
00092 m[0][2] = a.x * a.z * (1.f - c) + a.y * s;
00093 m[0][3] = 0;
00094
00095 m[1][0] = a.x * a.y * (1.f - c) + a.z * s;
00096 m[1][1] = a.y * a.y + (1.f - a.y * a.y) * c;
00097 m[1][2] = a.y * a.z * (1.f - c) - a.x * s;
00098 m[1][3] = 0;
00099
00100 m[2][0] = a.x * a.z * (1.f - c) - a.y * s;
00101 m[2][1] = a.y * a.z * (1.f - c) + a.x * s;
00102 m[2][2] = a.z * a.z + (1.f - a.z * a.z) * c;
00103 m[2][3] = 0;
00104
00105 m[3][0] = 0;
00106 m[3][1] = 0;
00107 m[3][2] = 0;
00108 m[3][3] = 1;
00109
00110 Matrix4x4 *mat = new Matrix4x4(m);
00111 return Transform(mat, mat->Transpose());
00112 }
00113 Transform LookAt(const Point &pos, const Point &look, const Vector &up) {
00114 float m[4][4];
00115
00116 m[0][3] = pos.x;
00117 m[1][3] = pos.y;
00118 m[2][3] = pos.z;
00119 m[3][3] = 1;
00120
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 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 Reference<Matrix4x4> m1 = Matrix4x4::Mul(m, t2.m);
00162 Reference<Matrix4x4> m2 = Matrix4x4::Mul(t2.mInv, mInv);
00163 return Transform(m1, m2);
00164 }
00165 bool Transform::SwapsHandedness() const {
00166 float det = ((m->m[0][0] *
00167 (m->m[1][1] * m->m[2][2] -
00168 m->m[1][2] * m->m[2][1])) -
00169 (m->m[0][1] *
00170 (m->m[1][0] * m->m[2][2] -
00171 m->m[1][2] * m->m[2][0])) +
00172 (m->m[0][2] *
00173 (m->m[1][0] * m->m[2][1] -
00174 m->m[1][1] * m->m[2][0])));
00175 return det < 0.f;
00176 }
00177 Transform COREDLL Orthographic(float znear, float zfar) {
00178 return Scale(1.f, 1.f, 1.f / (zfar-znear)) *
00179 Translate(Vector(0.f, 0.f, -znear));
00180 }
00181 COREDLL
00182 Transform Perspective(float fov, float n, float f) {
00183
00184 float inv_denom = 1.f/(f-n);
00185 Matrix4x4 *persp =
00186 new Matrix4x4(1, 0, 0, 0,
00187 0, 1, 0, 0,
00188 0, 0, f*inv_denom, -f*n*inv_denom,
00189 0, 0, 1, 0);
00190
00191 float invTanAng = 1.f / tanf(Radians(fov) / 2.f);
00192 return Scale(invTanAng, invTanAng, 1) *
00193 Transform(persp);
00194 }