]> icculus.org git repositories - btb/d2x.git/blob - include/vecmat.h
remove rcs tags
[btb/d2x.git] / include / vecmat.h
1 /*
2    THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3    SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4    END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5    ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6    IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7    SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8    FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9    CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10    AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11    COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12  */
13 /*
14  *
15  * Header file for vector/matrix library
16  *
17  */
18
19 #ifndef _VECMAT_H
20 #define _VECMAT_H
21
22 #include "maths.h"
23
24 //#define INLINE 1              //are some of these functions inline?
25
26 //The basic fixed-point vector.  Access elements by name or position
27 typedef struct vms_vector
28 {
29         fix x, y, z;
30 }
31 __pack__ vms_vector;
32
33
34 typedef struct vms_vector_array
35 {
36         fix xyz[3];
37 }
38 __pack__ vms_vector_array;
39
40
41 //Short vector, used for pre-rotation points.
42 //Access elements by name or position
43 typedef struct vms_svec
44 {
45         short sv_x, sv_y, sv_z;
46 }
47 __pack__ vms_svec;
48
49
50 //Angle vector.  Used to store orientations
51 typedef struct vms_angvec
52 {
53         fixang p, b, h;
54 }
55 __pack__ vms_angvec;
56
57
58 //A 3x3 rotation matrix.  Sorry about the numbering starting with one.
59 //Ordering is across then down, so <m1,m2,m3> is the first row
60 typedef struct vms_matrix
61 {
62         vms_vector rvec, uvec, fvec;
63 }
64 __pack__ vms_matrix;
65
66
67 //Macros/functions to fill in fields of structures
68
69 //macro to check if vector is zero
70 #define IS_VEC_NULL(v) (v->x == 0 && v->y == 0 && v->z == 0)
71
72 //macro to set a vector to zero.  we could do this with an in-line assembly
73 //macro, but it's probably better to let the compiler optimize it.
74 //Note: NO RETURN VALUE
75 #define vm_vec_zero(v) (v)->x=(v)->y=(v)->z=0
76
77 //macro set set a matrix to the identity. Note: NO RETURN VALUE
78
79 // DPH (18/9/98): Begin mod to fix linefeed problem under linux. Uses an
80 // inline function instead of a multi-line macro to fix CR/LF problems.
81
82 #ifdef __unix__
83 static inline void vm_set_identity(vms_matrix *m)
84 {
85         m->rvec.x = m->uvec.y = m->fvec.z = f1_0;
86         m->rvec.y = m->rvec.z = m->uvec.x = m->uvec.z = m->fvec.x = m->fvec.y = 0;
87 }
88 #else
89 #define vm_set_identity(m) do {m->rvec.x = m->uvec.y = m->fvec.z = f1_0; \
90         m->rvec.y = m->rvec.z = \
91         m->uvec.x = m->uvec.z = \
92         m->fvec.x = m->fvec.y = 0;} while (0)
93 #endif
94
95 // DPH (19/8/98): End changes.
96
97 vms_vector * vm_vec_make (vms_vector * v, fix x, fix y, fix z);
98
99
100 #ifdef __WATCOMC__
101 #pragma aux vm_vec_make "*_" parm [eax] [edx] [ebx] [ecx] value [eax] modify exact [] = \
102 "mov 0[eax],edx" \
103 "mov 4[eax],ebx" \
104 "mov 8[eax],ecx";
105
106 #endif
107
108 vms_angvec * vm_angvec_make (vms_angvec * v, fixang p, fixang b, fixang h);
109
110
111 #ifdef __WATCOMC__
112 #pragma aux vm_angvec_make "*_" parm [eax] [dx] [bx] [cx] value [eax] modify exact [] = \
113 "mov 0[eax],dx" \
114 "mov 2[eax],bx" \
115 "mov 4[eax],cx";
116
117 #endif
118
119 //Global constants
120
121 extern vms_vector vmd_zero_vector;
122
123 extern vms_matrix vmd_identity_matrix;
124
125
126 //Here's a handy constant
127
128 #define ZERO_VECTOR {0,0,0}
129 #define IDENTITY_MATRIX { {f1_0,0,0}, {0,f1_0,0}, {0,0,f1_0} }
130
131 //#define vm_vec_make(v,_x,_y,_z) (((v)->x=(_x), (v)->y=(_y), (v)->z=(_z)), (v))
132
133 //#pragma off (unreferenced)
134 ////make this local, so compiler can in-line it
135 //static vms_vector *vm_vec_make(vms_vector *v,fix x,fix y,fix z)
136 //{
137 //      v->x = x;
138 //      v->y = y;
139 //      v->z = z;
140 //
141 //      return v;
142 //}
143 //#pragma on (unreferenced)
144
145
146 ////macro to fill in elements of a matrix, also for Mike
147 /*
148    #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \
149    do { (m)->m1=(_m1); (m)->m2=(_m2); (m)->m3=(_m3); \
150    (m)->m4=(_m4); (m)->m5=(_m5); (m)->m6=(_m6); \
151    (m)->m7=(_m7); (m)->m8=(_m8); (m)->m9=(_m9);} while (0)
152  */
153
154 #if 0               //kill this, since bogus with new matrix ordering
155
156 //macro to fill in elements of a matrix, also for Mike
157 #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \
158 (((m)->m1 = (_m1), (m)->m2 = (_m2), (m)->m3 = (_m3), \
159   (m)->m4 = (_m4), (m)->m5 = (_m5), (m)->m6 = (_m6), \
160   (m)->m7 = (_m7), (m)->m8 = (_m8), (m)->m9 = (_m9)), (m))
161
162 #endif /* 0 */
163
164 ////fills in fields of an angle vector
165 //#define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v))
166
167 //negate a vector
168 #define vm_vec_negate(v) do {(v)->x = - (v)->x; (v)->y = - (v)->y; (v)->z = - (v)->z;} while (0);
169
170 //Functions in library
171
172 #ifndef INLINE
173
174 //adds two vectors, fills in dest, returns ptr to dest
175 //ok for dest to equal either source, but should use vm_vec_add2() if so
176 vms_vector * vm_vec_add (vms_vector * dest, vms_vector * src0, vms_vector * src1);
177
178
179 //subs two vectors, fills in dest, returns ptr to dest
180 //ok for dest to equal either source, but should use vm_vec_sub2() if so
181 vms_vector * vm_vec_sub (vms_vector * dest, vms_vector * src0, vms_vector * src1);
182
183
184 //adds one vector to another. returns ptr to dest
185 //dest can equal source
186 vms_vector * vm_vec_add2 (vms_vector * dest, vms_vector * src);
187
188
189 //subs one vector from another, returns ptr to dest
190 //dest can equal source
191 vms_vector * vm_vec_sub2 (vms_vector * dest, vms_vector * src);
192
193
194 #else   /* INLINE */
195
196 #define vm_vec_add(dest,src0,src1) do { \
197 (dest)->x = (src0)->x + (src1)->x;
198 \
199 (dest)->y = (src0)->y + (src1)->y;
200 \
201 (dest)->z = (src0)->z + (src1)->z;
202 \
203 }
204 while (0);
205
206
207 #define vm_vec_sub(dest,src0,src1) do { \
208 (dest)->x = (src0)->x - (src1)->x;
209 \
210 (dest)->y = (src0)->y - (src1)->y;
211 \
212 (dest)->z = (src0)->z - (src1)->z;
213 \
214 }
215 while (0);
216
217
218 #define vm_vec_add2(dest,src) do {  \
219 (dest)->x += (src)->x;
220 \
221 (dest)->y += (src)->y;
222 \
223 (dest)->z += (src)->z;
224 \
225 }
226 while (0);
227
228
229 #define vm_vec_sub2(dest,src) do {  \
230 (dest)->x -= (src)->x;
231 \
232 (dest)->y -= (src)->y;
233 \
234 (dest)->z -= (src)->z;
235 \
236 }
237 while (0);
238
239
240 #endif  /* INLINE */
241
242 //averages two vectors. returns ptr to dest
243 //dest can equal either source
244 vms_vector * vm_vec_avg (vms_vector * dest, vms_vector * src0, vms_vector * src1);
245
246
247 //averages four vectors. returns ptr to dest
248 //dest can equal any source
249 vms_vector * vm_vec_avg4 (vms_vector * dest, vms_vector * src0, vms_vector * src1, vms_vector * src2, vms_vector * src3);
250
251
252 //scales a vector in place.  returns ptr to vector
253 vms_vector * vm_vec_scale (vms_vector * dest, fix s);
254
255
256 //scales and copies a vector.  returns ptr to dest
257 vms_vector * vm_vec_copy_scale (vms_vector * dest, vms_vector * src, fix s);
258
259
260 //scales a vector, adds it to another, and stores in a 3rd vector
261 //dest = src1 + k * src2
262 vms_vector * vm_vec_scale_add (vms_vector * dest, vms_vector * src1, vms_vector * src2, fix k);
263
264
265 //scales a vector and adds it to another
266 //dest += k * src
267 vms_vector * vm_vec_scale_add2 (vms_vector * dest, vms_vector * src, fix k);
268
269
270 //scales a vector in place, taking n/d for scale.  returns ptr to vector
271 //dest *= n/d
272 vms_vector * vm_vec_scale2 (vms_vector * dest, fix n, fix d);
273
274
275 //returns magnitude of a vector
276 fix vm_vec_mag (vms_vector * v);
277
278
279 //computes the distance between two points. (does sub and mag)
280 fix vm_vec_dist (vms_vector * v0, vms_vector * v1);
281
282
283 //computes an approximation of the magnitude of the vector
284 //uses dist = largest + next_largest*3/8 + smallest*3/16
285 fix vm_vec_mag_quick (vms_vector * v);
286
287
288 //computes an approximation of the distance between two points.
289 //uses dist = largest + next_largest*3/8 + smallest*3/16
290 fix vm_vec_dist_quick (vms_vector * v0, vms_vector * v1);
291
292
293
294 //normalize a vector. returns mag of source vec
295 fix vm_vec_copy_normalize (vms_vector * dest, vms_vector * src);
296
297 fix vm_vec_normalize (vms_vector * v);
298
299
300 //normalize a vector. returns mag of source vec. uses approx mag
301 fix vm_vec_copy_normalize_quick (vms_vector * dest, vms_vector * src);
302
303 fix vm_vec_normalize_quick (vms_vector * v);
304
305
306 //return the normalized direction vector between two points
307 //dest = normalized(end - start).  Returns mag of direction vector
308 //NOTE: the order of the parameters matches the vector subtraction
309 fix vm_vec_normalized_dir (vms_vector * dest, vms_vector * end, vms_vector * start);
310
311 fix vm_vec_normalized_dir_quick (vms_vector * dest, vms_vector * end, vms_vector * start);
312
313
314 ////returns dot product of two vectors
315 fix vm_vec_dotprod (vms_vector * v0, vms_vector * v1);
316
317 #define vm_vec_dot(v0,v1) vm_vec_dotprod((v0),(v1))
318
319 #ifdef INLINE
320 #ifdef __WATCOMC__
321 #pragma aux vm_vec_dotprod parm [esi] [edi] value [eax] modify exact [eax ebx ecx edx] = \
322 "mov    eax,[esi]" \
323 "imul   dword ptr [edi]" \
324 "mov    ebx,eax" \
325 "mov    ecx,edx" \
326 \
327 "mov    eax,4[esi]" \
328 "imul   dword ptr 4[edi]" \
329 "add    ebx,eax" \
330 "adc    ecx,edx" \
331 \
332 "mov    eax,8[esi]" \
333 "imul   dword ptr 8[edi]" \
334 "add    eax,ebx" \
335 "adc    edx,ecx" \
336 \
337 "shrd   eax,edx,16";
338
339 #endif
340 #endif  /* INLINE */
341
342 //computes cross product of two vectors. returns ptr to dest
343 //dest CANNOT equal either source
344 vms_vector * vm_vec_crossprod (vms_vector * dest, vms_vector * src0, vms_vector * src1);
345
346 #define vm_vec_cross(dest,src0,src1) vm_vec_crossprod((dest),(src0),(src1))
347
348 //computes surface normal from three points. result is normalized
349 //returns ptr to dest
350 //dest CANNOT equal either source
351 vms_vector * vm_vec_normal (vms_vector * dest, vms_vector * p0, vms_vector * p1, vms_vector * p2);
352
353
354 //computes non-normalized surface normal from three points.
355 //returns ptr to dest
356 //dest CANNOT equal either source
357 vms_vector * vm_vec_perp (vms_vector * dest, vms_vector * p0, vms_vector * p1, vms_vector * p2);
358
359
360 //computes the delta angle between two vectors.
361 //vectors need not be normalized. if they are, call vm_vec_delta_ang_norm()
362 //the forward vector (third parameter) can be NULL, in which case the absolute
363 //value of the angle in returned.  Otherwise the angle around that vector is
364 //returned.
365 fixang vm_vec_delta_ang (vms_vector * v0, vms_vector * v1, vms_vector * fvec);
366
367
368 //computes the delta angle between two normalized vectors.
369 fixang vm_vec_delta_ang_norm (vms_vector * v0, vms_vector * v1, vms_vector * fvec);
370
371
372 //computes a matrix from a set of three angles.  returns ptr to matrix
373 vms_matrix * vm_angles_2_matrix (vms_matrix * m, vms_angvec * a);
374
375
376 //computes a matrix from a forward vector and an angle
377 vms_matrix * vm_vec_ang_2_matrix (vms_matrix * m, vms_vector * v, fixang a);
378
379
380 //computes a matrix from one or more vectors. The forward vector is required,
381 //with the other two being optional.  If both up & right vectors are passed,
382 //the up vector is used.  If only the forward vector is passed, a bank of
383 //zero is assumed
384 //returns ptr to matrix
385 vms_matrix * vm_vector_2_matrix (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec);
386
387
388 //this version of vector_2_matrix requires that the vectors be more-or-less
389 //normalized and close to perpendicular
390 vms_matrix * vm_vector_2_matrix_norm (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec);
391
392
393 //rotates a vector through a matrix. returns ptr to dest vector
394 //dest CANNOT equal either source
395 vms_vector * vm_vec_rotate (vms_vector * dest, vms_vector * src, vms_matrix * m);
396
397
398 //transpose a matrix in place. returns ptr to matrix
399 vms_matrix * vm_transpose_matrix (vms_matrix * m);
400
401 #define vm_transpose(m) vm_transpose_matrix(m)
402
403 //copy and transpose a matrix. returns ptr to matrix
404 //dest CANNOT equal source. use vm_transpose_matrix() if this is the case
405 vms_matrix * vm_copy_transpose_matrix (vms_matrix * dest, vms_matrix * src);
406
407 #define vm_copy_transpose(dest,src) vm_copy_transpose_matrix((dest),(src))
408
409 //mulitply 2 matrices, fill in dest.  returns ptr to dest
410 //dest CANNOT equal either source
411 vms_matrix * vm_matrix_x_matrix (vms_matrix * dest, vms_matrix * src0, vms_matrix * src1);
412
413
414 //extract angles from a matrix
415 vms_angvec * vm_extract_angles_matrix (vms_angvec * a, vms_matrix * m);
416
417
418 //extract heading and pitch from a vector, assuming bank==0
419 vms_angvec * vm_extract_angles_vector (vms_angvec * a, vms_vector * v);
420
421
422 //compute the distance from a point to a plane.  takes the normalized normal
423 //of the plane (ebx), a point on the plane (edi), and the point to check (esi).
424 //returns distance in eax
425 //distance is signed, so negative dist is on the back of the plane
426 fix vm_dist_to_plane (vms_vector * checkp, vms_vector * norm, vms_vector * planep);
427
428
429 //fills in fields of an angle vector
430 #define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v))
431 #endif  /* !_VECMAT_H */