1 /*
2 * The 3D Studio File Format Library
3 * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 * License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: matrix.c,v 1.14 2007/06/20 17:04:08 jeh Exp $
21 */
22 #include <lib3ds/matrix.h>
23 #include <lib3ds/quat.h>
24 #include <lib3ds/vector.h>
25 #include <string.h>
26 #include <math.h>
27
28
29 /*!
30 * \defgroup matrix Matrix Mathematics
31 */
32
33
34 /*!
35 * \typedef Lib3dsMatrix
36 * \ingroup matrix
37 */
38
39
40 /*!
41 * Clear a matrix to all zeros.
42 *
43 * \param m Matrix to be cleared.
44 *
45 * \ingroup matrix
46 */
47 void
lib3ds_matrix_zero(Lib3dsMatrix m)48 lib3ds_matrix_zero(Lib3dsMatrix m)
49 {
50 int i,j;
51
52 for (i=0; i<4; i++) {
53 for (j=0; j<4; j++) m[i][j]=0.0f;
54 }
55 }
56
57
58 /*!
59 * Set a matrix to identity.
60 *
61 * \param m Matrix to be set.
62 *
63 * \ingroup matrix
64 */
65 void
lib3ds_matrix_identity(Lib3dsMatrix m)66 lib3ds_matrix_identity(Lib3dsMatrix m)
67 {
68 int i,j;
69
70 for (i=0; i<4; i++) {
71 for (j=0; j<4; j++) m[i][j]=0.0;
72 }
73 for (i=0; i<4; i++) m[i][i]=1.0;
74 }
75
76
77 /*!
78 * Copy a matrix.
79 *
80 * \ingroup matrix
81 */
82 void
lib3ds_matrix_copy(Lib3dsMatrix dest,Lib3dsMatrix src)83 lib3ds_matrix_copy(Lib3dsMatrix dest, Lib3dsMatrix src)
84 {
85 memcpy(dest, src, sizeof(Lib3dsMatrix));
86 }
87
88
89 /*!
90 * Negate a matrix -- all elements negated.
91 *
92 * \ingroup matrix
93 */
94 void
lib3ds_matrix_neg(Lib3dsMatrix m)95 lib3ds_matrix_neg(Lib3dsMatrix m)
96 {
97 int i,j;
98
99 for (j=0; j<4; j++) {
100 for (i=0; i<4; i++) {
101 m[j][i]=-m[j][i];
102 }
103 }
104 }
105
106
107 /*!
108 * Set all matrix elements to their absolute value.
109 *
110 * \ingroup matrix
111 */
112 void
lib3ds_matrix_abs(Lib3dsMatrix m)113 lib3ds_matrix_abs(Lib3dsMatrix m)
114 {
115 int i,j;
116
117 for (j=0; j<4; j++) {
118 for (i=0; i<4; i++) {
119 m[j][i]=(Lib3dsFloat)fabs(m[j][i]);
120 }
121 }
122 }
123
124
125 /*!
126 * Transpose a matrix in place.
127 *
128 * \ingroup matrix
129 */
130 void
lib3ds_matrix_transpose(Lib3dsMatrix m)131 lib3ds_matrix_transpose(Lib3dsMatrix m)
132 {
133 int i,j;
134 Lib3dsFloat swp;
135
136 for (j=0; j<4; j++) {
137 for (i=j+1; i<4; i++) {
138 swp=m[j][i];
139 m[j][i]=m[i][j];
140 m[i][j]=swp;
141 }
142 }
143 }
144
145
146 /*!
147 * Add two matrices.
148 *
149 * \ingroup matrix
150 */
151 void
_lib3ds_matrix_add(Lib3dsMatrix m,Lib3dsMatrix a,Lib3dsMatrix b)152 _lib3ds_matrix_add(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
153 {
154 int i,j;
155
156 for (j=0; j<4; j++) {
157 for (i=0; i<4; i++) {
158 m[j][i]=a[j][i]+b[j][i];
159 }
160 }
161 }
162
163
164 /*!
165 * Subtract two matrices.
166 *
167 * \param m Result.
168 * \param a Addend.
169 * \param b Minuend.
170 *
171 * \ingroup matrix
172 */
173 void
_lib3ds_matrix_sub(Lib3dsMatrix m,Lib3dsMatrix a,Lib3dsMatrix b)174 _lib3ds_matrix_sub(Lib3dsMatrix m, Lib3dsMatrix a, Lib3dsMatrix b)
175 {
176 int i,j;
177
178 for (j=0; j<4; j++) {
179 for (i=0; i<4; i++) {
180 m[j][i]=a[j][i]-b[j][i];
181 }
182 }
183 }
184
185
186 /*!
187 * Multiplies a matrix by a second one (m = m * n).
188 *
189 * \ingroup matrix
190 */
191 void
lib3ds_matrix_mult(Lib3dsMatrix m,Lib3dsMatrix n)192 lib3ds_matrix_mult(Lib3dsMatrix m, Lib3dsMatrix n)
193 {
194 Lib3dsMatrix tmp;
195 int i,j,k;
196 Lib3dsFloat ab;
197
198 memcpy(tmp, m, sizeof(Lib3dsMatrix));
199 for (j=0; j<4; j++) {
200 for (i=0; i<4; i++) {
201 ab=0.0f;
202 for (k=0; k<4; k++) ab+=tmp[k][i]*n[j][k];
203 m[j][i]=ab;
204 }
205 }
206 }
207
208
209 /*!
210 * Multiply a matrix by a scalar.
211 *
212 * \param m Matrix to be set.
213 * \param k Scalar.
214 *
215 * \ingroup matrix
216 */
217 void
lib3ds_matrix_scalar(Lib3dsMatrix m,Lib3dsFloat k)218 lib3ds_matrix_scalar(Lib3dsMatrix m, Lib3dsFloat k)
219 {
220 int i,j;
221
222 for (j=0; j<4; j++) {
223 for (i=0; i<4; i++) {
224 m[j][i]*=k;
225 }
226 }
227 }
228
229
230 static Lib3dsFloat
det2x2(Lib3dsFloat a,Lib3dsFloat b,Lib3dsFloat c,Lib3dsFloat d)231 det2x2(
232 Lib3dsFloat a, Lib3dsFloat b,
233 Lib3dsFloat c, Lib3dsFloat d)
234 {
235 return((a)*(d)-(b)*(c));
236 }
237
238
239 static Lib3dsFloat
det3x3(Lib3dsFloat a1,Lib3dsFloat a2,Lib3dsFloat a3,Lib3dsFloat b1,Lib3dsFloat b2,Lib3dsFloat b3,Lib3dsFloat c1,Lib3dsFloat c2,Lib3dsFloat c3)240 det3x3(
241 Lib3dsFloat a1, Lib3dsFloat a2, Lib3dsFloat a3,
242 Lib3dsFloat b1, Lib3dsFloat b2, Lib3dsFloat b3,
243 Lib3dsFloat c1, Lib3dsFloat c2, Lib3dsFloat c3)
244 {
245 return(
246 a1*det2x2(b2,b3,c2,c3)-
247 b1*det2x2(a2,a3,c2,c3)+
248 c1*det2x2(a2,a3,b2,b3)
249 );
250 }
251
252
253 /*!
254 * Find determinant of a matrix.
255 *
256 * \ingroup matrix
257 */
258 Lib3dsFloat
lib3ds_matrix_det(Lib3dsMatrix m)259 lib3ds_matrix_det(Lib3dsMatrix m)
260 {
261 Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
262
263 a1 = m[0][0];
264 b1 = m[1][0];
265 c1 = m[2][0];
266 d1 = m[3][0];
267 a2 = m[0][1];
268 b2 = m[1][1];
269 c2 = m[2][1];
270 d2 = m[3][1];
271 a3 = m[0][2];
272 b3 = m[1][2];
273 c3 = m[2][2];
274 d3 = m[3][2];
275 a4 = m[0][3];
276 b4 = m[1][3];
277 c4 = m[2][3];
278 d4 = m[3][3];
279 return(
280 a1 * det3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4)-
281 b1 * det3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4)+
282 c1 * det3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4)-
283 d1 * det3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4)
284 );
285 }
286
287
288 /*!
289 * Find the adjoint of a matrix.
290 *
291 * \ingroup matrix
292 */
293 void
lib3ds_matrix_adjoint(Lib3dsMatrix m)294 lib3ds_matrix_adjoint(Lib3dsMatrix m)
295 {
296 Lib3dsFloat a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
297
298 a1 = m[0][0];
299 b1 = m[1][0];
300 c1 = m[2][0];
301 d1 = m[3][0];
302 a2 = m[0][1];
303 b2 = m[1][1];
304 c2 = m[2][1];
305 d2 = m[3][1];
306 a3 = m[0][2];
307 b3 = m[1][2];
308 c3 = m[2][2];
309 d3 = m[3][2];
310 a4 = m[0][3];
311 b4 = m[1][3];
312 c4 = m[2][3];
313 d4 = m[3][3];
314 m[0][0]= det3x3 (b2, b3, b4, c2, c3, c4, d2, d3, d4);
315 m[0][1]= -det3x3 (a2, a3, a4, c2, c3, c4, d2, d3, d4);
316 m[0][2]= det3x3 (a2, a3, a4, b2, b3, b4, d2, d3, d4);
317 m[0][3]= -det3x3 (a2, a3, a4, b2, b3, b4, c2, c3, c4);
318 m[1][0]= -det3x3 (b1, b3, b4, c1, c3, c4, d1, d3, d4);
319 m[1][1]= det3x3 (a1, a3, a4, c1, c3, c4, d1, d3, d4);
320 m[1][2]= -det3x3 (a1, a3, a4, b1, b3, b4, d1, d3, d4);
321 m[1][3]= det3x3 (a1, a3, a4, b1, b3, b4, c1, c3, c4);
322 m[2][0]= det3x3 (b1, b2, b4, c1, c2, c4, d1, d2, d4);
323 m[2][1]= -det3x3 (a1, a2, a4, c1, c2, c4, d1, d2, d4);
324 m[2][2]= det3x3 (a1, a2, a4, b1, b2, b4, d1, d2, d4);
325 m[2][3]= -det3x3 (a1, a2, a4, b1, b2, b4, c1, c2, c4);
326 m[3][0]= -det3x3 (b1, b2, b3, c1, c2, c3, d1, d2, d3);
327 m[3][1]= det3x3 (a1, a2, a3, c1, c2, c3, d1, d2, d3);
328 m[3][2]= -det3x3 (a1, a2, a3, b1, b2, b3, d1, d2, d3);
329 m[3][3]= det3x3 (a1, a2, a3, b1, b2, b3, c1, c2, c3);
330 }
331
332
333 /*!
334 * Invert a matrix in place.
335 *
336 * \param m Matrix to invert.
337 *
338 * \return LIB3DS_TRUE on success, LIB3DS_FALSE on failure.
339 * \ingroup matrix
340 *
341 * GGemsII, K.Wu, Fast Matrix Inversion
342 */
343 Lib3dsBool
lib3ds_matrix_inv(Lib3dsMatrix m)344 lib3ds_matrix_inv(Lib3dsMatrix m)
345 {
346 int i,j,k;
347 int pvt_i[4], pvt_j[4]; /* Locations of pivot elements */
348 Lib3dsFloat pvt_val; /* Value of current pivot element */
349 Lib3dsFloat hold; /* Temporary storage */
350 Lib3dsFloat determinat;
351
352 determinat = 1.0f;
353 for (k=0; k<4; k++) {
354 /* Locate k'th pivot element */
355 pvt_val=m[k][k]; /* Initialize for search */
356 pvt_i[k]=k;
357 pvt_j[k]=k;
358 for (i=k; i<4; i++) {
359 for (j=k; j<4; j++) {
360 if (fabs(m[i][j]) > fabs(pvt_val)) {
361 pvt_i[k]=i;
362 pvt_j[k]=j;
363 pvt_val=m[i][j];
364 }
365 }
366 }
367
368 /* Product of pivots, gives determinant when finished */
369 determinat*=pvt_val;
370 if (fabs(determinat)<LIB3DS_EPSILON) {
371 return(LIB3DS_FALSE); /* Matrix is singular (zero determinant) */
372 }
373
374 /* "Interchange" rows (with sign change stuff) */
375 i=pvt_i[k];
376 if (i!=k) { /* If rows are different */
377 for (j=0; j<4; j++) {
378 hold=-m[k][j];
379 m[k][j]=m[i][j];
380 m[i][j]=hold;
381 }
382 }
383
384 /* "Interchange" columns */
385 j=pvt_j[k];
386 if (j!=k) { /* If columns are different */
387 for (i=0; i<4; i++) {
388 hold=-m[i][k];
389 m[i][k]=m[i][j];
390 m[i][j]=hold;
391 }
392 }
393
394 /* Divide column by minus pivot value */
395 for (i=0; i<4; i++) {
396 if (i!=k) m[i][k]/=( -pvt_val) ;
397 }
398
399 /* Reduce the matrix */
400 for (i=0; i<4; i++) {
401 hold = m[i][k];
402 for (j=0; j<4; j++) {
403 if (i!=k && j!=k) m[i][j]+=hold*m[k][j];
404 }
405 }
406
407 /* Divide row by pivot */
408 for (j=0; j<4; j++) {
409 if (j!=k) m[k][j]/=pvt_val;
410 }
411
412 /* Replace pivot by reciprocal (at last we can touch it). */
413 m[k][k] = 1.0f/pvt_val;
414 }
415
416 /* That was most of the work, one final pass of row/column interchange */
417 /* to finish */
418 for (k=4-2; k>=0; k--) { /* Don't need to work with 1 by 1 corner*/
419 i=pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */
420 if (i!=k) { /* If rows are different */
421 for(j=0; j<4; j++) {
422 hold = m[k][j];
423 m[k][j]=-m[i][j];
424 m[i][j]=hold;
425 }
426 }
427
428 j=pvt_i[k]; /* Columns to swap correspond to pivot ROW */
429 if (j!=k) /* If columns are different */
430 for (i=0; i<4; i++) {
431 hold=m[i][k];
432 m[i][k]=-m[i][j];
433 m[i][j]=hold;
434 }
435 }
436 return(LIB3DS_TRUE);
437 }
438
439
440 /*!
441 * Apply a translation to a matrix.
442 *
443 * \ingroup matrix
444 */
445 void
lib3ds_matrix_translate_xyz(Lib3dsMatrix m,Lib3dsFloat x,Lib3dsFloat y,Lib3dsFloat z)446 lib3ds_matrix_translate_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z)
447 {
448 int i;
449
450 for (i=0; i<3; i++) {
451 m[3][i]+= m[0][i]*x + m[1][i]*y + m[2][i]*z;
452 }
453 }
454
455
456 /*!
457 * Apply a translation to a matrix.
458 *
459 * \ingroup matrix
460 */
461 void
lib3ds_matrix_translate(Lib3dsMatrix m,Lib3dsVector t)462 lib3ds_matrix_translate(Lib3dsMatrix m, Lib3dsVector t)
463 {
464 int i;
465
466 for (i=0; i<3; i++) {
467 m[3][i]+= m[0][i]*t[0] + m[1][i]*t[1] + m[2][i]*t[2];
468 }
469 }
470
471
472 /*!
473 * Apply scale factors to a matrix.
474 *
475 * \ingroup matrix
476 */
477 void
lib3ds_matrix_scale_xyz(Lib3dsMatrix m,Lib3dsFloat x,Lib3dsFloat y,Lib3dsFloat z)478 lib3ds_matrix_scale_xyz(Lib3dsMatrix m, Lib3dsFloat x, Lib3dsFloat y, Lib3dsFloat z)
479 {
480 int i;
481
482 for (i=0; i<4; i++) {
483 m[0][i]*=x;
484 m[1][i]*=y;
485 m[2][i]*=z;
486 }
487 }
488
489
490 /*!
491 * Apply scale factors to a matrix.
492 *
493 * \ingroup matrix
494 */
495 void
lib3ds_matrix_scale(Lib3dsMatrix m,Lib3dsVector s)496 lib3ds_matrix_scale(Lib3dsMatrix m, Lib3dsVector s)
497 {
498 int i;
499
500 for (i=0; i<4; i++) {
501 m[0][i]*=s[0];
502 m[1][i]*=s[1];
503 m[2][i]*=s[2];
504 }
505 }
506
507
508 /*!
509 * Apply a rotation about the x axis to a matrix.
510 *
511 * \ingroup matrix
512 */
513 void
lib3ds_matrix_rotate_x(Lib3dsMatrix m,Lib3dsFloat phi)514 lib3ds_matrix_rotate_x(Lib3dsMatrix m, Lib3dsFloat phi)
515 {
516 Lib3dsFloat SinPhi,CosPhi;
517 Lib3dsFloat a1[4],a2[4];
518
519 SinPhi=(Lib3dsFloat)sin(phi);
520 CosPhi=(Lib3dsFloat)cos(phi);
521 memcpy(a1,m[1],4*sizeof(Lib3dsFloat));
522 memcpy(a2,m[2],4*sizeof(Lib3dsFloat));
523 m[1][0]=CosPhi*a1[0]+SinPhi*a2[0];
524 m[1][1]=CosPhi*a1[1]+SinPhi*a2[1];
525 m[1][2]=CosPhi*a1[2]+SinPhi*a2[2];
526 m[1][3]=CosPhi*a1[3]+SinPhi*a2[3];
527 m[2][0]=-SinPhi*a1[0]+CosPhi*a2[0];
528 m[2][1]=-SinPhi*a1[1]+CosPhi*a2[1];
529 m[2][2]=-SinPhi*a1[2]+CosPhi*a2[2];
530 m[2][3]=-SinPhi*a1[3]+CosPhi*a2[3];
531 }
532
533
534 /*!
535 * Apply a rotation about the y axis to a matrix.
536 *
537 * \ingroup matrix
538 */
539 void
lib3ds_matrix_rotate_y(Lib3dsMatrix m,Lib3dsFloat phi)540 lib3ds_matrix_rotate_y(Lib3dsMatrix m, Lib3dsFloat phi)
541 {
542 Lib3dsFloat SinPhi,CosPhi;
543 Lib3dsFloat a0[4],a2[4];
544
545 SinPhi=(Lib3dsFloat)sin(phi);
546 CosPhi=(Lib3dsFloat)cos(phi);
547 memcpy(a0,m[0],4*sizeof(Lib3dsFloat));
548 memcpy(a2,m[2],4*sizeof(Lib3dsFloat));
549 m[0][0]=CosPhi*a0[0]-SinPhi*a2[0];
550 m[0][1]=CosPhi*a0[1]-SinPhi*a2[1];
551 m[0][2]=CosPhi*a0[2]-SinPhi*a2[2];
552 m[0][3]=CosPhi*a0[3]-SinPhi*a2[3];
553 m[2][0]=SinPhi*a0[0]+CosPhi*a2[0];
554 m[2][1]=SinPhi*a0[1]+CosPhi*a2[1];
555 m[2][2]=SinPhi*a0[2]+CosPhi*a2[2];
556 m[2][3]=SinPhi*a0[3]+CosPhi*a2[3];
557 }
558
559
560 /*!
561 * Apply a rotation about the z axis to a matrix.
562 *
563 * \ingroup matrix
564 */
565 void
lib3ds_matrix_rotate_z(Lib3dsMatrix m,Lib3dsFloat phi)566 lib3ds_matrix_rotate_z(Lib3dsMatrix m, Lib3dsFloat phi)
567 {
568 Lib3dsFloat SinPhi,CosPhi;
569 Lib3dsFloat a0[4],a1[4];
570
571 SinPhi=(Lib3dsFloat)sin(phi);
572 CosPhi=(Lib3dsFloat)cos(phi);
573 memcpy(a0,m[0],4*sizeof(Lib3dsFloat));
574 memcpy(a1,m[1],4*sizeof(Lib3dsFloat));
575 m[0][0]=CosPhi*a0[0]+SinPhi*a1[0];
576 m[0][1]=CosPhi*a0[1]+SinPhi*a1[1];
577 m[0][2]=CosPhi*a0[2]+SinPhi*a1[2];
578 m[0][3]=CosPhi*a0[3]+SinPhi*a1[3];
579 m[1][0]=-SinPhi*a0[0]+CosPhi*a1[0];
580 m[1][1]=-SinPhi*a0[1]+CosPhi*a1[1];
581 m[1][2]=-SinPhi*a0[2]+CosPhi*a1[2];
582 m[1][3]=-SinPhi*a0[3]+CosPhi*a1[3];
583 }
584
585
586 /*!
587 * Apply a rotation about an arbitrary axis to a matrix.
588 *
589 * \ingroup matrix
590 */
591 void
lib3ds_matrix_rotate(Lib3dsMatrix m,Lib3dsQuat q)592 lib3ds_matrix_rotate(Lib3dsMatrix m, Lib3dsQuat q)
593 {
594 Lib3dsFloat s,xs,ys,zs,wx,wy,wz,xx,xy,xz,yy,yz,zz,l;
595 Lib3dsMatrix R;
596
597 l=q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3];
598 if (fabs(l)<LIB3DS_EPSILON) {
599 s=1.0f;
600 }
601 else {
602 s=2.0f/l;
603 }
604
605 xs = q[0] * s; ys = q[1] * s; zs = q[2] * s;
606 wx = q[3] * xs; wy = q[3] * ys; wz = q[3] * zs;
607 xx = q[0] * xs; xy = q[0] * ys; xz = q[0] * zs;
608 yy = q[1] * ys; yz = q[1] * zs; zz = q[2] * zs;
609
610 R[0][0]=1.0f - (yy +zz);
611 R[1][0]=xy - wz;
612 R[2][0]=xz + wy;
613 R[0][1]=xy + wz;
614 R[1][1]=1.0f - (xx +zz);
615 R[2][1]=yz - wx;
616 R[0][2]=xz - wy;
617 R[1][2]=yz + wx;
618 R[2][2]=1.0f - (xx + yy);
619 R[3][0]=R[3][1]=R[3][2]=R[0][3]=R[1][3]=R[2][3]=0.0f;
620 R[3][3]=1.0f;
621
622 lib3ds_matrix_mult(m,R);
623 }
624
625
626 /*!
627 * Apply a rotation about an arbitrary axis to a matrix.
628 *
629 * \ingroup matrix
630 */
631 void
lib3ds_matrix_rotate_axis(Lib3dsMatrix m,Lib3dsVector axis,Lib3dsFloat angle)632 lib3ds_matrix_rotate_axis(Lib3dsMatrix m, Lib3dsVector axis, Lib3dsFloat angle)
633 {
634 Lib3dsQuat q;
635
636 lib3ds_quat_axis_angle(q,axis,angle);
637 lib3ds_matrix_rotate(m,q);
638 }
639
640
641 /*!
642 * Compute a camera matrix based on position, target and roll.
643 *
644 * Generates a translate/rotate matrix that maps world coordinates
645 * to camera coordinates. Resulting matrix does not include perspective
646 * transform.
647 *
648 * \param matrix Destination matrix.
649 * \param pos Camera position
650 * \param tgt Camera target
651 * \param roll Roll angle
652 *
653 * \ingroup matrix
654 */
655 void
lib3ds_matrix_camera(Lib3dsMatrix matrix,Lib3dsVector pos,Lib3dsVector tgt,Lib3dsFloat roll)656 lib3ds_matrix_camera(Lib3dsMatrix matrix, Lib3dsVector pos,
657 Lib3dsVector tgt, Lib3dsFloat roll)
658 {
659 Lib3dsMatrix M;
660 Lib3dsVector x, y, z;
661
662 lib3ds_vector_sub(y, tgt, pos);
663 lib3ds_vector_normalize(y);
664
665 if (y[0] != 0. || y[1] != 0) {
666 z[0] = 0;
667 z[1] = 0;
668 z[2] = 1.0;
669 }
670 else { /* Special case: looking straight up or down z axis */
671 z[0] = -1.0;
672 z[1] = 0;
673 z[2] = 0;
674 }
675
676 lib3ds_vector_cross(x, y, z);
677 lib3ds_vector_cross(z, x, y);
678 lib3ds_vector_normalize(x);
679 lib3ds_vector_normalize(z);
680
681 lib3ds_matrix_identity(M);
682 M[0][0] = x[0];
683 M[1][0] = x[1];
684 M[2][0] = x[2];
685 M[0][1] = y[0];
686 M[1][1] = y[1];
687 M[2][1] = y[2];
688 M[0][2] = z[0];
689 M[1][2] = z[1];
690 M[2][2] = z[2];
691
692 lib3ds_matrix_identity(matrix);
693 lib3ds_matrix_rotate_y(matrix, roll);
694 lib3ds_matrix_mult(matrix, M);
695 lib3ds_matrix_translate_xyz(matrix, -pos[0],-pos[1],-pos[2]);
696 }
697
698
699 /*!
700 * \ingroup matrix
701 */
702 void
lib3ds_matrix_dump(Lib3dsMatrix matrix)703 lib3ds_matrix_dump(Lib3dsMatrix matrix)
704 {
705 int i,j;
706
707 for (i=0; i<4; ++i) {
708 for (j=0; j<4; ++j) {
709 printf("%f ", matrix[j][i]);
710 }
711 printf("\n");
712 }
713 }
714
715
716
717
718
719