]> icculus.org git repositories - taylor/freespace2.git/blob - include/vecmat.h
rendering functions mostly done; more complete shader setup
[taylor/freespace2.git] / include / vecmat.h
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Math/VecMat.h $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Header file for functions that manipulate vectors and matricies
16  *
17  * $Log$
18  * Revision 1.4  2005/08/12 08:52:32  taylor
19  * various GCC4 warning fixes
20  *
21  * Revision 1.3  2002/06/17 06:33:08  relnev
22  * ryan's struct patch for gcc 2.95
23  *
24  * Revision 1.2  2002/06/09 04:41:15  relnev
25  * added copyright header
26  *
27  * Revision 1.1.1.1  2002/05/03 03:28:12  root
28  * Initial import.
29  *
30  * 
31  * 6     6/18/99 5:16p Dave
32  * Added real beam weapon lighting. Fixed beam weapon sounds. Added MOTD
33  * dialog to PXO screen.
34  * 
35  * 5     4/28/99 11:13p Dave
36  * Temporary checkin of artillery code.
37  * 
38  * 4     1/24/99 11:37p Dave
39  * First full rev of beam weapons. Very customizable. Removed some bogus
40  * Int3()'s in low level net code.
41  * 
42  * 3     1/12/99 12:53a Dave
43  * More work on beam weapons - made collision detection very efficient -
44  * collide against all object types properly - made 3 movement types
45  * smooth. Put in test code to check for possible non-darkening pixels on
46  * object textures.
47  * 
48  * 2     10/07/98 10:53a Dave
49  * Initial checkin.
50  * 
51  * 1     10/07/98 10:49a Dave
52  * 
53  * 43    9/11/98 10:10a Andsager
54  * Optimize and rename matrix_decomp to vm_matrix_to_rot_axis_and_angle,
55  * rename quatern_rot to vm_quaternion_rotate
56  * 
57  * 42    3/09/98 3:51p Mike
58  * More error checking.
59  * 
60  * 41    12/17/97 5:44p Andsager
61  * Change vm_matrix_interpolate so that it does not overshoot if optional
62  * last parameter is 1
63  * 
64  * 40    9/30/97 8:03p Lawrance
65  * add missing semi-colon to function prototype
66  * 
67  * 39    9/30/97 5:04p Andsager
68  * add vm_estimate_next_orientation
69  * 
70  * 38    9/28/97 2:17p Andsager
71  * added vm_project_point_onto_plane
72  * 
73  * 37    9/25/97 5:57p Andsager
74  * improved function description for matrix interpolate
75  * 
76  * 36    9/09/97 10:15p Andsager
77  * added vm_rotate_vec_to_body() and vm_rotate_vec_to_world()
78  * 
79  * 35    8/20/97 5:33p Andsager
80  * added vm_vec_projection_parallel and vm_vec_projection_onto_surface
81  * 
82  * 34    8/19/97 11:42p Lawrance
83  * use atan2_safe() instead of atan2()
84  * 
85  * 33    8/18/97 4:46p Hoffoss
86  * Added global default axis vector constants.
87  * 
88  * 32    8/03/97 3:54p Lawrance
89  * added vm_find_bounding_sphere()
90  * 
91  * 31    7/30/97 2:20p Dan
92  * from allender: fixed vm_is_vec_nan to work properly with address-of
93  * operator by adding parens around macro variables
94  * 
95  * 30    7/29/97 2:48p Hoffoss
96  * Added vm_is_vec_nan().
97  * 
98  * 29    7/28/97 2:21p John
99  * changed vecmat functions to not return src.  Started putting in code
100  * for inline vector math.    Fixed some bugs with optimizer.
101  * 
102  * 28    7/28/97 3:25p Andsager
103  * 
104  * 27    7/28/97 2:41p Mike
105  * Replace vm_forward_interpolate().
106  * 
107  * 26    7/28/97 1:18p Andsager
108  * implement vm_fvec_matrix_interpolate(), which interpolates matrices on
109  * xy and then z
110  * 
111  * 25    7/24/97 5:24p Andsager
112  * implement forward vector interpolation
113  * 
114  * 24    7/02/97 4:25p Mike
115  * Add matrix_interpolate(), but don't call it.
116  * 
117  * 23    7/01/97 3:27p Mike
118  * Improve skill level support.
119  * 
120  * 22    6/25/97 12:27p Hoffoss
121  * Added some functions I needed for Fred.
122  * 
123  * 21    5/21/97 8:49a Lawrance
124  * added vm_vec_same()
125  * 
126  * 20    4/15/97 4:00p Mike
127  * Intermediate checkin caused by getting other files.  Working on camera
128  * slewing system.
129  * 
130  * 19    3/17/97 1:55p Hoffoss
131  * Added function for error checking matrices.
132  * 
133  * 18    3/06/97 10:56a Mike
134  * Write error checking version of vm_vec_normalize().
135  * Fix resultant problems.
136  * 
137  * 17    3/04/97 3:30p John
138  * added function to interpolate an angle.
139  * 
140  * 16    2/25/97 5:12p John
141  * Added functions to see if two matrices or vectors are close.
142  * 
143  * 15    2/03/97 1:30p John
144  * Put a clearer comment in for vm_vec_unrotate
145  * 
146  * 14    2/03/97 1:14p John
147  * Added vm_vec_unrotate function
148  * 
149  * 13    1/27/97 11:57a John
150  * added a function to rotate a point around an arbritary line.
151  * 
152  * 12    11/26/96 12:18p Hoffoss
153  * Added the vm_vec_dist_squared() function.
154  * 
155  * 11    11/16/96 2:38p Mike
156  * Waypoint code, under construction and a painful mess.
157  * 
158  * 10    11/05/96 3:42p Mike
159  * Make AI use accuracy parameter, though not yet specified in ships.tbl
160  * or *.fsm.
161  * 
162  * Add vm_vec_rand_vec_quick.
163  * 
164  * Add frand() which returns a rand in 0.0..1.0.
165  * 
166  * 9     10/30/96 2:35p Mike
167  * Docking behavior.
168  * Changed quick versions of vecmat routines to not return 1/mag.  They
169  * return mag, just like non-quick versions.
170  * 
171  * 8     10/24/96 10:17a Hoffoss
172  * Moved function 'compute_point_on_plane()' to vecmat.
173  * 
174  * 7     10/23/96 10:32p Lawrance
175  * added function vm_vect_mag_squared()
176  *
177  * $NoKeywords: $
178  *
179 */
180
181 #ifndef _VECMAT_H
182 #define _VECMAT_H
183
184 #include <float.h>
185 #include "pstypes.h"
186
187 //#define _INLINE_VECMAT
188
189 #define vm_is_vec_nan(v) (isnan((v)->xyz.x) || isnan((v)->xyz.y) || isnan((v)->xyz.z))
190
191 //Macros/functions to fill in fields of structures
192
193 //macro to check if vector is zero
194 #define IS_VEC_NULL(v) (((v)->xyz.x == (float)0.0) && ((v)->xyz.y == (float)0.0) && ((v)->xyz.z == (float)0.0))
195
196 //macro to set a vector to zero.  we could do this with an in-line assembly
197 //macro, but it's probably better to let the compiler optimize it.
198 //Note: NO RETURN VALUE
199 #define vm_vec_zero(v) (v)->xyz.x=(v)->xyz.y=(v)->xyz.z=(float)0.0
200
201 /*
202 //macro set set a matrix to the identity. Note: NO RETURN VALUE
203 #define vm_set_identity(m) do {m->rvec.x = m->uvec.y = m->fvec.z = (float)1.0;  \
204                                                                                 m->rvec.xyz.y = m->rvec.xyz.z = \
205                                                                                 m->uvec.xyz.x = m->uvec.xyz.z = \
206                                                                                 m->fvec.xyz.x = m->fvec.xyz.y = (float)0.0;} while (0)
207 */
208 extern void vm_set_identity(matrix *m);
209
210 #define vm_vec_make(v,_x,_y,_z) (((v)->xyz.x=(_x), (v)->xyz.y=(_y), (v)->xyz.z=(_z)), (v))
211
212 //Global constants
213
214 extern vector vmd_zero_vector;
215 extern vector vmd_x_vector;
216 extern vector vmd_y_vector;
217 extern vector vmd_z_vector;
218 extern matrix vmd_identity_matrix;
219
220 //Here's a handy constant
221
222 #define ZERO_VECTOR { { { 0.0f, 0.0f, 0.0f } } }
223 //#define IDENTITY_MATRIX {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f}
224 // first set of inside braces is for union, second set is for inside union, then for a2d[3][3] (some compiler warning messages just suck)
225 #define IDENTITY_MATRIX { { { { { { 1.0f, 0.0f, 0.0f } } }, { { { 0.0f, 1.0f, 0.0f } } }, { { { 0.0f, 0.0f, 1.0f } } } } } }
226
227
228 //fills in fields of an angle vector
229 #define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v))
230
231 //negate a vector
232 #define vm_vec_negate(v) do {(v)->xyz.x = - (v)->xyz.x; (v)->xyz.y = - (v)->xyz.y; (v)->xyz.z = - (v)->xyz.z;} while (0);
233
234 typedef struct plane {
235         float   A, B, C, D;
236 } plane;
237
238 //Functions in library
239
240 //adds two vectors, fills in dest, returns ptr to dest
241 //ok for dest to equal either source, but should use vm_vec_add2() if so
242 #ifdef _INLINE_VECMAT
243 #define vm_vec_add( dst, src0, src1 ) do {      \
244         (dst)->xyz.x = (src0)->xyz.x + (src1)->xyz.x;                                   \
245         (dst)->xyz.y = (src0)->xyz.y + (src1)->xyz.y;                                   \
246         (dst)->xyz.z = (src0)->xyz.z + (src1)->xyz.z;                                   \
247 } while(0) 
248 #else
249 void vm_vec_add(vector *dest,vector *src0,vector *src1);
250 #endif
251
252 //adds src onto dest vector, returns ptr to dest
253 #ifdef _INLINE_VECMAT
254 #define vm_vec_add2( dst, src ) do {    \
255         (dst)->xyz.x += (src)->xyz.x;                                   \
256         (dst)->xyz.y += (src)->xyz.y;                                   \
257         (dst)->xyz.z += (src)->xyz.z;                                   \
258 } while(0) 
259 #else
260 void vm_vec_add2(vector *dest,vector *src);
261 #endif
262
263
264 //scales a vector and subs from to another
265 //dest -= k * src
266 #ifdef _INLINE_VECMAT
267 #define vm_vec_scale_sub2( dst, src, k ) do {   \
268         float tmp_k = (k);                                                              \
269         (dst)->xyz.x -= (src)->xyz.x*tmp_k;                                     \
270         (dst)->xyz.y -= (src)->xyz.y*tmp_k;                                     \
271         (dst)->xyz.z -= (src)->xyz.z*tmp_k;                                     \
272 } while(0) 
273 #else
274 void vm_vec_scale_sub2(vector *dest,vector *src, float k);
275 #endif
276
277 //subs two vectors, fills in dest, returns ptr to dest
278 //ok for dest to equal either source, but should use vm_vec_sub2() if so
279 #ifdef _INLINE_VECMAT
280 #define vm_vec_sub( dst, src0, src1 ) do {      \
281         (dst)->xyz.x = (src0)->xyz.x - (src1)->xyz.x;                                   \
282         (dst)->xyz.y = (src0)->xyz.y - (src1)->xyz.y;                                   \
283         (dst)->xyz.z = (src0)->xyz.z - (src1)->xyz.z;                                   \
284 } while(0) 
285 #else
286 void vm_vec_sub(vector *dest,vector *src0,vector *src1);
287 #endif
288
289
290 //subs one vector from another, returns ptr to dest
291 //dest can equal source
292 #ifdef _INLINE_VECMAT
293 #define vm_vec_sub2( dst, src ) do {    \
294         (dst)->xyz.x -= (src)->xyz.x;                                   \
295         (dst)->xyz.y -= (src)->xyz.y;                                   \
296         (dst)->xyz.z -= (src)->xyz.z;                                   \
297 } while(0) 
298 #else
299 void vm_vec_sub2(vector *dest,vector *src);
300 #endif
301
302
303 //averages two vectors. returns ptr to dest
304 //dest can equal either source
305 vector *vm_vec_avg(vector *dest,vector *src0,vector *src1);
306
307 //averages four vectors. returns ptr to dest
308 //dest can equal any source
309 vector *vm_vec_avg4(vector *dest,vector *src0,vector *src1,vector *src2,vector *src3);
310
311 //scales a vector in place.  returns ptr to vector
312 #ifdef _INLINE_VECMAT
313 #define vm_vec_scale( dst, k ) do {     \
314         float tmp_k = (k);                                                              \
315         (dst)->xyz.x *= tmp_k;                                  \
316         (dst)->xyz.y *= tmp_k;                                  \
317         (dst)->xyz.z *= tmp_k;                                  \
318 } while(0) 
319 #else
320 void vm_vec_scale(vector *dest,float s);
321 #endif
322
323 //scales and copies a vector.  returns ptr to dest
324 #ifdef _INLINE_VECMAT
325 #define vm_vec_copy_scale( dst, src, k ) do {   \
326         float tmp_k = (k);                                                              \
327         (dst)->xyz.x = (src)->xyz.x * tmp_k;                                    \
328         (dst)->xyz.y = (src)->xyz.y * tmp_k;                                    \
329         (dst)->xyz.z = (src)->xyz.z * tmp_k;                                    \
330 } while(0) 
331 #else
332 void vm_vec_copy_scale(vector *dest,vector *src,float s);
333 #endif
334
335 //scales a vector, adds it to another, and stores in a 3rd vector
336 //dest = src1 + k * src2
337 #ifdef _INLINE_VECMAT
338 #define vm_vec_scale_add( dst, src1, src2, k ) do {     \
339         float tmp_k = (k);                                                              \
340         (dst)->xyz.x = (src1)->xyz.x + (src2)->xyz.x * tmp_k;                                   \
341         (dst)->xyz.y = (src1)->xyz.y + (src2)->xyz.y * tmp_k;                                   \
342         (dst)->xyz.z = (src1)->xyz.z + (src2)->xyz.z * tmp_k;                                   \
343 } while(0) 
344 #else
345 void vm_vec_scale_add(vector *dest,vector *src1,vector *src2,float k);
346 #endif
347
348
349 //scales a vector and adds it to another
350 //dest += k * src
351 #ifdef _INLINE_VECMAT
352 #define vm_vec_scale_add2( dst, src, k ) do {   \
353         float tmp_k = (k);                                                              \
354         (dst)->xyz.x += (src)->xyz.x * tmp_k;                                   \
355         (dst)->xyz.y += (src)->xyz.y * tmp_k;                                   \
356         (dst)->xyz.z += (src)->xyz.z * tmp_k;                                   \
357 } while(0) 
358 #else
359 void vm_vec_scale_add2(vector *dest,vector *src,float k);
360 #endif
361
362 //scales a vector in place, taking n/d for scale.  returns ptr to vector
363 //dest *= n/d
364 #ifdef _INLINE_VECMAT
365 #define vm_vec_scale2( dst, n, d ) do { \
366         float tmp_k = (n)/(d);                                                          \
367         (dst)->xyz.x *= tmp_k;                                  \
368         (dst)->xyz.y *= tmp_k;                                  \
369         (dst)->xyz.z *= tmp_k;                                  \
370 } while(0) 
371 #else
372 void vm_vec_scale2(vector *dest,float n,float d);
373 #endif
374
375 // finds the projection of source vector along a unit vector
376 // returns the magnitude of the component
377 float vm_vec_projection_parallel (vector *component, vector *src, vector *unit_vector);
378
379 // finds the projection of source vector onto a surface given by surface normal
380 void vm_vec_projection_onto_plane (vector *projection, vector *src, vector *normal);
381
382 //returns magnitude of a vector
383 float vm_vec_mag(vector *v);
384
385 // returns the square of the magnitude of a vector (useful if comparing distances)
386 float vm_vec_mag_squared(vector* v);
387
388 // returns the square of the distance between two points (fast and exact)
389 float vm_vec_dist_squared(vector *v0, vector *v1);
390
391 //computes the distance between two points. (does sub and mag)
392 float vm_vec_dist(vector *v0,vector *v1);
393
394 //computes an approximation of the magnitude of the vector
395 //uses dist = largest + next_largest*3/8 + smallest*3/16
396 float vm_vec_mag_quick(vector *v);
397
398 //computes an approximation of the distance between two points.
399 //uses dist = largest + next_largest*3/8 + smallest*3/16
400 float vm_vec_dist_quick(vector *v0,vector *v1);
401
402
403 //normalize a vector. returns mag of source vec
404 float vm_vec_copy_normalize(vector *dest,vector *src);
405 float vm_vec_normalize(vector *v);
406
407 //      This version of vector normalize checks for the null vector before normalization.
408 //      If it is detected, it generates a Warning() and returns the vector 1, 0, 0.
409 float vm_vec_normalize_safe(vector *v);
410
411 //normalize a vector. returns mag of source vec. uses approx mag
412 float vm_vec_copy_normalize_quick(vector *dest,vector *src);
413 float vm_vec_normalize_quick(vector *v);
414
415 //normalize a vector. returns mag of source vec. uses approx mag
416 float vm_vec_copy_normalize_quick_mag(vector *dest,vector *src);
417 float vm_vec_normalize_quick_mag(vector *v);
418
419 //return the normalized direction vector between two points
420 //dest = normalized(end - start).  Returns mag of direction vector
421 //NOTE: the order of the parameters matches the vector subtraction
422 float vm_vec_normalized_dir(vector *dest,vector *end,vector *start);
423 float vm_vec_normalized_dir_quick_mag(vector *dest,vector *end,vector *start);
424 // Returns mag of direction vector
425 float vm_vec_normalized_dir_quick(vector *dest,vector *end,vector *start);
426
427 ////returns dot product of two vectors
428 #ifdef _INLINE_VECMAT
429 #define vm_vec_dotprod( v0, v1 ) (((v1)->xyz.x*(v0)->xyz.x)+((v1)->xyz.y*(v0)->xyz.y)+((v1)->xyz.z*(v0)->xyz.z))
430 #define vm_vec_dot( v0, v1 ) (((v1)->xyz.x*(v0)->xyz.x)+((v1)->xyz.y*(v0)->xyz.y)+((v1)->xyz.z*(v0)->xyz.z))
431 #else
432 float vm_vec_dotprod(vector *v0,vector *v1);
433 #define vm_vec_dot vm_vec_dotprod
434 #endif
435
436 #ifdef _INLINE_VECMAT
437 #define vm_vec_dot3( x1, y1, z1, v ) (((x1)*(v)->xyz.x)+((y1)*(v)->xyz.y)+((z1)*(v)->xyz.z))
438 #else
439 float vm_vec_dot3(float x,float y,float z,vector *v);
440 #endif
441
442 //computes cross product of two vectors. returns ptr to dest
443 //dest CANNOT equal either source
444 vector *vm_vec_crossprod(vector *dest,vector *src0,vector *src1);
445 #define vm_vec_cross vm_vec_crossprod
446
447 // test if 2 vectors are parallel or not.
448 int vm_test_parallel(vector *src0, vector *src1);
449
450 //computes surface normal from three points. result is normalized
451 //returns ptr to dest
452 //dest CANNOT equal either source
453 vector *vm_vec_normal(vector *dest,vector *p0,vector *p1,vector *p2);
454
455 //computes non-normalized surface normal from three points.
456 //returns ptr to dest
457 //dest CANNOT equal either source
458 vector *vm_vec_perp(vector *dest,vector *p0,vector *p1,vector *p2);
459
460 //computes the delta angle between two vectors.
461 //vectors need not be normalized. if they are, call vm_vec_delta_ang_norm()
462 //the forward vector (third parameter) can be NULL, in which case the absolute
463 //value of the angle in returned.  Otherwise the angle around that vector is
464 //returned.
465 float vm_vec_delta_ang(vector *v0,vector *v1,vector *fvec);
466
467 //computes the delta angle between two normalized vectors.
468 float vm_vec_delta_ang_norm(vector *v0,vector *v1,vector *fvec);
469
470 //computes a matrix from a set of three angles.  returns ptr to matrix
471 matrix *vm_angles_2_matrix(matrix *m,angles *a);
472
473 //      Computes a matrix from a single angle.
474 //      angle_index = 0,1,2 for p,b,h
475 matrix *vm_angle_2_matrix(matrix *m, float a, int angle_index);
476
477 //computes a matrix from a forward vector and an angle
478 matrix *vm_vec_ang_2_matrix(matrix *m,vector *v,float a);
479
480 //computes a matrix from one or more vectors. The forward vector is required,
481 //with the other two being optional.  If both up & right vectors are passed,
482 //the up vector is used.  If only the forward vector is passed, a bank of
483 //zero is assumed
484 //returns ptr to matrix
485 matrix *vm_vector_2_matrix(matrix *m,vector *fvec,vector *uvec,vector *rvec);
486
487 //this version of vector_2_matrix requires that the vectors be more-or-less
488 //normalized and close to perpendicular
489 matrix *vm_vector_2_matrix_norm(matrix *m,vector *fvec,vector *uvec,vector *rvec);
490
491 //rotates a vector through a matrix. returns ptr to dest vector
492 //dest CANNOT equal either source
493 vector *vm_vec_rotate(vector *dest,vector *src,matrix *m);
494
495 //rotates a vector through the transpose of the given matrix. 
496 //returns ptr to dest vector
497 //dest CANNOT equal source
498 // This is a faster replacement for this common code sequence:
499 //    vm_copy_transpose_matrix(&tempm,src_matrix);
500 //    vm_vec_rotate(dst_vec,src_vect,&tempm);
501 // Replace with:
502 //    vm_vec_unrotate(dst_vec,src_vect, src_matrix)
503 //
504 // THIS DOES NOT ACTUALLY TRANSPOSE THE SOURCE MATRIX!!! So if
505 // you need it transposed later on, you should use the 
506 // vm_vec_transpose() / vm_vec_rotate() technique.
507 vector *vm_vec_unrotate(vector *dest,vector *src,matrix *m);
508
509 //transpose a matrix in place. returns ptr to matrix
510 matrix *vm_transpose_matrix(matrix *m);
511 #define vm_transpose(m) vm_transpose_matrix(m)
512
513 //copy and transpose a matrix. returns ptr to matrix
514 //dest CANNOT equal source. use vm_transpose_matrix() if this is the case
515 matrix *vm_copy_transpose_matrix(matrix *dest,matrix *src);
516 #define vm_copy_transpose(dest,src) vm_copy_transpose_matrix((dest),(src))
517
518 //mulitply 2 matrices, fill in dest.  returns ptr to dest
519 //dest CANNOT equal either source
520 matrix *vm_matrix_x_matrix(matrix *dest,matrix *src0,matrix *src1);
521
522 //extract angles from a matrix
523 angles *vm_extract_angles_matrix(angles *a,matrix *m);
524
525 //extract heading and pitch from a vector, assuming bank==0
526 angles *vm_extract_angles_vector(angles *a,vector *v);
527
528 //make sure matrix is orthogonal
529 void vm_orthogonalize_matrix(matrix *m_src);
530
531 // like vm_orthogonalize_matrix(), except that zero vectors can exist within the
532 // matrix without causing problems.  Valid vectors will be created where needed.
533 void vm_fix_matrix(matrix *m);
534
535 //Rotates the orient matrix by the angles in tangles and then
536 //makes sure that the matrix is orthogonal.
537 void vm_rotate_matrix_by_angles( matrix *orient, angles *tangles );
538
539 //compute the distance from a point to a plane.  takes the normalized normal
540 //of the plane (ebx), a point on the plane (edi), and the point to check (esi).
541 //returns distance in eax
542 //distance is signed, so negative dist is on the back of the plane
543 float vm_dist_to_plane(vector *checkp,vector *norm,vector *planep);
544
545 // Given mouse movement in dx, dy, returns a 3x3 rotation matrix in RotMat.
546 // Taken from Graphics Gems III, page 51, "The Rolling Ball"
547 // Example:
548 //if ( (Mouse.dx!=0) || (Mouse.dy!=0) ) {
549 //   vm_trackball( Mouse.dx, Mouse.dy, &MouseRotMat );
550 //   vm_matrix_x_matrix(&tempm,&LargeView.ev_matrix,&MouseRotMat);
551 //   LargeView.ev_matrix = tempm;
552 //}
553 void vm_trackball( int idx, int idy, matrix * RotMat );
554
555 //      Find the point on the line between p0 and p1 that is nearest to int_pnt.
556 //      Stuff result in nearest_point.
557 //      Return value indicated where on the line *nearest_point lies.  Between 0.0f and 1.0f means it's
558 //      in the line segment.  Positive means beyond *p1, negative means before *p0.  2.0f means it's
559 //      beyond *p1 by 2x.
560 float find_nearest_point_on_line(vector *nearest_point, vector *p0, vector *p1, vector *int_pnt);
561
562 float vm_vec_dot_to_point(vector *dir, vector *p1, vector *p2);
563
564 void compute_point_on_plane(vector *q, plane *planep, vector *p);
565
566 // ----------------------------------------------------------------------------
567 // computes the point on a plane closest to a given point (which may be on the plane)
568 // 
569 //              inputs:         new_point               =>              point on the plane [result]
570 //                                              point                           =>              point to compute closest plane point
571 //                                              plane_normal    =>              plane normal
572 //                                              plane_point             =>              plane point
573 void vm_project_point_onto_plane(vector *new_point, vector *point, vector *plane_normal, vector *plane_point);
574
575
576 //      Returns fairly random vector, "quick" normalized
577 void vm_vec_rand_vec_quick(vector *rvec);
578
579 // Given an point "in" rotate it by "angle" around an
580 // arbritary line defined by a point on the line "line_point" 
581 // and the normalized line direction, "line_dir"
582 // Returns the rotated point in "out".
583 void vm_rot_point_around_line(vector *out, vector *in, float angle, vector *line_point, vector *line_dir);
584
585 // Given two position vectors, return 0 if the same, else non-zero.
586 int vm_vec_cmp( vector * a, vector * b );
587
588 // Given two orientation matrices, return 0 if the same, else non-zero.
589 int vm_matrix_cmp( matrix * a, matrix * b );
590
591 // Moves angle 'h' towards 'desired_angle', taking the shortest
592 // route possible.   It will move a maximum of 'step_size' radians
593 // each call.   All angles in radians.
594 void vm_interp_angle( float *h, float desired_angle, float step_size );
595
596 // check a matrix for zero rows and columns
597 int vm_check_matrix_for_zeros(matrix *m);
598
599 // see if two vectors are identical
600 int vm_vec_same(vector *v1, vector *v2);
601
602 //      Interpolate from a start matrix toward a goal matrix, minimizing time between orientations.
603 // Moves at maximum rotational acceleration toward the goal when far and then max deceleration when close.
604 // Subject to constaints on rotational velocity and angular accleleration.
605 // Returns next_orientation valid at time delta_t.
606 void vm_matrix_interpolate(matrix *goal_orient, matrix *start_orient, vector *rotvel_in, float delta_t, 
607                 matrix *next_orient, vector *rotvel_out, vector *rotvel_limit, vector *acc_limit, int no_overshoot=0);
608
609 //      Interpolate from a start forward vec toward a goal forward vec, minimizing time between orientations.
610 // Moves at maximum rotational acceleration toward the goal when far and then max deceleration when close.
611 // Subject to constaints on rotational velocity and angular accleleration.
612 // Returns next forward vec valid at time delta_t.
613 void vm_forward_interpolate(vector *goal_fvec, matrix *orient, vector *rotvel_in, float delta_t, float delta_bank,
614                 matrix *next_orient, vector *rotvel_out, vector *vel_limit, vector *acc_limit, int no_overshoot=0);
615
616 // Find the bounding sphere for a set of points (center and radius are output parameters)
617 void vm_find_bounding_sphere(vector *pnts, int num_pnts, vector *center, float *radius);
618
619 // Version of atan2() that is safe for optimized builds
620 float atan2_safe(float x, float y);
621
622 // Translates from world coordinates to body coordinates
623 vector* vm_rotate_vec_to_body(vector *body_vec, vector *world_vec, matrix *orient);
624
625 // Translates from body coordinates to world coordiantes
626 vector* vm_rotate_vec_to_world(vector *world_vec, vector *body_vec, matrix *orient);
627
628 // estimate next orientation matrix as extrapolation of last and current
629 void vm_estimate_next_orientation(matrix *last_orient, matrix *current_orient, matrix *next_orient);
630
631 //      Return true if all elements of *vec are legal, that is, not a NAN.
632 int is_valid_vec(vector *vec);
633
634 //      Return true if all elements of *m are legal, that is, not a NAN.
635 int is_valid_matrix(matrix *m);
636
637 // Finds the rotation matrix corresponding to a rotation of theta about axis u
638 void vm_quaternion_rotate(matrix *m, float theta, vector *u);
639
640 // Takes a rotation matrix and returns the axis and angle needed to generate it
641 void vm_matrix_to_rot_axis_and_angle(matrix *m, float *theta, vector *rot_axis);
642
643 // interpolate between 2 vectors. t goes from 0.0 to 1.0. at
644 void vm_vec_interp_constant(vector *out, vector *v1, vector *v2, float t);
645
646 // randomly perturb a vector around a given (normalized vector) or optional orientation matrix
647 void vm_vec_random_cone(vector *out, vector *in, float max_angle, matrix *orient = NULL);
648
649 // given a start vector, an orientation and a radius, give a point on the plane of the circle
650 // if on_edge is 1, the point is on the very edge of the circle
651 void vm_vec_random_in_circle(vector *out, vector *in, matrix *orient, float radius, int on_edge);
652
653 // find the nearest point on the line to p. if dist is non-NULL, it is filled in
654 // returns 0 if the point is inside the line segment, -1 if "before" the line segment and 1 ir "after" the line segment
655 int vm_vec_dist_to_line(vector *p, vector *l0, vector *l1, vector *nearest, float *dist);
656
657 #endif
658