FreeWRL/FreeX3D  3.0.0
LinearAlgebra.c
1 /*
2 
3 
4 ???
5 
6 */
7 
8 /****************************************************************************
9  This file is part of the FreeWRL/FreeX3D Distribution.
10 
11  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12 
13  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14  it under the terms of the GNU Lesser Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25 ****************************************************************************/
26 
27 #include <math.h>
28 
29 #include <config.h>
30 #include <system.h>
31 #include <display.h>
32 #include <internal.h>
33 
34 #include <libFreeWRL.h>
35 
36 #include "../vrml_parser/Structs.h"
37 #include "../main/headers.h"
38 
39 #include "LinearAlgebra.h"
40 
41 #define DJ_KEEP_COMPILER_WARNING 0
42 double signd(double val){
43  return val < 0.0 ? -1.0 : val > 0.0 ? 1.0 : 0;
44 }
45 double * vecsignd(double *b, double *a){
46  int i;
47  for (i = 0; i<3; i++) b[i] = signd(a[i]);
48  return b;
49 }
50 double * vecmuld(double *c, double *a, double *b){
51  int i;
52  for(i=0;i<3;i++)
53  c[i] = a[i]*b[i];
54  return c;
55 }
56 double * vecsetd(double *b, double x, double y, double z){
57  b[0] = x, b[1] = y; b[2] = z;
58  return b;
59 }
60 float *double2float(float *b, const double *a, int n){
61  int i;
62  for(i=0;i<n;i++) b[i] = (float)a[i];
63  return b;
64 }
65 double *float2double(double *b, float *a, int n){
66  int i;
67  for(i=0;i<n;i++) b[i] = (double)a[i];
68  return b;
69 }
70 double * vecadd2d(double *c, double *a, double *b){
71  c[0] = a[0] + b[0];
72  c[1] = a[1] + b[1];
73  return c;
74 }
75 
76 double *vecdif2d(double *c, double* a, double *b){
77  c[0] = a[0] - b[0];
78  c[1] = a[1] - b[1];
79  return c;
80 }
81 double veclength2d( double *p ){
82  return sqrt(p[0]*p[0] + p[1]*p[1]);
83 }
84 double vecdot2d(double *a, double *b){
85  return a[0]*b[0] + a[1]*b[1];
86 }
87 
88 double* vecscale2d(double* r, double* v, double s){
89  r[0] = v[0] * s;
90  r[1] = v[1] * s;
91  return r;
92 }
93 
94 double vecnormal2d(double *r, double *v){
95  double ret = sqrt(vecdot2d(v,v));
96  /* if(ret == 0.) return 0.; */
97  if (APPROX(ret, 0)) return 0.;
98  vecscale2d(r,v,1./ret);
99  return ret;
100 }
101 
102 float * vecadd2f(float *c, float *a, float *b){
103  c[0] = a[0] + b[0];
104  c[1] = a[1] + b[1];
105  return c;
106 }
107 
108 float *vecdif2f(float *c, float* a, float *b){
109  c[0] = a[0] - b[0];
110  c[1] = a[1] - b[1];
111  return c;
112 }
113 float veclength2f( float *p ){
114  return (float) sqrt(p[0]*p[0] + p[1]*p[1]);
115 }
116 float vecdot2f(float *a, float *b){
117  return a[0]*b[0] + a[1]*b[1];
118 }
119 
120 float* vecscale2f(float* r, float* v, float s){
121  r[0] = v[0] * s;
122  r[1] = v[1] * s;
123  return r;
124 }
125 
126 float vecnormal2f(float *r, float *v){
127  float ret = (float)sqrt(vecdot2f(v,v));
128  /* if(ret == 0.) return 0.; */
129  if (APPROX(ret, 0)) return 0.0f;
130  vecscale2f(r,v,1.0f/ret);
131  return ret;
132 }
133 
134 
135 
136 
137 /* Altenate implemetations available, should merge them eventually */
138 double *vecaddd(double *c, double* a, double *b)
139 {
140  c[0] = a[0] + b[0];
141  c[1] = a[1] + b[1];
142  c[2] = a[2] + b[2];
143  return c;
144 }
145 float *vecadd3f(float *c, float *a, float *b)
146 {
147  c[0] = a[0] + b[0];
148  c[1] = a[1] + b[1];
149  c[2] = a[2] + b[2];
150  return c;
151 }
152 double *vecdifd(double *c, double* a, double *b)
153 {
154  c[0] = a[0] - b[0];
155  c[1] = a[1] - b[1];
156  c[2] = a[2] - b[2];
157  return c;
158 }
159 float *vecdif3f(float *c, float *a, float *b)
160 {
161  c[0] = a[0] - b[0];
162  c[1] = a[1] - b[1];
163  c[2] = a[2] - b[2];
164  return c;
165 }
166 double *veccopyd(double *c, double *a)
167 {
168  c[0] = a[0];
169  c[1] = a[1];
170  c[2] = a[2];
171  return c;
172 }
173 double *vecnegated(double *b, double *a)
174 {
175  b[0] = -a[0];
176  b[1] = -a[1];
177  b[2] = -a[2];
178  return b;
179 }
180 float *veccopy3f(float *b, float *a)
181 {
182  b[0] = a[0];
183  b[1] = a[1];
184  b[2] = a[2];
185  return b;
186 }
187 int vecsame2f(float *b, float *a){
188  return a[0] == b[0] && a[1] == b[1] ? TRUE : FALSE;
189 }
190 float *veccopy2f(float *b, float *a)
191 {
192  b[0] = a[0];
193  b[1] = a[1];
194  return b;
195 }
196 float *vecset2f(float *b, float x, float y)
197 {
198  b[0] = x; b[1] = y;
199  return b;
200 }
201 double * veccrossd(double *c, double *a, double *b)
202 {
203  double aa[3], bb[3];
204  veccopyd(aa,a);
205  veccopyd(bb,b);
206  c[0] = aa[1] * bb[2] - aa[2] * bb[1];
207  c[1] = aa[2] * bb[0] - aa[0] * bb[2];
208  c[2] = aa[0] * bb[1] - aa[1] * bb[0];
209  return c;
210 }
211 double veclengthd( double *p )
212 {
213  return sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
214 }
215 double vecdotd(double *a, double *b)
216 {
217  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
218 }
219 double* vecscaled(double* r, double* v, double s)
220 {
221  r[0] = v[0] * s;
222  r[1] = v[1] * s;
223  r[2] = v[2] * s;
224  return r;
225 }
226 /* returns vector length, too */
227 double vecnormald(double *r, double *v)
228 {
229  double ret = sqrt(vecdotd(v,v));
230  /* if(ret == 0.) return 0.; */
231  if (APPROX(ret, 0)) return 0.;
232  vecscaled(r,v,1./ret);
233  return ret;
234 }
235 
236 void veccross(struct point_XYZ *c, struct point_XYZ a, struct point_XYZ b)
237 {
238  c->x = a.y * b.z - a.z * b.y;
239  c->y = a.z * b.x - a.x * b.z;
240  c->z = a.x * b.y - a.y * b.x;
241 }
242 float *veccross3f(float *c, float *a, float *b)
243 {
244  /*FLOPs 6 float*/
245  c[0] = a[1]*b[2] - a[2]*b[1];
246  c[1] = a[2]*b[0] - a[0]*b[2];
247  c[2] = a[0]*b[1] - a[1]*b[0];
248  return c;
249 }
250 float veclength( struct point_XYZ p )
251 {
252  return (float) sqrt(p.x*p.x + p.y*p.y + p.z*p.z);
253 }
254 float vecdot3f( float *a, float *b )
255 {
256  /*FLOPs 3 float */
257  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
258 }
259 float vecdot4f( float *a, float *b )
260 {
261  return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + + a[3]*b[3];
262 }
263 float *vecset3f(float *b, float x, float y, float z)
264 {
265  b[0] = x; b[1] = y; b[2] = z;
266  return b;
267 }
268 float veclength3f(float *a){
269  return (float)sqrt(vecdot3f(a, a));
270 }
271 
272 double vecangle(struct point_XYZ* V1, struct point_XYZ* V2) {
273  return acos((V1->x*V2->x + V1->y*V2->y +V1->z*V2->z) /
274  sqrt( (V1->x*V1->x + V1->y*V1->y + V1->z*V1->z)*(V2->x*V2->x + V2->y*V2->y + V2->z*V2->z) ) );
275 };
276 
277 float *veccopy4f(float *b, float *a)
278 {
279  b[0] = a[0];
280  b[1] = a[1];
281  b[2] = a[2];
282  b[3] = a[3];
283  return b;
284 }
285 
286 float calc_angle_between_two_vectors(struct point_XYZ a, struct point_XYZ b)
287 {
288  float length_a, length_b, scalar, temp;
289  scalar = (float) calc_vector_scalar_product(a,b);
290  length_a = calc_vector_length(a);
291  length_b = calc_vector_length(b);
292 
293  /* printf("scalar: %f length_a: %f length_b: %f \n", scalar, length_a, length_b);*/
294 
295  /* if (scalar == 0) */
296  if (APPROX(scalar, 0)) {
297  return (float) (M_PI/2.0);
298  }
299 
300  if ( (length_a <= 0) || (length_b <= 0)){
301  printf("Divide by 0 in calc_angle_between_two_vectors(): No can do! \n");
302  return 0;
303  }
304 
305  temp = scalar /(length_a * length_b);
306  /* printf("temp: %f", temp);*/
307 
308  /*acos() appears to be unable to handle 1 and -1 */
309  /* fixed to handle border case where temp <=-1.0 for 0.39 JAS */
310  if ((temp >= 1) || (temp <= -1)){
311  if (temp < 0.0f) return 3.141526f;
312  return 0.0f;
313  }
314  return (float) acos(temp);
315 }
316 
317 int vecsame3f(float *a, float *b){
318  int i,isame = TRUE;
319  for(i=0;i<3;i++)
320  if(a[i] != b[i]) isame = FALSE;
321  return isame;
322 }
323 int vecsame4f(float *a, float *b){
324  int i,isame = TRUE;
325  for(i=0;i<4;i++)
326  if(a[i] != b[i]) isame = FALSE;
327  return isame;
328 }
329 /* returns vector length, too */
330 GLDOUBLE vecnormal(struct point_XYZ*r, struct point_XYZ* v)
331 {
332  GLDOUBLE ret = sqrt(vecdot(v,v));
333  /* if(ret == 0.) return 0.; */
334  if (APPROX(ret, 0)) return 0.;
335  vecscale(r,v,1./ret);
336  return ret;
337 }
338 float vecnormsquared3f(float *a){
339  return a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
340 }
341 float *vecscale3f(float *b, float *a, float scale){
342  b[0] = a[0] * scale;
343  b[1] = a[1] * scale;
344  b[2] = a[2] * scale;
345  return b;
346 }
347 float *vecscale4f(float *b, float *a, float scale){
348  b[0] = a[0] * scale;
349  b[1] = a[1] * scale;
350  b[2] = a[2] * scale;
351  b[3] = a[3] * scale;
352  return b;
353 }
354 float *vecmult3f(float *c, float *a, float *b){
355  /* c[i] = a[i]*b[i] */
356  int i=0;
357  for(;i<3;i++) c[i] = a[i]*b[i];
358  return c;
359 }
360 float *vecmult2f(float *c, float *a, float *b){
361  /* c[i] = a[i]*b[i] */
362  int i=0;
363  for(;i<2;i++) c[i] = a[i]*b[i];
364  return c;
365 }
366 
367 float *vecnormalize3f(float *b, float *a)
368 {
369  float norm = veclength3f(a);
370  if (APPROX(norm, 0.0f)){
371  b[0] = 1.0f; b[1] = 0.0f; b[2] = 0.0f;
372  }else{
373  vecscale3f(b, a, 1.0f / norm);
374  }
375  return b;
376 }
377 /*will add functions here as needed. */
378 
379 GLDOUBLE det3x3(GLDOUBLE* data)
380 {
381  return -data[1]*data[10]*data[4] +data[0]*data[10]*data[5] -data[2]*data[5]*data[8] +data[1]*data[6]*data[8] +data[2]*data[4]*data[9] -data[0]*data[6]*data[9];
382 }
383 float det3f(float *a, float *b, float *c)
384 {
385  /*FLOPs 9 float: dot 3, cross 6 */
386  float temp[3];
387  return vecdot3f(a,veccross3f(temp,b, c));
388 }
389 
390 struct point_XYZ* transform(struct point_XYZ* r, const struct point_XYZ* a, const GLDOUBLE* b)
391 {
392  //FLOPs 9 double
393  // r = a x b
394  struct point_XYZ tmp; /* JAS*/
395 
396  if(r != a) { /*protect from self-assignments */
397  r->x = b[0]*a->x +b[4]*a->y +b[8]*a->z +b[12];
398  r->y = b[1]*a->x +b[5]*a->y +b[9]*a->z +b[13];
399  r->z = b[2]*a->x +b[6]*a->y +b[10]*a->z +b[14];
400  } else {
401  /* JAS was - struct point_XYZ tmp = {a->x,a->y,a->z};*/
402  tmp.x = a->x; tmp.y = a->y; tmp.z = a->z;
403  r->x = b[0]*tmp.x +b[4]*tmp.y +b[8]*tmp.z +b[12];
404  r->y = b[1]*tmp.x +b[5]*tmp.y +b[9]*tmp.z +b[13];
405  r->z = b[2]*tmp.x +b[6]*tmp.y +b[10]*tmp.z +b[14];
406  }
407  return r;
408 }
409 GLDOUBLE* transformUPPER3X3d(double *r,double *a, const GLDOUBLE* b){
410  double tmp[3];
411  veccopyd(tmp,a);
412  r[0] = b[0]*tmp[0] +b[4]*tmp[1] +b[8]*tmp[2];
413  r[1] = b[1]*tmp[0] +b[5]*tmp[1] +b[9]*tmp[2];
414  r[2] = b[2]*tmp[0] +b[6]*tmp[1] +b[10]*tmp[2];
415  return r;
416 }
417 struct point_XYZ* transformAFFINE(struct point_XYZ* r, const struct point_XYZ* a, const GLDOUBLE* b){
418  //FLOPs 9 double
419  // r = a x b
420  return transform(r,a,b);
421 }
422 GLDOUBLE* pointxyz2double(double* r, struct point_XYZ *p){
423  r[0] = p->x; r[1] = p->y; r[2] = p->z;
424  return r;
425 }
426 struct point_XYZ* double2pointxyz(struct point_XYZ* r, double* p){
427  r->x = p[0]; r->y = p[1]; r->z = p[2];
428  return r;
429 }
430 double *transformAFFINEd(double *r, double *a, const GLDOUBLE* mat){
431  // r = a x mat
432  struct point_XYZ pa, pr;
433  double2pointxyz(&pa,a);
434  transformAFFINE(&pr,&pa,mat);
435  pointxyz2double(r,&pr);
436  return r;
437 }
438 double *transformFULL4d(double *r, double *a, double *mat){
439  //same as __gluMultMatrixVecd elsewhere
440  int i;
441  for (i=0; i<4; i++) {
442  r[i] =
443  a[0] * mat[0*4+i] +
444  a[1] * mat[1*4+i] +
445  a[2] * mat[2*4+i] +
446  a[3] * mat[3*4+i];
447  }
448  return r;
449 }
450 float* transformf(float* r, const float* a, const GLDOUBLE* b)
451 {
452  //r = a x b
453  float tmp[3]; /* JAS*/
454 
455  if(r != a) { /*protect from self-assignments */
456  r[0] = (float) (b[0]*a[0] +b[4]*a[1] +b[8]*a[2] +b[12]);
457  r[1] = (float) (b[1]*a[0] +b[5]*a[1] +b[9]*a[2] +b[13]);
458  r[2] = (float) (b[2]*a[0] +b[6]*a[1] +b[10]*a[2] +b[14]);
459  } else {
460  tmp[0] =a[0]; tmp[1] = a[1]; tmp[2] = a[2]; /* JAS*/
461  r[0] = (float) (b[0]*tmp[0] +b[4]*tmp[1] +b[8]*tmp[2] +b[12]);
462  r[1] = (float) (b[1]*tmp[0] +b[5]*tmp[1] +b[9]*tmp[2] +b[13]);
463  r[2] = (float) (b[2]*tmp[0] +b[6]*tmp[1] +b[10]*tmp[2] +b[14]);
464  }
465  return r;
466 }
467 float* matmultvec4f(float* r4, float *mat4, float* a4 )
468 {
469  int i,j;
470  float t4[4], *b[4];
471  memcpy(t4,a4,4*sizeof(float));
472  for(i=0;i<4;i++){
473  r4[i] = 0.0f;
474  b[i] = &mat4[i*4];
475  for(j=0;j<4;j++)
476  r4[i] += b[i][j]*t4[j];
477  }
478  return r4;
479 }
480 float* vecmultmat4f_broken(float* r4, float* a4, float *mat4 )
481 {
482  int i,j;
483  float t4[4], *b[4];
484  memcpy(t4,a4,4*sizeof(float));
485  for(i=0;i<4;i++){
486  r4[i] = 0.0f;
487  b[i] = &mat4[i*4];
488  for(j=0;j<4;j++)
489  r4[i] += t4[j]*b[j][i];
490  }
491  return r4;
492 }
493 float* vecmultmat4f(float* r4, float* a4, float *mat4 )
494 {
495  int i,j;
496  float t4[4], *b;
497  memcpy(t4,a4,4*sizeof(float));
498  for(i=0;i<4;i++){
499  r4[i] = 0.0f;
500  b = &mat4[i*4];
501  for(j=0;j<4;j++)
502  r4[i] += t4[j]*b[j];
503  }
504  return r4;
505 }
506 float* matmultvec3f(float* r3, float *mat3, float* a3 )
507 {
508  int i,j;
509  float t3[3], *b[3];
510  memcpy(t3,a3,3*sizeof(float));
511  for(i=0;i<3;i++){
512  r3[i] = 0.0f;
513  b[i] = &mat3[i*3];
514  for(j=0;j<3;j++)
515  r3[i] += b[i][j]*t3[j];
516  }
517  return r3;
518 }
519 float* vecmultmat3f(float* r3, float* a3, float *mat3 )
520 {
521  int i,j;
522  float t3[3], *b[3];
523  memcpy(t3,a3,3*sizeof(float));
524  for(i=0;i<3;i++){
525  r3[i] = 0.0f;
526  b[i] = &mat3[i*4];
527  for(j=0;j<3;j++)
528  r3[i] += t3[j]*b[j][i];
529  }
530 
531  return r3;
532 }
533 
534 /*transform point, but ignores translation.*/
535 struct point_XYZ* transform3x3(struct point_XYZ* r, const struct point_XYZ* a, const GLDOUBLE* b)
536 {
537  struct point_XYZ tmp;
538 
539  if(r != a) { /*protect from self-assignments */
540  r->x = b[0]*a->x +b[4]*a->y +b[8]*a->z;
541  r->y = b[1]*a->x +b[5]*a->y +b[9]*a->z;
542  r->z = b[2]*a->x +b[6]*a->y +b[10]*a->z;
543  } else {
544  /* JAS struct point_XYZ tmp = {a->x,a->y,a->z};*/
545  tmp.x = a->x; tmp.y = a->y; tmp.z = a->z;
546  r->x = b[0]*tmp.x +b[4]*tmp.y +b[8]*tmp.z;
547  r->y = b[1]*tmp.x +b[5]*tmp.y +b[9]*tmp.z;
548  r->z = b[2]*tmp.x +b[6]*tmp.y +b[10]*tmp.z;
549  }
550  return r;
551 }
552 
553 struct point_XYZ* vecscale(struct point_XYZ* r, struct point_XYZ* v, GLDOUBLE s)
554 {
555  r->x = v->x * s;
556  r->y = v->y * s;
557  r->z = v->z * s;
558  return r;
559 }
560 double vecdot(struct point_XYZ* a, struct point_XYZ* b)
561 {
562  return (a->x*b->x) + (a->y*b->y) + (a->z*b->z);
563 }
564 
565 
566 /* returns 0 if p1 is closest, 1 if p2 is closest, and a fraction if the closest point is in between */
567 /* To get the closest point, use pclose = retval*p1 + (1-retval)p2; */
568 /* y1 must be smaller than y2 */
569 /*double closest_point_of_segment_to_y_axis_segment(double y1, double y2, struct point_XYZ p1, struct point_XYZ p2) {
570  double imin = (y1- p1.y) / (p2.y - p1.y);
571  double imax = (y2- p1.y) / (p2.y - p1.y);
572 
573  double x21 = (p2.x - p1.x);
574  double z21 = (p2.z - p1.z);
575  double i = (p2.x * x21 + p2.z * z21) /
576  ( x21*x21 + z21*z21 );
577  return max(min(i,imax),imin);
578 
579  }*/
580 
581 double closest_point_of_segment_to_y_axis_segment(double y1, double y2, struct point_XYZ p1, struct point_XYZ p2) {
582  /*cylinder constraints (to be between y1 and y2) */
583  double imin = (y1- p1.y) / (p2.y - p1.y);
584  double imax = (y2- p1.y) / (p2.y - p1.y);
585 
586  /*the equation */
587  double x12 = (p1.x - p2.x);
588  double z12 = (p1.z - p2.z);
589  double q = ( x12*x12 + z12*z12 );
590 
591  /* double i = ((q == 0.) ? 0 : (p1.x * x12 + p1.z * z12) / q); */
592  double i = ((APPROX(q, 0)) ? 0 : (p1.x * x12 + p1.z * z12) / q);
593 
594  printf("imin=%f, imax=%f => ",imin,imax);
595 
596  if(imin > imax) {
597  double tmp = imax;
598  imax = imin;
599  imin = tmp;
600  }
601 
602  /*clamp constraints to segment*/
603  if(imin < 0) imin = 0;
604  if(imax > 1) imax = 1;
605 
606  printf("imin=%f, imax=%f\n",imin,imax);
607 
608  /*clamp result to constraints */
609  if(i < imin) i = imin;
610  if(i > imax) i = imax;
611  return i;
612 
613 }
614 BOOL line_intersect_line_3f(float *p1, float *v1, float *p2, float *v2, float *t, float *s, float *x1, float *x2)
615 {
616  //from Graphics Gems I, p.304 http://inis.jinr.ru/sl/vol1/CMC/Graphics_Gems_1,ed_A.Glassner.pdf
617  //L1: P1 + V1*t
618  //L2: P2 + V2*s
619  //t and s are at the footpoint/point of closest passing
620  //t = det(P2-P1,V2,V1xV2) / |V1 x V2|**2
621  //s = det(P2-P1,V1,V1xV2) / |V1 x V2|**2
622  float t1[3], cross[3]; //temp intermediate variables
623  float crosslength2, ss, tt;
624  veccross3f(cross, v1, v2);
625  crosslength2 = vecnormsquared3f(cross);
626  if (APPROX(crosslength2, 0.0f)) return FALSE; //lines are parallel, no intersection
627  crosslength2 = 1.0f / crosslength2;
628  tt = det3f(vecdif3f(t1, p2, p1), v2, cross) * crosslength2;
629  ss = det3f(vecdif3f(t1, p2, p1), v1, cross) * crosslength2;
630  if (x1)
631  vecadd3f(x1, p1, vecscale3f(t1, v1, tt));
632  if (x2)
633  vecadd3f(x2, p2, vecscale3f(t1, v2, ss));
634  if (t)
635  *t = tt;
636  if (s)
637  *s = ss;
638  return TRUE; //success we have 2 footpoints.
639 }
640 
641 BOOL line_intersect_planed_3f(float *p, float *v, float *N, float d, float *pi, float *t)
642 {
643  //from graphics gems I, p.391 http://inis.jinr.ru/sl/vol1/CMC/Graphics_Gems_1,ed_A.Glassner.pdf
644  // V dot N = d = const for points on a plane, or N dot P + d = 0
645  // line/ray P1 + v1*t = P2 (intersection point)
646  // combining t = -(d + N dot P1)/(N dot v1)
647  float t1[3], t2[3], nd, tt;
648  nd = vecdot3f(N, v);
649  if (APPROX(nd, 0.0f)) return FALSE;
650  tt = -(d + vecdot3f(N, p)) / nd;
651  vecadd3f(t2, p, vecscale3f(t1, v, tt));
652  if (t) *t = tt;
653  if (pi) veccopy3f(pi, t2);
654  return TRUE;
655 }
656 BOOL line_intersect_plane_3f(float *p, float *v, float *N, float *pp, float *pi, float *t)
657 {
658  float d;
659  d = vecdot3f(N, pp);
660  return line_intersect_planed_3f(p, v, N, d, pi, t);
661 }
662 
663 BOOL line_intersect_cylinder_3f(float *p, float *v, float radius, float *pi)
664 {
665  //from rendray_Cylinder
666  //intersects arbitrary ray (p,v) with cylinder of radius, origiin 0,0,0 and axis 0,1,0
667  //april 2014: NOT TESTED, NOT USED - just hacked in and compiled
668  // if((!XEQ) && (!ZEQ)) {
669  float pp[3];
670  float dx = v[0];
671  float dz = v[2];
672  float a = dx*dx + dz*dz;
673  float b = 2.0f*(dx * p[0] + dz * p[2]);
674  float c = p[0] * p[0] + p[2] * p[2] - radius*radius;
675  float und;
676  if (APPROX(a, 0.0f))return FALSE;
677  b /= a; c /= a;
678  und = b*b - 4*c;
679  if(und > 0) { /* HITS the infinite cylinder */
680  float t2[3];
681  //float sol1 = (-b+(float) sqrt(und))/2;
682  float sol2 = (-b-(float) sqrt(und))/2;
683  float sol = sol2;// sol1 < sol2 ? sol1 : sol2; //take the one closest to p (but should these be abs? what about direction
684  vecadd3f(pp, p, vecscale3f(t2, v, sol));
685  if (pi) veccopy3f(pi, pp);
686  return TRUE;
687  }
688  // }
689  return FALSE;
690 }
691 
692 struct point_XYZ* vecadd(struct point_XYZ* r, struct point_XYZ* v, struct point_XYZ* v2)
693 {
694  r->x = v->x + v2->x;
695  r->y = v->y + v2->y;
696  r->z = v->z + v2->z;
697  return r;
698 }
699 
700 struct point_XYZ* vecdiff(struct point_XYZ* r, struct point_XYZ* v, struct point_XYZ* v2)
701 {
702  r->x = v->x - v2->x;
703  r->y = v->y - v2->y;
704  r->z = v->z - v2->z;
705  return r;
706 }
707 
708 /*i,j,n will form an orthogonal vector space */
709 void make_orthogonal_vector_space(struct point_XYZ* i, struct point_XYZ* j, struct point_XYZ n) {
710  /* optimal axis finding algorithm. the solution isn't unique.*/
711  /* each of these three calculations doesn't work (or works poorly)*/
712  /* in certain distinct cases. (gives zero vectors when two axes are 0)*/
713  /* selecting the calculations according to smallest axis avoids this problem.*/
714  /* (the two remaining axis are thus far from zero, if n is normal)*/
715  if(fabs(n.x) <= fabs(n.y) && fabs(n.x) <= fabs(n.z)) { /* x smallest*/
716  i->x = 0;
717  i->y = n.z;
718  i->z = -n.y;
719  vecnormal(i,i);
720  j->x = n.y*n.y + n.z*n.z;
721  j->y = (-n.x)*n.y;
722  j->z = (-n.x)*n.z;
723  } else if(fabs(n.y) <= fabs(n.x) && fabs(n.y) <= fabs(n.z)) { /* y smallest*/
724  i->x = -n.z;
725  i->y = 0;
726  i->z = n.x;
727  vecnormal(i,i);
728  j->x = (-n.x)*n.y;
729  j->y = n.x*n.x + n.z*n.z;
730  j->z = (-n.y)*n.z;
731  } else { /* z smallest*/
732  i->x = n.y;
733  i->y = -n.x;
734  i->z = 0;
735  vecnormal(i,i);
736  j->x = (-n.x)*n.z;
737  j->y = (-n.y)*n.z;
738  j->z = n.x*n.x + n.y*n.y;
739  }
740 }
741 
742 
743 GLDOUBLE* mattranspose(GLDOUBLE* res, GLDOUBLE* mm)
744 {
745  GLDOUBLE mcpy[16];
746  int i, j;
747  GLDOUBLE *m;
748 
749  m = mm;
750  if(res == m) {
751  memcpy(mcpy,m,sizeof(GLDOUBLE)*16);
752  m = mcpy;
753  }
754 
755  for (i = 0; i < 4; i++) {
756  //for (j = i + 1; j < 4; j++) {
757  // res[i*4+j] = m[j*4+i];
758  //}
759  for (j = 0; j < 4; j++) {
760  res[i*4+j] = m[j*4+i];
761  }
762  }
763  return res;
764 }
765 
766 float* mattranspose4f(float* res, float* mm)
767 {
768  float mcpy[16];
769  int i, j;
770  float *m;
771 
772  m = mm;
773  if(res == m) {
774  memcpy(mcpy,m,sizeof(float)*16);
775  m = mcpy;
776  }
777 
778  for (i = 0; i < 4; i++) {
779  for (j = 0; j < 4; j++) {
780  res[i*4+j] = m[j*4+i];
781  }
782  }
783  return res;
784 }
785 float* mattranspose3f(float* res, float* mm)
786 {
787  float mcpy[9];
788  int i, j;
789  float *m;
790 
791  m = mm;
792  if(res == m) {
793  memcpy(mcpy,m,sizeof(float)*9);
794  m = mcpy;
795  }
796 
797  for (i = 0; i < 3; i++) {
798  for (j = 0; j < 3; j++) {
799  res[i*3+j] = m[j*3+i];
800  }
801  }
802  return res;
803 }
804 
805 GLDOUBLE* matinverse98(GLDOUBLE* res, GLDOUBLE* mm)
806 {
807  /*FLOPs 98 double: det3 9, 1/det 1, adj3x3 9x4=36, inv*T 13x4=52 */
808  //July 2016 THIS IS WRONG DON'T USE
809  //see the glu equivalent elsewhere
810  //you can check with A*A-1 = I and this function doesn't give I
811  double Deta;
812  GLDOUBLE mcpy[16];
813  GLDOUBLE *m;
814 
815  m = mm;
816  if(res == m) {
817  memcpy(mcpy,m,sizeof(GLDOUBLE)*16);
818  m = mcpy;
819  }
820 
821  Deta = det3x3(m);
822  if(APPROX(Deta,0.0))
823  printf("deta 0\n");
824  Deta = 1.0 / Deta;
825 
826  res[0] = (-m[9]*m[6] +m[5]*m[10])*Deta;
827  res[4] = (+m[8]*m[6] -m[4]*m[10])*Deta;
828  res[8] = (-m[8]*m[5] +m[4]*m[9])*Deta;
829  res[12] = ( m[12]*m[9]*m[6] -m[8]*m[13]*m[6] -m[12]*m[5]*m[10] +m[4]*m[13]*m[10] +m[8]*m[5]*m[14] -m[4]*m[9]*m[14])*Deta;
830 
831  res[1] = (+m[9]*m[2] -m[1]*m[10])*Deta;
832  res[5] = (-m[8]*m[2] +m[0]*m[10])*Deta;
833  res[9] = (+m[8]*m[1] -m[0]*m[9])*Deta;
834  res[13] = (-m[12]*m[9]*m[2] +m[8]*m[13]*m[2] +m[12]*m[1]*m[10] -m[0]*m[13]*m[10] -m[8]*m[1]*m[14] +m[0]*m[9]*m[14])*Deta;
835 
836  res[2] = (-m[5]*m[2] +m[1]*m[6])*Deta;
837  res[6] = (+m[4]*m[2] -m[0]*m[6])*Deta;
838  res[10] = (-m[4]*m[1] +m[0]*m[5])*Deta;
839  res[14] = ( m[12]*m[5]*m[2] -m[4]*m[13]*m[2] -m[12]*m[1]*m[6] +m[0]*m[13]*m[6] +m[4]*m[1]*m[14] -m[0]*m[5]*m[14])*Deta;
840 
841  res[3] = (+m[5]*m[2]*m[11] -m[1]*m[6]*m[11])*Deta;
842  res[7] = (-m[4]*m[2]*m[11] +m[0]*m[6]*m[11])*Deta;
843  res[11] = (+m[4]*m[1]*m[11] -m[0]*m[5]*m[11])*Deta;
844  res[15] = (-m[8]*m[5]*m[2] +m[4]*m[9]*m[2] +m[8]*m[1]*m[6] -m[0]*m[9]*m[6] -m[4]*m[1]*m[10] +m[0]*m[5]*m[10])*Deta;
845 
846  return res;
847 }
848 float* matinverse4f(float* res, float* mm)
849 {
850  /*FLOPs 98 float: det3 9, 1/det 1, adj3x3 9x4=36, inv*T 13x4=52 */
851 
852  float Deta;
853  float mcpy[16];
854  float *m;
855 
856  m = mm;
857  if(res == m) {
858  memcpy(mcpy,m,sizeof(float)*16);
859  m = mcpy;
860  }
861 
862  Deta = det3f(&m[0],&m[4],&m[8]); //det3x3(m);
863  Deta = 1.0f / Deta;
864 
865  res[0] = (-m[9]*m[6] +m[5]*m[10])*Deta;
866  res[4] = (+m[8]*m[6] -m[4]*m[10])*Deta;
867  res[8] = (-m[8]*m[5] +m[4]*m[9])*Deta;
868  res[12] = ( m[12]*m[9]*m[6] -m[8]*m[13]*m[6] -m[12]*m[5]*m[10] +m[4]*m[13]*m[10] +m[8]*m[5]*m[14] -m[4]*m[9]*m[14])*Deta;
869 
870  res[1] = (+m[9]*m[2] -m[1]*m[10])*Deta;
871  res[5] = (-m[8]*m[2] +m[0]*m[10])*Deta;
872  res[9] = (+m[8]*m[1] -m[0]*m[9])*Deta;
873  res[13] = (-m[12]*m[9]*m[2] +m[8]*m[13]*m[2] +m[12]*m[1]*m[10] -m[0]*m[13]*m[10] -m[8]*m[1]*m[14] +m[0]*m[9]*m[14])*Deta;
874 
875  res[2] = (-m[5]*m[2] +m[1]*m[6])*Deta;
876  res[6] = (+m[4]*m[2] -m[0]*m[6])*Deta;
877  res[10] = (-m[4]*m[1] +m[0]*m[5])*Deta;
878  res[14] = ( m[12]*m[5]*m[2] -m[4]*m[13]*m[2] -m[12]*m[1]*m[6] +m[0]*m[13]*m[6] +m[4]*m[1]*m[14] -m[0]*m[5]*m[14])*Deta;
879 
880  res[3] = (+m[5]*m[2]*m[11] -m[1]*m[6]*m[11])*Deta;
881  res[7] = (-m[4]*m[2]*m[11] +m[0]*m[6]*m[11])*Deta;
882  res[11] = (+m[4]*m[1]*m[11] -m[0]*m[5]*m[11])*Deta;
883  res[15] = (-m[8]*m[5]*m[2] +m[4]*m[9]*m[2] +m[8]*m[1]*m[6] -m[0]*m[9]*m[6] -m[4]*m[1]*m[10] +m[0]*m[5]*m[10])*Deta;
884 
885  return res;
886 }
887 
888 struct point_XYZ* polynormal(struct point_XYZ* r, struct point_XYZ* p1, struct point_XYZ* p2, struct point_XYZ* p3) {
889  struct point_XYZ v1;
890  struct point_XYZ v2;
891  VECDIFF(*p2,*p1,v1);
892  VECDIFF(*p3,*p1,v2);
893  veccross(r,v1,v2);
894  vecnormal(r,r);
895  return r;
896 }
897 
898 /*simple wrapper for now. optimize later */
899 struct point_XYZ* polynormalf(struct point_XYZ* r, float* p1, float* p2, float* p3) {
900  struct point_XYZ pp[3];
901  pp[0].x = p1[0];
902  pp[0].y = p1[1];
903  pp[0].z = p1[2];
904  pp[1].x = p2[0];
905  pp[1].y = p2[1];
906  pp[1].z = p2[2];
907  pp[2].x = p3[0];
908  pp[2].y = p3[1];
909  pp[2].z = p3[2];
910  return polynormal(r,pp+0,pp+1,pp+2);
911 }
912 
913 
914 GLDOUBLE* matrotate(GLDOUBLE* Result, double Theta, double x, double y, double z)
915 {
916  GLDOUBLE CosTheta = cos(Theta);
917  GLDOUBLE SinTheta = sin(Theta);
918 
919  Result[0] = x*x + (y*y+z*z)*CosTheta;
920  Result[1] = x*y - x*y*CosTheta + z*SinTheta;
921  Result[2] = x*z - x*z*CosTheta - y*SinTheta;
922  Result[4] = x*y - x*y*CosTheta - z*SinTheta;
923  Result[5] = y*y + (x*x+z*z)*CosTheta;
924  Result[6] = z*y - z*y*CosTheta + x*SinTheta;
925  Result[8] = z*x - z*x*CosTheta + y*SinTheta;
926  Result[9] = z*y - z*y*CosTheta - x*SinTheta;
927  Result[10]= z*z + (x*x+y*y)*CosTheta;
928  Result[3] = 0;
929  Result[7] = 0;
930  Result[11] = 0;
931  Result[12] = 0;
932  Result[13] = 0;
933  Result[14] = 0;
934  Result[15] = 1;
935 
936  return Result;
937 }
938 
939 GLDOUBLE* mattranslate(GLDOUBLE* r, double dx, double dy, double dz)
940 {
941  r[0] = r[5] = r[10] = r[15] = 1;
942  r[1] = r[2] = r[3] = r[4] =
943  r[6] = r[7] = r[8] = r[9] =
944  r[11] = 0;
945  r[12] = dx;
946  r[13] = dy;
947  r[14] = dz;
948  return r;
949 }
950 
951 GLDOUBLE* matmultiplyFULL(GLDOUBLE* r, GLDOUBLE* mm , GLDOUBLE* nn)
952 {
953  /* full 4x4, will do perspectives
954  FLOPs 64 double: 4x4x4
955  r = mm x nn
956  */
957  GLDOUBLE tm[16],tn[16];
958  GLDOUBLE *m, *n;
959  int i,j,k;
960  /* prevent self-multiplication problems.*/
961  m = mm;
962  n = nn;
963  if(r == m) {
964  memcpy(tm,m,sizeof(GLDOUBLE)*16);
965  m = tm;
966  }
967  if(r == n) {
968  memcpy(tn,n,sizeof(GLDOUBLE)*16);
969  n = tn;
970  }
971  if(0){
972  if(1) for(i=0;i<3;i++){
973  if(mm[i +12] != 0.0){
974  double p = mm[i +12];
975  printf("Ft[%d]%f ",i,p);
976  }
977  if(nn[i + 12] != 0.0){
978  double p = nn[i +12];
979  printf("FT[%d]%f ",i,p);
980  }
981  }
982  if(1) for(i=0;i<3;i++){
983  if(mm[i*4 + 3] != 0.0){
984  double p = mm[i*4 + 3];
985  printf("Fp[%d]%f ",i,p);
986  }
987  if(nn[i*4 + 3] != 0.0){
988  double p = nn[i*4 + 3];
989  printf("FP[%d]%f ",i,p);
990  }
991  }
992  }
993  /* assume 4x4 homgenous transform */
994  for(i=0;i<4;i++)
995  for(j=0;j<4;j++)
996  {
997  r[i*4+j] = 0.0;
998  for(k=0;k<4;k++)
999  r[i*4+j] += m[i*4+k]*n[k*4+j];
1000  }
1001  return r;
1002 }
1003 
1004 GLDOUBLE* matmultiplyAFFINE(GLDOUBLE* r, GLDOUBLE* nn , GLDOUBLE* mm)
1005 {
1006  /* AFFINE subset - ignores perspectives, use for MODELVIEW
1007  FLOPs 36 double: 3x3x4
1008  r = nn x mm
1009  */
1010  GLDOUBLE tm[16],tn[16];
1011  GLDOUBLE *m, *n;
1012  int i; //,j,k;
1013  /* prevent self-multiplication problems.*/
1014  m = mm;
1015  n = nn;
1016  if(r == m) {
1017  memcpy(tm,m,sizeof(GLDOUBLE)*16);
1018  m = tm;
1019  }
1020  if(r == n) {
1021  memcpy(tn,n,sizeof(GLDOUBLE)*16);
1022  n = tn;
1023  }
1024  if(0){
1025  if(0) for(i=0;i<3;i++){
1026  if(mm[i +12] != 0.0){
1027  double p = mm[i +12];
1028  printf("At[%d]%lf ",i,p);
1029  }
1030  if(nn[i + 12] != 0.0){
1031  double p = nn[i +12];
1032  printf("AT[%d]%lf ",i,p);
1033  }
1034  }
1035  if(1) for(i=0;i<3;i++){
1036  if(mm[i*4 + 3] != 0.0){
1037  double p = mm[i*4 + 3];
1038  printf("Ap[%d]%lf ",i,p);
1039  }
1040  if(nn[i*4 + 3] != 0.0){
1041  double p = nn[i*4 + 3];
1042  printf("AP[%d]%lf ",i,p);
1043  }
1044  }
1045  }
1046 
1047 
1048  /* this method ignors the perspectives */
1049  r[0] = m[0]*n[0] +m[4]*n[1] +m[8]*n[2];
1050  r[4] = m[0]*n[4] +m[4]*n[5] +m[8]*n[6];
1051  r[8] = m[0]*n[8] +m[4]*n[9] +m[8]*n[10];
1052  r[12]= m[0]*n[12]+m[4]*n[13]+m[8]*n[14] +m[12];
1053 
1054  r[1] = m[1]*n[0] +m[5]*n[1] +m[9]*n[2];
1055  r[5] = m[1]*n[4] +m[5]*n[5] +m[9]*n[6];
1056  r[9] = m[1]*n[8] +m[5]*n[9] +m[9]*n[10];
1057  r[13]= m[1]*n[12]+m[5]*n[13]+m[9]*n[14] +m[13];
1058 
1059  r[2] = m[2]*n[0]+ m[6]*n[1] +m[10]*n[2];
1060  r[6] = m[2]*n[4]+ m[6]*n[5] +m[10]*n[6];
1061  r[10]= m[2]*n[8]+ m[6]*n[9] +m[10]*n[10];
1062  r[14]= m[2]*n[12]+m[6]*n[13]+m[10]*n[14] +m[14];
1063 
1064  r[3] = r[7] = r[11] = 0.0;
1065  r[15] = 1.0;
1066 
1067  return r;
1068 }
1069 GLDOUBLE* matmultiply(GLDOUBLE* r, GLDOUBLE* mm , GLDOUBLE* nn){
1070  return matmultiplyFULL(r,mm,nn);
1071 }
1072 
1073 float* matmultiply4f(float* r, float* mm , float* nn)
1074 {
1075  /* FLOPs 64 float: N^3 = 4x4x4
1076  r = mm x nn
1077  */
1078  float tm[16],tn[16];
1079  float *m, *n;
1080  int i,j,k;
1081  /* prevent self-multiplication problems.*/
1082  m = mm;
1083  n = nn;
1084  if(r == m) {
1085  memcpy(tm,m,sizeof(float)*16);
1086  m = tm;
1087  }
1088  if(r == n) {
1089  memcpy(tn,n,sizeof(float)*16);
1090  n = tn;
1091  }
1092  /* assume 4x4 homgenous transform */
1093  for(i=0;i<4;i++)
1094  for(j=0;j<4;j++)
1095  {
1096  r[i*4+j] = 0.0;
1097  for(k=0;k<4;k++)
1098  r[i*4+j] += m[i*4+k]*n[k*4+j];
1099  }
1100  return r;
1101 }
1102 float* matmultiply3f(float* r, float* mm , float* nn)
1103 {
1104  /* FLOPs 27 float: N^3 = 3x3x3
1105  r = mm x nn
1106  */
1107  float tm[9],tn[9];
1108  float *m, *n;
1109  int i,j,k;
1110  /* prevent self-multiplication problems.*/
1111  m = mm;
1112  n = nn;
1113  if(r == m) {
1114  memcpy(tm,m,sizeof(float)*9);
1115  m = tm;
1116  }
1117  if(r == n) {
1118  memcpy(tn,n,sizeof(float)*9);
1119  n = tn;
1120  }
1121  /* assume 4x4 homgenous transform */
1122  for(i=0;i<3;i++)
1123  for(j=0;j<3;j++)
1124  {
1125  r[i*3+j] = 0.0;
1126  for(k=0;k<3;k++)
1127  r[i*3+j] += m[i*3+k]*n[k*3+j];
1128  }
1129  return r;
1130 }
1131 float *axisangle_rotate3f(float* b, float *a, float *axisangle)
1132 {
1133  /* http://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation
1134  uses Rodrigues formula axisangle (axis,angle)
1135  somewhat expensive, so if tranforming many points with the same rotation,
1136  it might be more efficient to use another method (like axisangle -> matrix, then matrix transforms)
1137  b = a*cos(angle) + (axis cross a)*sin(theta) + axis*(axis dot a)*(1 - cos(theta))
1138  */
1139  float cosine, sine, cross[3], dot, theta, *axis, t1[3], t2[3],t3[3],t4[3];
1140  theta = axisangle[3];
1141  axis = axisangle;
1142  cosine = (float)cos(theta);
1143  sine = (float)sin(theta);
1144  veccross3f(cross,axis, a);
1145  dot = vecdot3f(axis, a);
1146  vecadd3f(b,vecscale3f(t1, a, cosine), vecadd3f(t2, vecscale3f(t3, cross, sine), vecscale3f(t4, axis, dot*(1.0f - cosine))));
1147  return b;
1148 }
1149 float *matidentity4f(float *b){
1150  // zeros a 4x4 and puts 1's down the diagonal to make a 4x4 identity matrix
1151  int i,j;
1152  float *mat[4];
1153  for(i=0;i<4;i++){
1154  mat[i] = &b[i*4];
1155  for(j=0;j<4;j++)
1156  mat[i][j] = 0.0f;
1157  mat[i][i] = 1.0f;
1158  }
1159  return b;
1160 }
1161 float *matidentity3f(float *b){
1162  // zeros a 4x4 and puts 1's down the diagonal to make a 4x4 identity matrix
1163  int i;
1164  for(i=0;i<9;i++) b[i] = 0.0f;
1165  for(i=0;i<3;i++) b[i*3 +i] = 1.0f;
1166  return b;
1167 }
1168 float *axisangle2matrix4f(float *b, float *axisangle){
1169  //untested as of july 2014
1170  int i; //,j;
1171  float *mat[4];
1172  for(i=0;i<4;i++)
1173  mat[i] = &b[i*4];
1174  matidentity4f(b);
1175  //rotate identity using axisangle
1176  for(i=0;i<3;i++){ //could be 4 here if there was anything on line 4, but with identity its 0 0 0 1
1177  axisangle_rotate3f(mat[i], mat[i], axisangle);
1178  }
1179  return b;
1180 }
1181 
1182 void matrixFromAxisAngle4d(double *mat, double rangle, double x, double y, double z)
1183 {
1184 
1185  // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/
1186  int i;
1187  double c, s, t;
1188  double *m[4];
1189  double tmp1;
1190  double tmp2;
1191 
1192  c = cos(rangle);
1193  s = sin(rangle);
1194  t = 1.0 - c;
1195  //row indexes
1196  m[0] = &mat[0];
1197  m[1] = &mat[4];
1198  m[2] = &mat[8];
1199  m[3] = &mat[12];
1200  //identity
1201  for(i=0;i<16;i++) mat[i] = 0.0;
1202  for(i=0;i<4;i++) m[i][i] = 1.0;
1203  // if axis is not already normalised then uncomment this
1204  // double magnitude = Math.sqrt(a1.x*a1.x + a1.y*a1.y + a1.z*a1.z);
1205  // if (magnitude==0) throw error;
1206  // a1.x /= magnitude;
1207  // a1.y /= magnitude;
1208  // a1.z /= magnitude;
1209 
1210  m[0][0] = c + x*x*t;
1211  m[1][1] = c + y*y*t;
1212  m[2][2] = c + z*z*t;
1213 
1214 
1215  tmp1 = x*y*t;
1216  tmp2 = z*s;
1217  m[1][0] = tmp1 + tmp2;
1218  m[0][1] = tmp1 - tmp2;
1219  tmp1 = x*z*t;
1220  tmp2 = y*s;
1221  m[2][0] = tmp1 - tmp2;
1222  m[0][2] = tmp1 + tmp2;
1223  tmp1 = y*z*t;
1224  tmp2 = x*s;
1225  m[2][1] = tmp1 + tmp2;
1226  m[1][2] = tmp1 - tmp2;
1227 
1228 }
1229 
1230 void rotate_v2v_axisAngled(double* axis, double* angle, double *orig, double *result)
1231 {
1232  double cvl;
1233  double dv[3], iv[3], cv[3];
1234 
1235  dv[0] = 0;
1236  dv[1] = 0;
1237  dv[2] = 0;
1238 
1239  iv[0] = 0;
1240  iv[1] = 0;
1241  iv[2] = 0;
1242 
1243  cv[0] = 0;
1244  cv[1] = 0;
1245  cv[2] = 0;
1246 
1247  /* step 1 get sin of angle between 2 vectors using cross product rule: ||u x v|| = ||u||*||v||*sin(theta) */
1248  vecnormald(dv,orig); /*normalizes vector to unit length U -> u^ (length 1) */
1249  vecnormald(iv,result);
1250 
1251  veccrossd(cv,dv,iv); /*the axis of rotation cv = dv X iv*/
1252  cvl = vecnormald(cv,cv); /* cvl = ||u x v|| / ||u^||*||v^|| = ||u x v|| = sin(theta)*/
1253  veccopyd(axis,cv);
1254 
1255  /* if(cvl == 0) { */
1256  if(APPROX(cvl, 0)) {
1257  cv[2] = 1.0;
1258  }
1259  /* step 2 get cos of angle between 2 vectors using dot product rule: u dot v = ||u||*||v||*cos(theta) or cos(theta) = u dot v/( ||u|| ||v||)
1260  or, since U,V already unit length from being normalized, cos(theta) = u dot v */
1261  *angle = atan2(cvl,vecdotd(dv,iv)); /*the angle theta = arctan(rise/run) = atan2(sin_theta,cos_theta) in radians*/
1262 }
1263 /*puts dv back on iv - return the 4x4 rotation matrix that will rotate vector dv onto iv*/
1264 double matrotate2v(GLDOUBLE* res, struct point_XYZ iv/*original*/, struct point_XYZ dv/*result*/) {
1265  struct point_XYZ cv;
1266  double cvl,a;
1267 
1268  /* step 1 get sin of angle between 2 vectors using cross product rule: ||u x v|| = ||u||*||v||*sin(theta) */
1269  vecnormal(&dv,&dv); /*normalizes vector to unit length U -> u^ (length 1) */
1270  vecnormal(&iv,&iv);
1271 
1272  veccross(&cv,dv,iv); /*the axis of rotation cv = dv X iv*/
1273  cvl = vecnormal(&cv,&cv); /* cvl = ||u x v|| / ||u^||*||v^|| = ||u x v|| = sin(theta)*/
1274  /* if(cvl == 0) { */
1275  if(APPROX(cvl, 0)) {
1276  cv.z = 1;
1277  }
1278  /* step 2 get cos of angle between 2 vectors using dot product rule: u dot v = ||u||*||v||*cos(theta) or cos(theta) = u dot v/( ||u|| ||v||)
1279  or, since U,V already unit length from being normalized, cos(theta) = u dot v */
1280  a = atan2(cvl,vecdot(&dv,&iv)); /*the angle theta = arctan(rise/run) = atan2(sin_theta,cos_theta) in radians*/
1281  /* step 3 convert rotation angle around unit directional vector of rotation into an equivalent rotation matrix 4x4 */
1282  matrotate(res,a,cv.x,cv.y,cv.z);
1283  return a;
1284 }
1285 
1286 
1287 #define SHOW_NONSINGULARS 0 //or 1 for noisy
1288 /****
1289  * hacked from a graphics gem
1290  * Returned value:
1291  * TRUE if input matrix is nonsingular
1292  * FALSE otherwise
1293  *
1294  ***/
1295 
1296 BOOL matrix3x3_inverse_float(float *inn, float *outt)
1297 {
1298  /*FLOPs 40 float: det3 12, 1/det 1, adj3x3 9x3=27 */
1299 
1300  float det_1;
1301  float pos, /* neg, */ temp;
1302  float *in[3], *out[3];
1303 
1304 /*#define ACCUMULATE \
1305 // if (temp >= 0.0) \
1306 // pos += temp; \
1307 // else \
1308  neg += temp;
1309 */
1310 
1311 #define ACCUMULATE pos += temp;
1312 
1313 //#define PRECISION_LIMIT 1.0e-7 //(1.0e-15)
1314  in[0] = &inn[0];
1315  in[1] = &inn[3];
1316  in[2] = &inn[6];
1317  out[0] = &outt[0];
1318  out[1] = &outt[3];
1319  out[2] = &outt[6];
1320 
1321  /*
1322  * Calculate the determinant of submatrix A and determine if the
1323  * the matrix is singular as limited by the double precision
1324  * floating-point data representation.
1325  */
1326  pos = 0.0f; //neg = 0.0;
1327  temp = in[0][0] * in[1][1] * in[2][2];
1328  ACCUMULATE
1329  temp = in[0][1] * in[1][2] * in[2][0];
1330  ACCUMULATE
1331  temp = in[0][2] * in[1][0] * in[2][1];
1332  ACCUMULATE
1333  temp = -in[0][2] * in[1][1] * in[2][0];
1334  ACCUMULATE
1335  temp = -in[0][1] * in[1][0] * in[2][2];
1336  ACCUMULATE
1337  temp = -in[0][0] * in[1][2] * in[2][1];
1338  ACCUMULATE
1339  det_1 = pos; // + neg;
1340 
1341  /* Is the submatrix A singular? */
1342  //if ((det_1 == 0.0) || (abs(det_1 / (pos - neg)) < PRECISION_LIMIT)) {
1343  if(APPROX(det_1,0.0f)){
1344 
1345  /* Matrix M has no inverse */
1346 
1347  if(SHOW_NONSINGULARS) fprintf (stderr, "affine_matrix4_inverse: singular matrix\n");
1348  return FALSE;
1349  }
1350 
1351  else {
1352 
1353  /* Calculate inverse(A) = adj(A) / det(A) */
1354  det_1 = 1.0f / det_1;
1355  out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1] ) * det_1;
1356  out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0] ) * det_1;
1357  out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0] ) * det_1;
1358  out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1] ) * det_1;
1359  out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0] ) * det_1;
1360  out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0] ) * det_1;
1361  out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1] ) * det_1;
1362  out[1][2] = -(in[0][0] * in[1][2] - in[0][2] * in[1][0] ) * det_1;
1363  out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0] ) * det_1;
1364 
1365  return TRUE;
1366  }
1367 }
1368 float * mat423f(float *out3x3, float *in4x4)
1369 {
1370  int i,j;
1371  for(i=0;i<3;i++){
1372  for(j=0;j<3;j++)
1373  out3x3[i*3 + j] = in4x4[i*4 + j];
1374  }
1375  return out3x3;
1376 }
1377 float * matinverse3f(float *out3x3, float *in3x3)
1378 {
1379  matrix3x3_inverse_float(in3x3,out3x3);
1380  return out3x3;
1381 }
1382 
1383 float * transform3x3f(float *out3, float *in3, float *mat3x3){
1384  int i,j;
1385  float t3[3];
1386  memcpy(t3,in3,3*sizeof(float));
1387  for(i=0;i<3;i++){
1388  out3[i] = 0.0f;
1389  for(j=0;j<3;j++)
1390  out3[i] += t3[j]*mat3x3[j*3 + i];
1391  }
1392 
1393  return out3;
1394 }
1395 
1396 BOOL affine_matrix4x4_inverse_float(float *inn, float *outt)
1397 {
1398  /*FLOPs 49 float: det3 12, 1/det 1, adj3x3 9x3=27, INV*T=9 */
1399  /* faithful transcription of GraphicsGem II, p.604, Wu
1400  use this for modelview matrix which has no perspectives (vs FULL 4x4 100 FLOPs)
1401  */
1402 
1403  float det_1;
1404  float pos, /* neg, */ temp;
1405  float *in[4], *out[4];
1406 
1407 /*#define ACCUMULATE \
1408 // if (temp >= 0.0) \
1409 // pos += temp; \
1410 // else \
1411  neg += temp;
1412 */
1413 
1414 #define ACCUMULATE pos += temp;
1415 
1416 //#define PRECISION_LIMIT 1.0e-7 //(1.0e-15)
1417  in[0] = &inn[0];
1418  in[1] = &inn[4];
1419  in[2] = &inn[8];
1420  in[3] = &inn[12];
1421  out[0] = &outt[0];
1422  out[1] = &outt[4];
1423  out[2] = &outt[8];
1424  out[3] = &outt[12];
1425 
1426  /*
1427  * Calculate the determinant of submatrix A and determine if the
1428  * the matrix is singular as limited by the double precision
1429  * floating-point data representation.
1430  */
1431  pos = 0.0f; //neg = 0.0;
1432  temp = in[0][0] * in[1][1] * in[2][2];
1433  ACCUMULATE
1434  temp = in[0][1] * in[1][2] * in[2][0];
1435  ACCUMULATE
1436  temp = in[0][2] * in[1][0] * in[2][1];
1437  ACCUMULATE
1438  temp = -in[0][2] * in[1][1] * in[2][0];
1439  ACCUMULATE
1440  temp = -in[0][1] * in[1][0] * in[2][2];
1441  ACCUMULATE
1442  temp = -in[0][0] * in[1][2] * in[2][1];
1443  ACCUMULATE
1444  det_1 = pos; // + neg;
1445 
1446  /* Is the submatrix A singular? */
1447  //if ((det_1 == 0.0) || (abs(det_1 / (pos - neg)) < PRECISION_LIMIT)) {
1448  if(APPROX(det_1,0.0f)){
1449 
1450  /* Matrix M has no inverse */
1451  if(SHOW_NONSINGULARS) fprintf (stderr, "affine_matrix4_inverse: singular matrix\n");
1452  return FALSE;
1453  }
1454 
1455  else {
1456 
1457  /* Calculate inverse(A) = adj(A) / det(A) */
1458  det_1 = 1.0f / det_1;
1459  out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1] ) * det_1;
1460  out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0] ) * det_1;
1461  out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0] ) * det_1;
1462  out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1] ) * det_1;
1463  out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0] ) * det_1;
1464  out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0] ) * det_1;
1465  out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1] ) * det_1;
1466  out[1][2] = -(in[0][0] * in[1][2] - in[0][2] * in[1][0] ) * det_1;
1467  out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0] ) * det_1;
1468 
1469  /* Calculat -C * inverse(A) */
1470  out[3][0] = -(in[3][0] * out[0][0] + in[3][1]*out[1][0] + in[3][2]*out[2][0]);
1471  out[3][1] = -(in[3][0] * out[0][1] + in[3][1]*out[1][1] + in[3][2]*out[2][1]);
1472  out[3][2] = -(in[3][0] * out[0][2] + in[3][1]*out[1][2] + in[3][2]*out[2][2]);
1473 
1474  /* Fill in last column */
1475  out[0][3] = out[1][3] = out[2][3] = 0.0f;
1476  out[3][3] = 1.0f;
1477  return TRUE;
1478  }
1479 }
1480 
1481 BOOL affine_matrix4x4_inverse_double(double *inn, double *outt)
1482 {
1483  /*FLOPs 49 double: det3 12, 1/det 1, adj3x3 9x3=27, INV*T=9 */
1484  /* faithful transcription of Graphics Gems II, p.604, Wu, FAST MATRIX INVERSION
1485  use this for modelview matrix which has no perspectives (vs FULL 4x4 inverse 102 FLOPs)
1486  */
1487  double det_1;
1488  double pos, /* neg, */ temp;
1489  double *in[4], *out[4];
1490 
1491 /*#define ACCUMULATE \
1492 // if (temp >= 0.0) \
1493 // pos += temp; \
1494 // else \
1495  neg += temp;
1496 */
1497 
1498 #define ACCUMULATE pos += temp;
1499 
1500 //#define PRECISION_LIMIT 1.0e-7 //(1.0e-15)
1501  in[0] = &inn[0];
1502  in[1] = &inn[4];
1503  in[2] = &inn[8];
1504  in[3] = &inn[12];
1505  out[0] = &outt[0];
1506  out[1] = &outt[4];
1507  out[2] = &outt[8];
1508  out[3] = &outt[12];
1509 
1510  /*
1511  * Calculate the determinant of submatrix A and determine if the
1512  * the matrix is singular as limited by the double precision
1513  * floating-point data representation.
1514  */
1515  pos = 0.0; //neg = 0.0;
1516  temp = in[0][0] * in[1][1] * in[2][2];
1517  ACCUMULATE
1518  temp = in[0][1] * in[1][2] * in[2][0];
1519  ACCUMULATE
1520  temp = in[0][2] * in[1][0] * in[2][1];
1521  ACCUMULATE
1522  temp = -in[0][2] * in[1][1] * in[2][0];
1523  ACCUMULATE
1524  temp = -in[0][1] * in[1][0] * in[2][2];
1525  ACCUMULATE
1526  temp = -in[0][0] * in[1][2] * in[2][1];
1527  ACCUMULATE
1528  det_1 = pos; // + neg;
1529 
1530  /* Is the submatrix A singular? */
1531  //if ((det_1 == 0.0) || (abs(det_1 / (pos - neg)) < PRECISION_LIMIT)) {
1532  if(APPROX(det_1,0.0)){
1533 
1534  /* Matrix M has no inverse */
1535  if(SHOW_NONSINGULARS) fprintf (stderr, "affine_matrix4_inverse: singular matrix\n");
1536  return FALSE;
1537  }
1538 
1539  else {
1540 
1541  /* Calculate inverse(A) = adj(A) / det(A) */
1542  det_1 = 1.0 / det_1;
1543  out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1] ) * det_1;
1544  out[1][0] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0] ) * det_1;
1545  out[2][0] = (in[1][0] * in[2][1] - in[1][1] * in[2][0] ) * det_1;
1546  out[0][1] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1] ) * det_1;
1547  out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0] ) * det_1;
1548  out[2][1] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0] ) * det_1;
1549  out[0][2] = (in[0][1] * in[1][2] - in[0][2] * in[1][1] ) * det_1;
1550  out[1][2] = -(in[0][0] * in[1][2] - in[0][2] * in[1][0] ) * det_1;
1551  out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0] ) * det_1;
1552 
1553  /* Calculat -C * inverse(A) */
1554  out[3][0] = -(in[3][0] * out[0][0] + in[3][1]*out[1][0] + in[3][2]*out[2][0]);
1555  out[3][1] = -(in[3][0] * out[0][1] + in[3][1]*out[1][1] + in[3][2]*out[2][1]);
1556  out[3][2] = -(in[3][0] * out[0][2] + in[3][1]*out[1][2] + in[3][2]*out[2][2]);
1557 
1558  /* Fill in last column */
1559  out[0][3] = out[1][3] = out[2][3] = 0.0;
1560  out[3][3] = 1.0;
1561  return TRUE;
1562  }
1563 }
1564 GLDOUBLE* matinverseAFFINE(GLDOUBLE* res, GLDOUBLE* mm){
1565  affine_matrix4x4_inverse_double(mm, res);
1566  return res;
1567 }
1568 GLDOUBLE* matinverseFULL(GLDOUBLE* res, GLDOUBLE* mm){
1569  matinverse98(res,mm);
1570  return res;
1571 }
1572 GLDOUBLE* matinverse(GLDOUBLE* res, GLDOUBLE* mm){
1573  matinverseFULL(res,mm);
1574  return res;
1575 }
1576 
1577 
1578 
1579 #ifdef COMMENT
1580 /*fast crossproduct using references, that checks for auto-assignments */
1581 GLDOUBLE* veccross(GLDOUBLE* r, GLDOUBLE* v1, GLDOUBLE* v2)
1582 {
1583  /*check against self-assignment. */
1584  if(r != v1) {
1585  if(r != v2) {
1586  r[0] = v1[1]*v2[2] - v1[2]*v2[1];
1587  r[1] = v1[2]*v2[0] - v1[0]*v2[2];
1588  r[2] = v1[0]*v2[1] - v1[1]*v2[0];
1589  } else { /* r == v2 */
1590  GLDOUBLE v2c[3] = {v2[0],v2[1],v2[2]};
1591  r[0] = v1[1]*v2c[2] - v1[2]*v2c[1];
1592  r[1] = v1[2]*v2c[0] - v1[0]*v2c[2];
1593  r[2] = v1[0]*v2c[1] - v1[1]*v2c[0];
1594  }
1595  } else { /* r == v1 */
1596  GLDOUBLE v1c[3] = {v1[0],v1[1],v1[2]};
1597  r[0] = v1c[1]*v2[2] - v1c[2]*v2[1];
1598  r[1] = v1c[2]*v2[0] - v1c[0]*v2[2];
1599  r[2] = v1c[0]*v2[1] - v1c[1]*v2[0];
1600  }
1601  return r;
1602 }
1603 
1604 
1605 
1606 #endif
1607 
1608 
1609 /*
1610  * apply a scale to the matrix given. Assumes matrix is valid...
1611  *
1612  */
1613 
1614 void scale_to_matrix (double *mat, struct point_XYZ *scale) {
1615 /* copy the definitions from quaternion.h... */
1616 #define MAT00 mat[0]
1617 #define MAT01 mat[1]
1618 #define MAT02 mat[2]
1619 #if DJ_KEEP_COMPILER_WARNING
1620 #define MAT03 mat[3]
1621 #endif
1622 #define MAT10 mat[4]
1623 #define MAT11 mat[5]
1624 #define MAT12 mat[6]
1625 #if DJ_KEEP_COMPILER_WARNING
1626 #define MAT13 mat[7]
1627 #endif
1628 #define MAT20 mat[8]
1629 #define MAT21 mat[9]
1630 #define MAT22 mat[10]
1631 #if DJ_KEEP_COMPILER_WARNING
1632 #define MAT23 mat[11]
1633 #define MAT30 mat[12]
1634 #define MAT31 mat[13]
1635 #define MAT32 mat[14]
1636 #define MAT33 mat[15]
1637 #endif
1638 
1639  MAT00 *=scale->x;
1640  MAT01 *=scale->x;
1641  MAT02 *=scale->x;
1642  MAT10 *=scale->y;
1643  MAT11 *=scale->y;
1644  MAT12 *=scale->y;
1645  MAT20 *=scale->z;
1646  MAT21 *=scale->z;
1647  MAT22 *=scale->z;
1648 }
1649 
1650 static double identity[] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
1651 
1652 void loadIdentityMatrix (double *mat) {
1653  memcpy((void *)mat, (void *)identity, sizeof(double)*16);
1654 }
1655 double *matcopy(double *r, double*mat){
1656  memcpy((void*)r, (void*)mat,sizeof(double)*16);
1657  return r;
1658 }
1659 float *matdouble2float4(float *rmat4, double *dmat4){
1660  int i;
1661  /* convert GLDOUBLE to float */
1662  for (i=0; i<16; i++) {
1663  rmat4[i] = (float)dmat4[i];
1664  }
1665  return rmat4;
1666 }
1667 void printmatrix3(GLDOUBLE *mat, char *description, int row_major){
1668  int i,j;
1669  printf("mat %s {\n",description);
1670  if(row_major){
1671  //prints in C row-major order, element numbers remain correct/same
1672  for(i = 0; i< 4; i++) {
1673  printf("mat [%2d-%2d] = ",i*4,(i*4)+3);
1674  for(j=0;j<4;j++)
1675  printf(" %lf ",mat[(i*4)+j]);
1676  printf("\n");
1677  }
1678  }
1679  if(!row_major){
1680  //prints in opengl column-major order, element numbers remain correct/same
1681  for(i=0;i<4;i++){
1682  printf("mat [%2d %2d %2d %2d] =",i,i+4,i+8,i+12);
1683  printf(" %lf %lf %lf %lf\n",mat[i],mat[i+4],mat[i+8],mat[i+12]);
1684  }
1685  }
1686  printf("}\n");
1687 }
1688 void printmatrix2(GLDOUBLE* mat,char* description ) {
1689  static int row_major = FALSE;
1690  printmatrix3(mat,description,row_major);
1691 }
1692 
1693 
1694 
1695 void general_slerp(double *ret, double *p1, double *p2, int size, const double t)
1696 {
1697  //not tested as of July16,2011
1698  //goal start slow, speed up in the middle, and slow down when stopping
1699  // (like a sine or cosine wave)
1700  //let omega = t*pi
1701  //then cos omega goes from 1 to -1 natively
1702  //we want scale0 to go from 1 to 0
1703  //scale0 = .5(1+cos(t*pi)) should be in the 1 to 0 range,
1704  //and be 'fastest' in the middle ie at pi/2
1705  //then scale1 = 1 - scale0
1706  double scale0, scale1, omega;
1707  int i;
1708  /* calculate coefficients */
1709  if (0) {
1710  //if ( t > .05 || t < .95 ) {
1711  /* standard case (SLERP) */
1712  omega = t*PI;
1713  scale0 = 0.5*(1.0 + cos(omega));
1714  scale1 = 1.0 - scale0;
1715  } else {
1716  /* p1 & p2 are very close, so do linear interpolation */
1717  scale0 = 1.0 - t;
1718  scale1 = t;
1719  }
1720  for(i=0;i<size;i++)
1721  ret[i] = scale0 * p1[i] + scale1 * p2[i];
1722 }
1723 void point_XYZ_slerp(struct point_XYZ *ret, struct point_XYZ *p1, struct point_XYZ *p2, const double t){
1724  double pret[3], pp1[3], pp2[3];
1725  pointxyz2double(pp1, p1);
1726  pointxyz2double(pp2, p2);
1727  general_slerp(pret, pp1, pp2, 3, t);
1728  double2pointxyz(ret,pret);
1729 }