00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023
00024 #include <cmath>
00025 #include <stdexcept>
00026
00027 #include "luxrays/core/geometry/matrix4x4.h"
00028 #include "luxrays/core/utils.h"
00029
00030 namespace luxrays {
00031
00032 Matrix4x4::Matrix4x4(float mat[4][4]) {
00033 memcpy(m, mat, 16 * sizeof (float));
00034 }
00035
00036 Matrix4x4::Matrix4x4(float t00, float t01, float t02, float t03,
00037 float t10, float t11, float t12, float t13,
00038 float t20, float t21, float t22, float t23,
00039 float t30, float t31, float t32, float t33) {
00040 m[0][0] = t00;
00041 m[0][1] = t01;
00042 m[0][2] = t02;
00043 m[0][3] = t03;
00044 m[1][0] = t10;
00045 m[1][1] = t11;
00046 m[1][2] = t12;
00047 m[1][3] = t13;
00048 m[2][0] = t20;
00049 m[2][1] = t21;
00050 m[2][2] = t22;
00051 m[2][3] = t23;
00052 m[3][0] = t30;
00053 m[3][1] = t31;
00054 m[3][2] = t32;
00055 m[3][3] = t33;
00056 }
00057
00058 Matrix4x4 Matrix4x4::Transpose() const {
00059 return Matrix4x4(m[0][0], m[1][0], m[2][0], m[3][0],
00060 m[0][1], m[1][1], m[2][1], m[3][1],
00061 m[0][2], m[1][2], m[2][2], m[3][2],
00062 m[0][3], m[1][3], m[2][3], m[3][3]);
00063 }
00064
00065
00066 float Det2x2(const float a00, const float a01, const float a10, const float a11) {
00067 return a00 * a11 - a01*a10;
00068 }
00069
00070
00071 float Det3x3(float A[3][3]) {
00072 return
00073 A[0][0] * Det2x2(A[1][1], A[1][2], A[2][1], A[2][2]) -
00074 A[0][1] * Det2x2(A[1][0], A[1][2], A[2][0], A[2][2]) +
00075 A[0][2] * Det2x2(A[1][0], A[1][1], A[2][0], A[2][1]);
00076 }
00077
00078 float Matrix4x4::Determinant() const {
00079
00080
00081
00082
00083 float result = 0;
00084 float s = -1;
00085
00086 float A[3][3];
00087
00088
00089 for (int i = 0; i < 3; i++) {
00090 for (int j = 0; j < 3; j++)
00091 A[i][j] = m[i][j + 1];
00092 }
00093
00094 int k = 0;
00095
00096 while (true) {
00097 if (m[3][k] != 0.f)
00098 result += s * m[3][k] * Det3x3(A);
00099
00100
00101 if (k >= 3)
00102 break;
00103
00104 s *= -1;
00105
00106
00107 for (int i = 0; i < 3; i++)
00108 A[i][k] = m[i][k];
00109
00110 k++;
00111 }
00112
00113 return result;
00114 }
00115
00116 Matrix4x4 Matrix4x4::Inverse() const {
00117 int indxc[4], indxr[4];
00118 int ipiv[4] = {0, 0, 0, 0};
00119 float minv[4][4];
00120 memcpy(minv, m, 4 * 4 * sizeof (float));
00121 for (int i = 0; i < 4; ++i) {
00122 int irow = -1, icol = -1;
00123 float big = 0.;
00124
00125 for (int j = 0; j < 4; ++j) {
00126 if (ipiv[j] != 1) {
00127 for (int k = 0; k < 4; ++k) {
00128 if (ipiv[k] == 0) {
00129 if (fabsf(minv[j][k]) >= big) {
00130 big = fabsf(minv[j][k]);
00131 irow = j;
00132 icol = k;
00133 }
00134 } else if (ipiv[k] > 1)
00135 throw std::runtime_error("Singular matrix in MatrixInvert");
00136 }
00137 }
00138 }
00139 ++ipiv[icol];
00140
00141 if (irow != icol) {
00142 for (int k = 0; k < 4; ++k)
00143 Swap(minv[irow][k], minv[icol][k]);
00144 }
00145 indxr[i] = irow;
00146 indxc[i] = icol;
00147 if (minv[icol][icol] == 0.)
00148 throw std::runtime_error("Singular matrix in MatrixInvert");
00149
00150 float pivinv = 1.f / minv[icol][icol];
00151 minv[icol][icol] = 1.f;
00152 for (int j = 0; j < 4; ++j)
00153 minv[icol][j] *= pivinv;
00154
00155 for (int j = 0; j < 4; ++j) {
00156 if (j != icol) {
00157 float save = minv[j][icol];
00158 minv[j][icol] = 0;
00159 for (int k = 0; k < 4; ++k)
00160 minv[j][k] -= minv[icol][k] * save;
00161 }
00162 }
00163 }
00164
00165 for (int j = 3; j >= 0; --j) {
00166 if (indxr[j] != indxc[j]) {
00167 for (int k = 0; k < 4; ++k)
00168 Swap(minv[k][indxr[j]], minv[k][indxc[j]]);
00169 }
00170 }
00171
00172 return Matrix4x4(minv);
00173 }
00174
00175 }