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