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