2
Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published
7
by the Free Software Foundation, either version 2.1 of the License, or
8
(at your option) any later version.
10
Thisprogram is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU Lesser General Public License for more details.
15
You should have received a copy of the GNU Lesser General Public License
16
along with this program; If not, see <http://www.gnu.org/licenses/>.
18
#include "lib3ds_impl.h"
22
* Clear a matrix to all zeros.
24
* \param m Matrix to be cleared.
27
lib3ds_matrix_zero(float m[4][4]) {
30
for (i = 0; i < 4; i++) {
31
for (j = 0; j < 4; j++) m[i][j] = 0.0f;
37
* Set a matrix to identity.
39
* \param m Matrix to be set.
42
lib3ds_matrix_identity(float m[4][4]) {
45
for (i = 0; i < 4; i++) {
46
for (j = 0; j < 4; j++) m[i][j] = 0.0;
48
for (i = 0; i < 4; i++) m[i][i] = 1.0;
56
lib3ds_matrix_copy(float dest[4][4], float src[4][4]) {
57
memcpy(dest, src, 16 * sizeof(float));
62
* Negate a matrix -- all elements negated.
65
lib3ds_matrix_neg(float m[4][4]) {
68
for (j = 0; j < 4; j++) {
69
for (i = 0; i < 4; i++) {
77
* Transpose a matrix in place.
80
lib3ds_matrix_transpose(float m[4][4]) {
84
for (j = 0; j < 4; j++) {
85
for (i = j + 1; i < 4; i++) {
98
lib3ds_matrix_add(float m[4][4], float a[4][4], float b[4][4]) {
101
for (j = 0; j < 4; j++) {
102
for (i = 0; i < 4; i++) {
103
m[j][i] = a[j][i] + b[j][i];
110
* Subtract two matrices.
117
lib3ds_matrix_sub(float m[4][4], float a[4][4], float b[4][4]) {
120
for (j = 0; j < 4; j++) {
121
for (i = 0; i < 4; i++) {
122
m[j][i] = a[j][i] - b[j][i];
129
* Multiplies a matrix by a second one (m = m * n).
132
lib3ds_matrix_mult(float m[4][4], float a[4][4], float b[4][4]) {
137
memcpy(tmp, a, 16 * sizeof(float));
138
for (j = 0; j < 4; j++) {
139
for (i = 0; i < 4; i++) {
141
for (k = 0; k < 4; k++) ab += tmp[k][i] * b[j][k];
149
* Multiply a matrix by a scalar.
151
* \param m Matrix to be set.
155
lib3ds_matrix_scalar(float m[4][4], float k) {
158
for (j = 0; j < 4; j++) {
159
for (i = 0; i < 4; i++) {
170
return((a)*(d) - (b)*(c));
176
float a1, float a2, float a3,
177
float b1, float b2, float b3,
178
float c1, float c2, float c3) {
180
a1*det2x2(b2, b3, c2, c3) -
181
b1*det2x2(a2, a3, c2, c3) +
182
c1*det2x2(a2, a3, b2, b3)
188
* Find determinant of a matrix.
191
lib3ds_matrix_det(float m[4][4]) {
192
float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
211
a1 * det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
212
b1 * det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
213
c1 * det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
214
d1 * det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4)
220
* Invert a matrix in place.
222
* \param m Matrix to invert.
224
* \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
226
* GGemsII, K.Wu, Fast Matrix Inversion
229
lib3ds_matrix_inv(float m[4][4]) {
231
int pvt_i[4], pvt_j[4]; /* Locations of pivot elements */
232
float pvt_val; /* Value of current pivot element */
233
float hold; /* Temporary storage */
237
for (k = 0; k < 4; k++) {
238
/* Locate k'th pivot element */
239
pvt_val = m[k][k]; /* Initialize for search */
242
for (i = k; i < 4; i++) {
243
for (j = k; j < 4; j++) {
244
if (fabs(m[i][j]) > fabs(pvt_val)) {
252
/* Product of pivots, gives determinant when finished */
253
determinat *= pvt_val;
254
if (fabs(determinat) < LIB3DS_EPSILON) {
255
return(FALSE); /* Matrix is singular (zero determinant) */
258
/* "Interchange" rows (with sign change stuff) */
260
if (i != k) { /* If rows are different */
261
for (j = 0; j < 4; j++) {
268
/* "Interchange" columns */
270
if (j != k) { /* If columns are different */
271
for (i = 0; i < 4; i++) {
278
/* Divide column by minus pivot value */
279
for (i = 0; i < 4; i++) {
280
if (i != k) m[i][k] /= (-pvt_val) ;
283
/* Reduce the matrix */
284
for (i = 0; i < 4; i++) {
286
for (j = 0; j < 4; j++) {
287
if (i != k && j != k) m[i][j] += hold * m[k][j];
291
/* Divide row by pivot */
292
for (j = 0; j < 4; j++) {
293
if (j != k) m[k][j] /= pvt_val;
296
/* Replace pivot by reciprocal (at last we can touch it). */
297
m[k][k] = 1.0f / pvt_val;
300
/* That was most of the work, one final pass of row/column interchange */
302
for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
303
i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
304
if (i != k) { /* If rows are different */
305
for (j = 0; j < 4; j++) {
312
j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
313
if (j != k) /* If columns are different */
314
for (i = 0; i < 4; i++) {
325
* Apply a translation to a matrix.
328
lib3ds_matrix_translate(float m[4][4], float x, float y, float z) {
331
for (i = 0; i < 3; i++) {
332
m[3][i] += m[0][i] * x + m[1][i] * y + m[2][i] * z;
338
* Apply scale factors to a matrix.
341
lib3ds_matrix_scale(float m[4][4], float x, float y, float z) {
344
for (i = 0; i < 4; i++) {
353
* Apply a rotation about an arbitrary axis to a matrix.
356
lib3ds_matrix_rotate_quat(float m[4][4], float q[4]) {
357
float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, l;
360
l = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
361
if (fabs(l) < LIB3DS_EPSILON) {
380
R[0][0] = 1.0f - (yy + zz);
384
R[1][1] = 1.0f - (xx + zz);
388
R[2][2] = 1.0f - (xx + yy);
389
R[3][0] = R[3][1] = R[3][2] = R[0][3] = R[1][3] = R[2][3] = 0.0f;
392
lib3ds_matrix_mult(m, m, R);
397
* Apply a rotation about an arbitrary axis to a matrix.
400
lib3ds_matrix_rotate(float m[4][4], float angle, float ax, float ay, float az) {
404
lib3ds_vector_make(axis, ax, ay, az);
405
lib3ds_quat_axis_angle(q, axis, angle);
406
lib3ds_matrix_rotate_quat(m, q);
411
* Compute a camera matrix based on position, target and roll.
413
* Generates a translate/rotate matrix that maps world coordinates
414
* to camera coordinates. Resulting matrix does not include perspective
417
* \param matrix Destination matrix.
418
* \param pos Camera position
419
* \param tgt Camera target
420
* \param roll Roll angle
423
lib3ds_matrix_camera(float matrix[4][4], float pos[3], float tgt[3], float roll) {
425
float x[3], y[3], z[3];
427
lib3ds_vector_sub(y, tgt, pos);
428
lib3ds_vector_normalize(y);
430
if (y[0] != 0. || y[1] != 0) {
434
} else { /* Special case: looking straight up or down z axis */
440
lib3ds_vector_cross(x, y, z);
441
lib3ds_vector_cross(z, x, y);
442
lib3ds_vector_normalize(x);
443
lib3ds_vector_normalize(z);
445
lib3ds_matrix_identity(M);
456
lib3ds_matrix_identity(matrix);
457
lib3ds_matrix_rotate(matrix, roll, 0, 1, 0);
458
lib3ds_matrix_mult(matrix, matrix, M);
459
lib3ds_matrix_translate(matrix, -pos[0], -pos[1], -pos[2]);
2
Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published
7
by the Free Software Foundation, either version 2.1 of the License, or
8
(at your option) any later version.
10
Thisprogram is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU Lesser General Public License for more details.
15
You should have received a copy of the GNU Lesser General Public License
16
along with this program; If not, see <http://www.gnu.org/licenses/>.
18
#include "lib3ds_impl.h"
22
* Clear a matrix to all zeros.
24
* \param m Matrix to be cleared.
27
lib3ds_matrix_zero(float m[4][4]) {
30
for (i = 0; i < 4; i++) {
31
for (j = 0; j < 4; j++) m[i][j] = 0.0f;
37
* Set a matrix to identity.
39
* \param m Matrix to be set.
42
lib3ds_matrix_identity(float m[4][4]) {
45
for (i = 0; i < 4; i++) {
46
for (j = 0; j < 4; j++) m[i][j] = 0.0;
48
for (i = 0; i < 4; i++) m[i][i] = 1.0;
56
lib3ds_matrix_copy(float dest[4][4], float src[4][4]) {
57
memcpy(dest, src, 16 * sizeof(float));
62
* Negate a matrix -- all elements negated.
65
lib3ds_matrix_neg(float m[4][4]) {
68
for (j = 0; j < 4; j++) {
69
for (i = 0; i < 4; i++) {
77
* Transpose a matrix in place.
80
lib3ds_matrix_transpose(float m[4][4]) {
84
for (j = 0; j < 4; j++) {
85
for (i = j + 1; i < 4; i++) {
98
lib3ds_matrix_add(float m[4][4], float a[4][4], float b[4][4]) {
101
for (j = 0; j < 4; j++) {
102
for (i = 0; i < 4; i++) {
103
m[j][i] = a[j][i] + b[j][i];
110
* Subtract two matrices.
117
lib3ds_matrix_sub(float m[4][4], float a[4][4], float b[4][4]) {
120
for (j = 0; j < 4; j++) {
121
for (i = 0; i < 4; i++) {
122
m[j][i] = a[j][i] - b[j][i];
129
* Multiplies a matrix by a second one (m = m * n).
132
lib3ds_matrix_mult(float m[4][4], float a[4][4], float b[4][4]) {
137
memcpy(tmp, a, 16 * sizeof(float));
138
for (j = 0; j < 4; j++) {
139
for (i = 0; i < 4; i++) {
141
for (k = 0; k < 4; k++) ab += tmp[k][i] * b[j][k];
149
* Multiply a matrix by a scalar.
151
* \param m Matrix to be set.
155
lib3ds_matrix_scalar(float m[4][4], float k) {
158
for (j = 0; j < 4; j++) {
159
for (i = 0; i < 4; i++) {
170
return((a)*(d) - (b)*(c));
176
float a1, float a2, float a3,
177
float b1, float b2, float b3,
178
float c1, float c2, float c3) {
180
a1*det2x2(b2, b3, c2, c3) -
181
b1*det2x2(a2, a3, c2, c3) +
182
c1*det2x2(a2, a3, b2, b3)
188
* Find determinant of a matrix.
191
lib3ds_matrix_det(float m[4][4]) {
192
float a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
211
a1 * det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) -
212
b1 * det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) +
213
c1 * det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) -
214
d1 * det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4)
220
* Invert a matrix in place.
222
* \param m Matrix to invert.
224
* \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
226
* GGemsII, K.Wu, Fast Matrix Inversion
229
lib3ds_matrix_inv(float m[4][4]) {
231
int pvt_i[4], pvt_j[4]; /* Locations of pivot elements */
232
float pvt_val; /* Value of current pivot element */
233
float hold; /* Temporary storage */
237
for (k = 0; k < 4; k++) {
238
/* Locate k'th pivot element */
239
pvt_val = m[k][k]; /* Initialize for search */
242
for (i = k; i < 4; i++) {
243
for (j = k; j < 4; j++) {
244
if (fabs(m[i][j]) > fabs(pvt_val)) {
252
/* Product of pivots, gives determinant when finished */
253
determinat *= pvt_val;
254
if (fabs(determinat) < LIB3DS_EPSILON) {
255
return(FALSE); /* Matrix is singular (zero determinant) */
258
/* "Interchange" rows (with sign change stuff) */
260
if (i != k) { /* If rows are different */
261
for (j = 0; j < 4; j++) {
268
/* "Interchange" columns */
270
if (j != k) { /* If columns are different */
271
for (i = 0; i < 4; i++) {
278
/* Divide column by minus pivot value */
279
for (i = 0; i < 4; i++) {
280
if (i != k) m[i][k] /= (-pvt_val) ;
283
/* Reduce the matrix */
284
for (i = 0; i < 4; i++) {
286
for (j = 0; j < 4; j++) {
287
if (i != k && j != k) m[i][j] += hold * m[k][j];
291
/* Divide row by pivot */
292
for (j = 0; j < 4; j++) {
293
if (j != k) m[k][j] /= pvt_val;
296
/* Replace pivot by reciprocal (at last we can touch it). */
297
m[k][k] = 1.0f / pvt_val;
300
/* That was most of the work, one final pass of row/column interchange */
302
for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/
303
i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
304
if (i != k) { /* If rows are different */
305
for (j = 0; j < 4; j++) {
312
j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */
313
if (j != k) /* If columns are different */
314
for (i = 0; i < 4; i++) {
325
* Apply a translation to a matrix.
328
lib3ds_matrix_translate(float m[4][4], float x, float y, float z) {
331
for (i = 0; i < 3; i++) {
332
m[3][i] += m[0][i] * x + m[1][i] * y + m[2][i] * z;
338
* Apply scale factors to a matrix.
341
lib3ds_matrix_scale(float m[4][4], float x, float y, float z) {
344
for (i = 0; i < 4; i++) {
353
* Apply a rotation about an arbitrary axis to a matrix.
356
lib3ds_matrix_rotate_quat(float m[4][4], float q[4]) {
357
float s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz, l;
360
l = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
361
if (fabs(l) < LIB3DS_EPSILON) {
380
R[0][0] = 1.0f - (yy + zz);
384
R[1][1] = 1.0f - (xx + zz);
388
R[2][2] = 1.0f - (xx + yy);
389
R[3][0] = R[3][1] = R[3][2] = R[0][3] = R[1][3] = R[2][3] = 0.0f;
392
lib3ds_matrix_mult(m, m, R);
397
* Apply a rotation about an arbitrary axis to a matrix.
400
lib3ds_matrix_rotate(float m[4][4], float angle, float ax, float ay, float az) {
404
lib3ds_vector_make(axis, ax, ay, az);
405
lib3ds_quat_axis_angle(q, axis, angle);
406
lib3ds_matrix_rotate_quat(m, q);
411
* Compute a camera matrix based on position, target and roll.
413
* Generates a translate/rotate matrix that maps world coordinates
414
* to camera coordinates. Resulting matrix does not include perspective
417
* \param matrix Destination matrix.
418
* \param pos Camera position
419
* \param tgt Camera target
420
* \param roll Roll angle
423
lib3ds_matrix_camera(float matrix[4][4], float pos[3], float tgt[3], float roll) {
425
float x[3], y[3], z[3];
427
lib3ds_vector_sub(y, tgt, pos);
428
lib3ds_vector_normalize(y);
430
if (y[0] != 0. || y[1] != 0) {
434
} else { /* Special case: looking straight up or down z axis */
440
lib3ds_vector_cross(x, y, z);
441
lib3ds_vector_cross(z, x, y);
442
lib3ds_vector_normalize(x);
443
lib3ds_vector_normalize(z);
445
lib3ds_matrix_identity(M);
456
lib3ds_matrix_identity(matrix);
457
lib3ds_matrix_rotate(matrix, roll, 0, 1, 0);
458
lib3ds_matrix_mult(matrix, matrix, M);
459
lib3ds_matrix_translate(matrix, -pos[0], -pos[1], -pos[2]);