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