00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "matrix.h"
00022
00023 #include <cstdio>
00024
00025 using namespace salt;
00026
00027 float Matrix::mIdentity[16]=
00028 {
00029 1.0, 0.0, 0.0, 0.0,
00030 0.0, 1.0, 0.0, 0.0,
00031 0.0, 0.0, 1.0, 0.0,
00032 0.0, 0.0, 0.0, 1.0
00033 };
00034
00035 void Matrix::Dump() const
00036 {
00037 printf("%f %f %f %f\n", m[0], m[4], m[8], m[12]);
00038 printf("%f %f %f %f\n", m[1], m[5], m[9], m[13]);
00039 printf("%f %f %f %f\n", m[2], m[6], m[10], m[14]);
00040 printf("%f %f %f %f\n", m[3], m[7], m[11], m[15]);
00041 }
00042
00043
00044 void Matrix::LookAt(const Vector3f & inEye, const Vector3f & inDirection, const Vector3f & inUp)
00045 {
00046 Vector3f forward = inDirection.Normalized();
00047 Vector3f up = inUp.Normalized();
00048 Vector3f right = forward.Cross(up);
00049 right.Normalize();
00050
00051 up = right.Cross(forward);
00052
00053
00054 Set( right.x(), right.y(), right.z(), 0.0f,
00055 up.x(), up.y(), up.z(), 0.0f,
00056 forward.x(), forward.y(), forward.z(), 0.0f,
00057 0.0f, 0.0f, 0.0f, 1.0f);
00058
00059 Pos() = Rotate(-inEye);
00060 }
00061
00066 void Matrix::CalcAttenuationNoRotation(const Vector3f &pos, float radius)
00067 {
00068 Matrix tmp1, tmp2;
00069
00070
00071 tmp1.Translation(-pos);
00072
00073
00074 float invrad = 0.5f / radius;
00075
00076 tmp2.Identity();
00077 tmp2(0,0) = invrad;
00078 tmp2(1,1) = invrad;
00079 tmp2(2,2) = invrad;
00080
00081 Identity ();
00082 Translation (Vector3f(0.5f, 0.5f, 0.5f));
00083
00084 *this *= tmp2 * tmp1;
00085 }
00086
00087 void Matrix::CalcAttenuationWithRotation(const Matrix &lightWorldMatrix, float radius)
00088 {
00089 Matrix tmp1, tmp2;
00090
00091
00092 tmp1 = lightWorldMatrix;
00093 tmp1.InvertRotationMatrix();
00094
00095
00096 float invrad = 0.5f / radius;
00097
00098 tmp2.Identity();
00099 tmp2(0,0) = invrad;
00100 tmp2(1,1) = invrad;
00101 tmp2(2,2) = invrad;
00102
00103 Identity ();
00104 Translation (Vector3f(0.5f, 0.5f, 0.5f));
00105
00106 *this *= tmp2 * tmp1;
00107 }
00108
00109 void Matrix::CalcInfiniteProjection(float width, float height, float fov, float zNear)
00110 {
00111 const float halfWidth = zNear * (float)tan(gDegToRad(fov*0.5f));
00112 const float halfHeight = halfWidth * (height/width);
00113
00114 CalcInfiniteFrustum(-halfWidth, halfWidth, -halfHeight, halfHeight, zNear);
00115 }
00116
00117 void Matrix::CalcInfiniteFrustum(float left, float right, float bottom, float top, float zNear)
00118 {
00119 Identity();
00120
00121 El(0,0) = (2*zNear) / (right - left);
00122 El(0,2) = (right + left) / (right - left);
00123
00124 El(1,1) = (2*zNear) / (top - bottom);
00125 El(1,2) = (top + bottom) / (top - bottom);
00126
00127
00128 const float nudge = 1 - 1.0 / (1<<23);
00129
00130 El(2,2) = -1 * nudge;
00131 El(2,3) = -2*zNear * nudge;
00132
00133 El(3,2) = -1;
00134 El(3,3) = 0;
00135 }
00136
00137 void Matrix::CalcSpotLight(const Matrix &lightWorldTransform, float fov, float width, float height, float zNear)
00138 {
00139 Matrix scale, proj, space;
00140 Vector3f halfVector(0.5f, 0.5f, 0.5f);
00141
00142 Identity ();
00143 Translation (halfVector);
00144
00145 scale.Identity ();
00146 scale.Scale (halfVector);
00147
00148
00149 proj.CalcInfiniteProjection(width, height, fov, zNear);
00150
00151 space = lightWorldTransform;
00152 space.InvertRotationMatrix();
00153
00154
00155
00156 *this *= scale * proj * space;
00157 }
00158
00159 bool Matrix::IsEqual(const Matrix& matrix) const
00160 {
00161 for (int i=0; i<16; ++i)
00162 if (matrix.m[i] != m[i]) return false;
00163
00164 return true;
00165 }