1 /* $Id: vecmat.h,v 1.5 2004-05-19 01:47:24 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * Header file for vector/matrix library
20 * Revision 1.1 1995/04/17 16:18:05 allender
24 * --- PC RCS Information ---
25 * Revision 1.37 1995/02/22 13:23:22 john
26 * Added the vms_vector_array structure, to access a vms_vector
29 * Revision 1.36 1995/02/22 12:34:33 john
30 * Took out anonymous unions.
32 * Revision 1.35 1994/12/13 14:44:20 matt
33 * Added vm_vector_2_matrix_norm()
35 * Revision 1.34 1994/09/11 19:22:55 matt
36 * Added vm_vec_normalized_dir_quick()
38 * Revision 1.33 1994/08/04 19:45:38 matt
39 * Added option to make a bunch of functions (add, sub, dotprod) inline
41 * Revision 1.32 1994/07/19 18:52:36 matt
42 * Added vm_vec_normalize_quick() and vm_vec_copy_normalize_quick()
44 * Revision 1.31 1994/06/16 18:24:30 matt
45 * Added vm_vec_mag_quick()
47 * Revision 1.30 1994/06/10 23:19:00 matt
48 * New register usage for vm_vec_ang_2_matrix()
50 * Revision 1.29 1994/06/01 17:32:06 matt
51 * Fixed modify list for vm_vec_normalized_dir()
53 * Revision 1.28 1994/05/19 12:07:20 matt
54 * Fixed globals and macros and added a constant
56 * Revision 1.27 1994/05/19 09:19:15 matt
57 * Made vm_vec_normalized_dir() return mag of vector
59 * Revision 1.26 1994/05/18 22:28:57 matt
60 * Added function vm_vec_normalized_dir()
61 * Added C macros IS_ZERO_VEC(), vm_vec_zero(), and vm_set_identity()
62 * Added C global static vars vmd_zero_vector & vmd_identity_matrix
64 * Revision 1.25 1994/05/18 21:45:06 matt
66 * vm_extract_angles_vector()
67 * vm_extract_angles_vector_normalized()
68 * vm_vec_copy_normalize()
70 * Revision 1.24 1994/05/13 12:42:16 matt
71 * Added new function, vm_vec_dist_quick(), which does an approximation.
73 * Revision 1.23 1994/03/30 13:37:34 matt
74 * Added prototype for vm_vec_scale_add(), and fixed typos
76 * Revision 1.22 1994/03/30 13:29:42 matt
77 * Header for vm_vec_scale_add2()
79 * Revision 1.21 1994/01/31 19:45:13 matt
80 * Added function vm_extract_angles_matrix()
82 * Revision 1.20 1993/12/21 19:46:14 matt
83 * Added function vm_dist_to_plane()
85 * Revision 1.19 1993/12/13 17:26:41 matt
88 * Revision 1.18 1993/12/02 12:45:11 matt
89 * New functions: vm_vec_copy_scale(), vm_vec_scale2()
90 * Aliases: vm_transpose(), vm_vec_dot(), vm_vec_cross(), vm_copy_transpose()
92 * Revision 1.17 1993/10/29 22:38:36 matt
93 * Changed matrix order, making direction vectors the rows
95 * Revision 1.16 1993/10/25 11:49:57 matt
96 * Made vm_vec_delta_ang() take optional forward vector to return signed delta
98 * Revision 1.15 1993/10/20 01:10:05 matt
99 * Added vm_vec_delta_ang(), vm_vec_delta_ang_norm(), and vm_vec_ang_2_matrix()
101 * Revision 1.14 1993/10/17 17:02:52 matt
102 * vm_vector_2_matrix() now takes optional right vector
104 * Revision 1.13 1993/10/12 19:31:39 matt
105 * Added IDENTITY_MATRIX constant
107 * Revision 1.12 1993/10/08 18:10:16 matt
108 * Changed vm_vec_make() and vm_angvec_make() to be inline assembly
109 * functions, to get rid of compiler warnings. Did not change vm_mat_make(),
110 * which could still get warnings if the return value is unused.
112 * Revision 1.11 1993/09/29 12:10:07 matt
113 * Changed modified regs in pragmas to include return register
115 * Revision 1.10 1993/09/28 12:15:41 matt
116 * Added func vm_vector_2_matrix()
118 * Revision 1.9 1993/09/24 21:18:38 matt
119 * Added vm_vec_avg(), vm_vec_avg4(), and vm_angvec_make().
120 * Documented which functions could have dest==source
122 * Revision 1.8 1993/09/20 14:56:11 matt
123 * Added new function, vm_vec_perp()
125 * Revision 1.7 1993/09/20 14:27:42 mike
126 * unfix last fix which introduced a bug
128 * Revision 1.6 1993/09/20 10:11:53 mike
131 * Revision 1.5 1993/09/20 09:58:58 mike
134 * Revision 1.4 1993/09/20 09:41:21 mike
135 * Correct vm_vec_make and vm_mat_make macros to return the destination
136 * as the value of the macro.
138 * Revision 1.3 1993/09/17 11:23:47 matt
139 * Added row access (via xrow,yrow,zrow) to vms_matrix
140 * Added macro vm_mat_make(), like vm_vec_make()
142 * Revision 1.2 1993/09/17 11:10:32 matt
143 * Added vm_vec_add2() and vm_vec_sub2(), which take 2 args (dest==src0)
145 * Revision 1.1 1993/09/16 20:10:01 matt
156 //#define INLINE 1 //are some of these functions inline?
158 //The basic fixed-point vector. Access elements by name or position
159 typedef struct vms_vector
166 typedef struct vms_vector_array
170 __pack__ vms_vector_array;
173 //Short vector, used for pre-rotation points.
174 //Access elements by name or position
175 typedef struct vms_svec
177 short sv_x, sv_y, sv_z;
182 //Angle vector. Used to store orientations
183 typedef struct vms_angvec
190 //A 3x3 rotation matrix. Sorry about the numbering starting with one.
191 //Ordering is across then down, so <m1,m2,m3> is the first row
192 typedef struct vms_matrix
194 vms_vector rvec, uvec, fvec;
199 //Macros/functions to fill in fields of structures
201 //macro to check if vector is zero
202 #define IS_VEC_NULL(v) (v->x == 0 && v->y == 0 && v->z == 0)
204 //macro to set a vector to zero. we could do this with an in-line assembly
205 //macro, but it's probably better to let the compiler optimize it.
206 //Note: NO RETURN VALUE
207 #define vm_vec_zero(v) (v)->x=(v)->y=(v)->z=0
209 //macro set set a matrix to the identity. Note: NO RETURN VALUE
211 // DPH (18/9/98): Begin mod to fix linefeed problem under linux. Uses an
212 // inline function instead of a multi-line macro to fix CR/LF problems.
215 static inline void vm_set_identity(vms_matrix *m)
217 m->rvec.x = m->uvec.y = m->fvec.z = f1_0;
218 m->rvec.y = m->rvec.z = m->uvec.x = m->uvec.z = m->fvec.x = m->fvec.y = 0;
221 #define vm_set_identity(m) do {m->rvec.x = m->uvec.y = m->fvec.z = f1_0; \
222 m->rvec.y = m->rvec.z = \
223 m->uvec.x = m->uvec.z = \
224 m->fvec.x = m->fvec.y = 0;} while (0)
227 // DPH (19/8/98): End changes.
229 vms_vector * vm_vec_make (vms_vector * v, fix x, fix y, fix z);
233 #pragma aux vm_vec_make "*_" parm [eax] [edx] [ebx] [ecx] value [eax] modify exact [] = \
240 vms_angvec * vm_angvec_make (vms_angvec * v, fixang p, fixang b, fixang h);
244 #pragma aux vm_angvec_make "*_" parm [eax] [dx] [bx] [cx] value [eax] modify exact [] = \
253 extern vms_vector vmd_zero_vector;
255 extern vms_matrix vmd_identity_matrix;
258 //Here's a handy constant
260 #define ZERO_VECTOR {0,0,0}
261 #define IDENTITY_MATRIX { {f1_0,0,0}, {0,f1_0,0}, {0,0,f1_0} }
263 //#define vm_vec_make(v,_x,_y,_z) (((v)->x=(_x), (v)->y=(_y), (v)->z=(_z)), (v))
265 //#pragma off (unreferenced)
266 ////make this local, so compiler can in-line it
267 //static vms_vector *vm_vec_make(vms_vector *v,fix x,fix y,fix z)
275 //#pragma on (unreferenced)
278 ////macro to fill in elements of a matrix, also for Mike
280 #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \
281 do { (m)->m1=(_m1); (m)->m2=(_m2); (m)->m3=(_m3); \
282 (m)->m4=(_m4); (m)->m5=(_m5); (m)->m6=(_m6); \
283 (m)->m7=(_m7); (m)->m8=(_m8); (m)->m9=(_m9);} while (0)
286 #if 0 //kill this, since bogus with new matrix ordering
288 //macro to fill in elements of a matrix, also for Mike
289 #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \
290 (((m)->m1 = (_m1), (m)->m2 = (_m2), (m)->m3 = (_m3), \
291 (m)->m4 = (_m4), (m)->m5 = (_m5), (m)->m6 = (_m6), \
292 (m)->m7 = (_m7), (m)->m8 = (_m8), (m)->m9 = (_m9)), (m))
296 ////fills in fields of an angle vector
297 //#define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v))
300 #define vm_vec_negate(v) do {(v)->x = - (v)->x; (v)->y = - (v)->y; (v)->z = - (v)->z;} while (0);
302 //Functions in library
306 //adds two vectors, fills in dest, returns ptr to dest
307 //ok for dest to equal either source, but should use vm_vec_add2() if so
308 vms_vector * vm_vec_add (vms_vector * dest, vms_vector * src0, vms_vector * src1);
311 //subs two vectors, fills in dest, returns ptr to dest
312 //ok for dest to equal either source, but should use vm_vec_sub2() if so
313 vms_vector * vm_vec_sub (vms_vector * dest, vms_vector * src0, vms_vector * src1);
316 //adds one vector to another. returns ptr to dest
317 //dest can equal source
318 vms_vector * vm_vec_add2 (vms_vector * dest, vms_vector * src);
321 //subs one vector from another, returns ptr to dest
322 //dest can equal source
323 vms_vector * vm_vec_sub2 (vms_vector * dest, vms_vector * src);
328 #define vm_vec_add(dest,src0,src1) do { \
329 (dest)->x = (src0)->x + (src1)->x;
331 (dest)->y = (src0)->y + (src1)->y;
333 (dest)->z = (src0)->z + (src1)->z;
339 #define vm_vec_sub(dest,src0,src1) do { \
340 (dest)->x = (src0)->x - (src1)->x;
342 (dest)->y = (src0)->y - (src1)->y;
344 (dest)->z = (src0)->z - (src1)->z;
350 #define vm_vec_add2(dest,src) do { \
351 (dest)->x += (src)->x;
353 (dest)->y += (src)->y;
355 (dest)->z += (src)->z;
361 #define vm_vec_sub2(dest,src) do { \
362 (dest)->x -= (src)->x;
364 (dest)->y -= (src)->y;
366 (dest)->z -= (src)->z;
374 //averages two vectors. returns ptr to dest
375 //dest can equal either source
376 vms_vector * vm_vec_avg (vms_vector * dest, vms_vector * src0, vms_vector * src1);
379 //averages four vectors. returns ptr to dest
380 //dest can equal any source
381 vms_vector * vm_vec_avg4 (vms_vector * dest, vms_vector * src0, vms_vector * src1, vms_vector * src2, vms_vector * src3);
384 //scales a vector in place. returns ptr to vector
385 vms_vector * vm_vec_scale (vms_vector * dest, fix s);
388 //scales and copies a vector. returns ptr to dest
389 vms_vector * vm_vec_copy_scale (vms_vector * dest, vms_vector * src, fix s);
392 //scales a vector, adds it to another, and stores in a 3rd vector
393 //dest = src1 + k * src2
394 vms_vector * vm_vec_scale_add (vms_vector * dest, vms_vector * src1, vms_vector * src2, fix k);
397 //scales a vector and adds it to another
399 vms_vector * vm_vec_scale_add2 (vms_vector * dest, vms_vector * src, fix k);
402 //scales a vector in place, taking n/d for scale. returns ptr to vector
404 vms_vector * vm_vec_scale2 (vms_vector * dest, fix n, fix d);
407 //returns magnitude of a vector
408 fix vm_vec_mag (vms_vector * v);
411 //computes the distance between two points. (does sub and mag)
412 fix vm_vec_dist (vms_vector * v0, vms_vector * v1);
415 //computes an approximation of the magnitude of the vector
416 //uses dist = largest + next_largest*3/8 + smallest*3/16
417 fix vm_vec_mag_quick (vms_vector * v);
420 //computes an approximation of the distance between two points.
421 //uses dist = largest + next_largest*3/8 + smallest*3/16
422 fix vm_vec_dist_quick (vms_vector * v0, vms_vector * v1);
426 //normalize a vector. returns mag of source vec
427 fix vm_vec_copy_normalize (vms_vector * dest, vms_vector * src);
429 fix vm_vec_normalize (vms_vector * v);
432 //normalize a vector. returns mag of source vec. uses approx mag
433 fix vm_vec_copy_normalize_quick (vms_vector * dest, vms_vector * src);
435 fix vm_vec_normalize_quick (vms_vector * v);
438 //return the normalized direction vector between two points
439 //dest = normalized(end - start). Returns mag of direction vector
440 //NOTE: the order of the parameters matches the vector subtraction
441 fix vm_vec_normalized_dir (vms_vector * dest, vms_vector * end, vms_vector * start);
443 fix vm_vec_normalized_dir_quick (vms_vector * dest, vms_vector * end, vms_vector * start);
446 ////returns dot product of two vectors
447 fix vm_vec_dotprod (vms_vector * v0, vms_vector * v1);
449 #define vm_vec_dot(v0,v1) vm_vec_dotprod((v0),(v1))
453 #pragma aux vm_vec_dotprod parm [esi] [edi] value [eax] modify exact [eax ebx ecx edx] = \
455 "imul dword ptr [edi]" \
460 "imul dword ptr 4[edi]" \
465 "imul dword ptr 8[edi]" \
474 //computes cross product of two vectors. returns ptr to dest
475 //dest CANNOT equal either source
476 vms_vector * vm_vec_crossprod (vms_vector * dest, vms_vector * src0, vms_vector * src1);
478 #define vm_vec_cross(dest,src0,src1) vm_vec_crossprod((dest),(src0),(src1))
480 //computes surface normal from three points. result is normalized
481 //returns ptr to dest
482 //dest CANNOT equal either source
483 vms_vector * vm_vec_normal (vms_vector * dest, vms_vector * p0, vms_vector * p1, vms_vector * p2);
486 //computes non-normalized surface normal from three points.
487 //returns ptr to dest
488 //dest CANNOT equal either source
489 vms_vector * vm_vec_perp (vms_vector * dest, vms_vector * p0, vms_vector * p1, vms_vector * p2);
492 //computes the delta angle between two vectors.
493 //vectors need not be normalized. if they are, call vm_vec_delta_ang_norm()
494 //the forward vector (third parameter) can be NULL, in which case the absolute
495 //value of the angle in returned. Otherwise the angle around that vector is
497 fixang vm_vec_delta_ang (vms_vector * v0, vms_vector * v1, vms_vector * fvec);
500 //computes the delta angle between two normalized vectors.
501 fixang vm_vec_delta_ang_norm (vms_vector * v0, vms_vector * v1, vms_vector * fvec);
504 //computes a matrix from a set of three angles. returns ptr to matrix
505 vms_matrix * vm_angles_2_matrix (vms_matrix * m, vms_angvec * a);
508 //computes a matrix from a forward vector and an angle
509 vms_matrix * vm_vec_ang_2_matrix (vms_matrix * m, vms_vector * v, fixang a);
512 //computes a matrix from one or more vectors. The forward vector is required,
513 //with the other two being optional. If both up & right vectors are passed,
514 //the up vector is used. If only the forward vector is passed, a bank of
516 //returns ptr to matrix
517 vms_matrix * vm_vector_2_matrix (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec);
520 //this version of vector_2_matrix requires that the vectors be more-or-less
521 //normalized and close to perpendicular
522 vms_matrix * vm_vector_2_matrix_norm (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec);
525 //rotates a vector through a matrix. returns ptr to dest vector
526 //dest CANNOT equal either source
527 vms_vector * vm_vec_rotate (vms_vector * dest, vms_vector * src, vms_matrix * m);
530 //transpose a matrix in place. returns ptr to matrix
531 vms_matrix * vm_transpose_matrix (vms_matrix * m);
533 #define vm_transpose(m) vm_transpose_matrix(m)
535 //copy and transpose a matrix. returns ptr to matrix
536 //dest CANNOT equal source. use vm_transpose_matrix() if this is the case
537 vms_matrix * vm_copy_transpose_matrix (vms_matrix * dest, vms_matrix * src);
539 #define vm_copy_transpose(dest,src) vm_copy_transpose_matrix((dest),(src))
541 //mulitply 2 matrices, fill in dest. returns ptr to dest
542 //dest CANNOT equal either source
543 vms_matrix * vm_matrix_x_matrix (vms_matrix * dest, vms_matrix * src0, vms_matrix * src1);
546 //extract angles from a matrix
547 vms_angvec * vm_extract_angles_matrix (vms_angvec * a, vms_matrix * m);
550 //extract heading and pitch from a vector, assuming bank==0
551 vms_angvec * vm_extract_angles_vector (vms_angvec * a, vms_vector * v);
554 //compute the distance from a point to a plane. takes the normalized normal
555 //of the plane (ebx), a point on the plane (edi), and the point to check (esi).
556 //returns distance in eax
557 //distance is signed, so negative dist is on the back of the plane
558 fix vm_dist_to_plane (vms_vector * checkp, vms_vector * norm, vms_vector * planep);
561 //fills in fields of an angle vector
562 #define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v))
563 #endif /* !_VECMAT_H */