]> icculus.org git repositories - taylor/freespace2.git/blob - src/render/3dmath.cpp
ryan's struct patch for gcc 2.95
[taylor/freespace2.git] / src / render / 3dmath.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Render/3dMath.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * 3d Math routines used by the Renderer lib
16  *
17  * $Log$
18  * Revision 1.3  2002/06/17 06:33:10  relnev
19  * ryan's struct patch for gcc 2.95
20  *
21  * Revision 1.2  2002/06/09 04:41:25  relnev
22  * added copyright header
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:10  root
25  * Initial import.
26  *
27  * 
28  * 7     7/24/99 4:19p Dave
29  * Fixed dumb code with briefing bitmaps. Made d3d zbuffer work much
30  * better. Made model code use zbuffer more intelligently.
31  * 
32  * 6     3/19/99 9:51a Dave
33  * Checkin to repair massive source safe crash. Also added support for
34  * pof-style nebulae, and some new weapons code.
35  * 
36  * 6     3/15/99 6:45p Daveb
37  * Put in rough nebula bitmap support.
38  * 
39  * 5     1/29/99 12:47a Dave
40  * Put in sounds for beam weapon. A bunch of interface screens (tech
41  * database stuff).
42  * 
43  * 4     12/07/98 5:51p Dave
44  * Finally got d3d fog working! Now we just need to tweak values.
45  * 
46  * 3     12/06/98 2:36p Dave
47  * Drastically improved nebula fogging.
48  * 
49  * 2     10/07/98 10:53a Dave
50  * Initial checkin.
51  * 
52  * 1     10/07/98 10:51a Dave
53  * 
54  * 21    3/16/98 4:51p John
55  * Added low-level code to clip all polygons against an arbritary plane.
56  * Took out all old model_interp_zclip and used this new method instead.  
57  * 
58  * 20    2/05/98 9:21p John
59  * Some new Direct3D code.   Added code to monitor a ton of stuff in the
60  * game.
61  * 
62  * 19    7/28/97 2:21p John
63  * changed vecmat functions to not return src.  Started putting in code
64  * for inline vector math.    Fixed some bugs with optimizer.
65  * 
66  * 18    7/03/97 1:32p John
67  * took out wacky warp.  Tried to make rotation faster by inlining all its
68  * functions and using temp variables to help the optimizer
69  * 
70  * 17    4/29/97 12:24p Adam
71  * JAS:   Added code for delayed point to vec.   Fixed some FRED
72  * sequencing problems with g3_start_frame / g3_end_frame.
73  * 
74  * 16    4/29/97 9:55a John
75  * 
76  * 15    3/24/97 3:26p John
77  * Cleaned up and restructured model_collide code and fvi code.  In fvi
78  * made code that finds uvs work..  Added bm_get_pixel to BmpMan.
79  * 
80  * 14    3/06/97 5:36p Mike
81  * Change vec_normalize_safe() back to vec_normalize().
82  * Spruce up docking a bit.
83  * 
84  * 13    3/06/97 10:56a Mike
85  * Write error checking version of vm_vec_normalize().
86  * Fix resultant problems.
87  * 
88  * 12    2/17/97 5:18p John
89  * Added a bunch of RCS headers to a bunch of old files that don't have
90  * them.
91  *
92  * $NoKeywords: $
93  */
94
95 #include "2d.h"
96 #include "3dinternal.h"
97
98
99 #define MIN_Z 0.0f
100
101 //Codes a vector.  Returns the codes of a point.
102 ubyte g3_code_vector(vector * p)
103 {
104         ubyte cc=0;
105
106         if (p->xyz.x > p->xyz.z)
107                 cc |= CC_OFF_RIGHT;
108
109         if (p->xyz.y > p->xyz.z)
110                 cc |= CC_OFF_TOP;
111
112         if (p->xyz.x < -p->xyz.z)
113                 cc |= CC_OFF_LEFT;
114
115         if (p->xyz.y < -p->xyz.z)
116                 cc |= CC_OFF_BOT;
117
118         if (p->xyz.z < MIN_Z )
119                 cc |= CC_BEHIND;
120
121         if ( G3_user_clip )     {
122                 // Check if behind user plane
123                 if ( g3_point_behind_user_plane(p))     {
124                         cc |= CC_OFF_USER;
125                 }
126         }
127
128         return cc;
129 }
130
131
132 //code a point.  fills in the p3_codes field of the point, and returns the codes
133 ubyte g3_code_vertex(vertex *p)
134 {
135         ubyte cc=0;
136
137         if (p->x > p->z)
138                 cc |= CC_OFF_RIGHT;
139
140         if (p->y > p->z)
141                 cc |= CC_OFF_TOP;
142
143         if (p->x < -p->z)
144                 cc |= CC_OFF_LEFT;
145
146         if (p->y < -p->z)
147                 cc |= CC_OFF_BOT;
148
149         if (p->z < MIN_Z )
150                 cc |= CC_BEHIND;
151
152         if ( G3_user_clip )     {
153                 // Check if behind user plane
154                 if ( g3_point_behind_user_plane((vector *)&p->x))       {
155                         cc |= CC_OFF_USER;
156                 }
157         }
158
159         return p->codes = cc;
160
161 }
162
163 MONITOR( NumRotations );        
164
165 ubyte g3_rotate_vertex(vertex *dest,vector *src)
166 {
167 #if 0
168         vector tempv;
169         Assert( G3_count == 1 );
170         vm_vec_sub(&tempv,src,&View_position);
171         vm_vec_rotate( (vector *)&dest->x, &tempv, &View_matrix );
172         dest->flags = 0;        //not projected
173         return g3_code_vertex(dest);
174 #else
175         float tx, ty, tz, x,y,z;
176         ubyte codes;
177
178         MONITOR_INC( NumRotations, 1 ); 
179
180         tx = src->xyz.x - View_position.xyz.x;
181         ty = src->xyz.y - View_position.xyz.y;
182         tz = src->xyz.z - View_position.xyz.z;
183
184         x = tx * View_matrix.v.rvec.xyz.x;
185         x += ty * View_matrix.v.rvec.xyz.y;
186         x += tz * View_matrix.v.rvec.xyz.z;
187
188         y = tx * View_matrix.v.uvec.xyz.x;
189         y += ty * View_matrix.v.uvec.xyz.y;
190         y += tz * View_matrix.v.uvec.xyz.z;
191
192         z = tx * View_matrix.v.fvec.xyz.x;
193         z += ty * View_matrix.v.fvec.xyz.y;
194         z += tz * View_matrix.v.fvec.xyz.z;
195
196         codes = 0;
197
198         if (x > z)                      codes |= CC_OFF_RIGHT;
199         if (x < -z)                     codes |= CC_OFF_LEFT;
200         if (y > z)                      codes |= CC_OFF_TOP;
201         if (y < -z)                     codes |= CC_OFF_BOT;
202         if (z < MIN_Z ) codes |= CC_BEHIND;
203
204         dest->x = x;
205         dest->y = y;
206         dest->z = z;
207
208         if ( G3_user_clip )     {
209                 // Check if behind user plane
210                 if ( g3_point_behind_user_plane((vector *)&dest->x))    {
211                         codes |= CC_OFF_USER;
212                 }
213         }
214
215         dest->codes = codes;
216
217         dest->flags = 0;        // not projected
218
219         return codes;
220 #endif
221 }       
222
223
224 ubyte g3_rotate_faraway_vertex(vertex *dest,vector *src)
225 {       
226         Assert( G3_count == 1 );
227
228         MONITOR_INC( NumRotations, 1 ); 
229
230         vm_vec_rotate( (vector *)&dest->x, src, &View_matrix );
231         dest->flags = 0;        //not projected
232         return g3_code_vertex(dest);
233 }       
234
235
236 //rotates a point. returns codes.  does not check if already rotated
237 ubyte g3_rotate_vector(vector *dest,vector *src)
238 {
239         vector tempv;
240
241         Assert( G3_count == 1 );
242
243         MONITOR_INC( NumRotations, 1 ); 
244
245         vm_vec_sub(&tempv,src,&View_position);
246         vm_vec_rotate(dest,&tempv,&View_matrix);
247         return g3_code_vector(dest);
248 }       
249                 
250 ubyte g3_project_vector(vector *p, float *sx, float *sy )
251 {
252         float w;
253
254         Assert( G3_count == 1 );
255
256         if ( p->xyz.z <= MIN_Z ) return PF_OVERFLOW;
257
258         w=1.0f / p->xyz.z;
259
260         *sx = (Canvas_width + (p->xyz.x*Canvas_width*w))*0.5f;
261         *sy = (Canvas_height - (p->xyz.y*Canvas_height*w))*0.5f;
262         return PF_PROJECTED;
263 }
264
265 //projects a point. Checks for overflow.
266
267 int g3_project_vertex(vertex *p)
268 {
269         float w;
270
271         Assert( G3_count == 1 );
272
273         if ( p->flags & PF_PROJECTED )
274                 return p->flags;
275
276         //if ( p->z < MIN_Z ) {
277         if ( p->z <= MIN_Z ) {
278                 p->flags |= PF_OVERFLOW;
279         } else {
280                 // w = (p->z == 0.0f) ? 100.0f : 1.0f / p->z;
281                 w = 1.0f / p->z;
282                 p->sx = (Canvas_width + (p->x*Canvas_width*w))*0.5f;
283                 p->sy = (Canvas_height - (p->y*Canvas_height*w))*0.5f;
284
285                 if(gr_screen.mode == GR_GLIDE){
286                         if ( w > 61439.0f ) w = 61439.0f;
287                 } else {
288                         if ( w > 1.0f ) w = 1.0f;               
289                 }
290                 p->sw = w;
291                 p->flags |= PF_PROJECTED;
292         }
293         
294         return p->flags;
295 }
296
297
298 //from a 2d point, compute the vector through that point
299 void g3_point_to_vec(vector *v,int sx,int sy)
300 {
301         vector  tempv;
302
303         Assert( G3_count == 1 );
304
305         tempv.xyz.x =  ((float)sx - Canv_w2) / Canv_w2;
306         tempv.xyz.y = -((float)sy - Canv_h2) / Canv_h2;
307         tempv.xyz.z = 1.0f;
308
309         tempv.xyz.x = tempv.xyz.x * Matrix_scale.xyz.z / Matrix_scale.xyz.x;
310         tempv.xyz.y = tempv.xyz.y * Matrix_scale.xyz.z / Matrix_scale.xyz.y;
311
312         vm_vec_normalize(&tempv);
313         vm_vec_unrotate(v, &tempv, &Unscaled_matrix);
314 }
315
316 //from a 2d point, compute the vector through that point.
317 // This can be called outside of a g3_start_frame/g3_end_frame
318 // pair as long g3_start_frame was previously called.
319 void g3_point_to_vec_delayed(vector *v,int sx,int sy)
320 {
321         vector  tempv;
322
323         tempv.xyz.x =  ((float)sx - Canv_w2) / Canv_w2;
324         tempv.xyz.y = -((float)sy - Canv_h2) / Canv_h2;
325         tempv.xyz.z = 1.0f;
326
327         tempv.xyz.x = tempv.xyz.x * Matrix_scale.xyz.z / Matrix_scale.xyz.x;
328         tempv.xyz.y = tempv.xyz.y * Matrix_scale.xyz.z / Matrix_scale.xyz.y;
329
330         vm_vec_normalize(&tempv);
331         vm_vec_unrotate(v, &tempv, &Unscaled_matrix);
332 }
333
334 vector *g3_rotate_delta_vec(vector *dest,vector *src)
335 {
336         Assert( G3_count == 1 );
337         return vm_vec_rotate(dest,src,&View_matrix);
338 }
339
340 //      vms_vector tempv;
341 //      vms_matrix tempm;
342 //
343 //      tempv.xyz.x =  fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.xyz.z,Matrix_scale.xyz.x);
344 //      tempv.xyz.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.xyz.z,Matrix_scale.xyz.y);
345 //      tempv.xyz.z = f1_0;
346 //
347 //      vm_vec_normalize(&tempv);
348 //
349 //      vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
350 //
351 //      vm_vec_rotate(v,&tempv,&tempm);
352
353 /*
354
355 //from a 2d point, compute the vector through that point
356 void g3_point_2_vec(vector *v,int sx,int sy)
357 {
358         vector tempv;
359         matrix tempm;
360
361         tempv.xyz.x =  fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.xyz.z,Matrix_scale.xyz.x);
362         tempv.xyz.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.xyz.z,Matrix_scale.xyz.y);
363         tempv.xyz.z = f1_0;
364
365         vm_vec_normalize(&tempv);
366
367         vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
368
369         vm_vec_rotate(v,&tempv,&tempm);
370
371 }
372
373 //delta rotation functions
374 vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx)
375 {
376         dest->x = fixmul(View_matrix.v.rvec.xyz.x,dx);
377         dest->y = fixmul(View_matrix.v.uvec.xyz.x,dx);
378         dest->z = fixmul(View_matrix.v.fvec.xyz.x,dx);
379
380         return dest;
381 }
382
383 vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy)
384 {
385         dest->x = fixmul(View_matrix.v.rvec.xyz.y,dy);
386         dest->y = fixmul(View_matrix.v.uvec.xyz.y,dy);
387         dest->z = fixmul(View_matrix.v.fvec.xyz.y,dy);
388
389         return dest;
390 }
391
392 vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz)
393 {
394         dest->x = fixmul(View_matrix.v.rvec.xyz.z,dz);
395         dest->y = fixmul(View_matrix.v.uvec.xyz.z,dz);
396         dest->z = fixmul(View_matrix.v.fvec.xyz.z,dz);
397
398         return dest;
399 }
400
401
402
403 ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav)
404 {
405         vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav);
406
407         dest->p3_flags = 0;             //not projected
408
409         return g3_code_point(dest);
410 }
411 */
412
413 // calculate the depth of a point - returns the z coord of the rotated point
414 float g3_calc_point_depth(vector *pnt)
415 {
416         float q;
417
418         q = (pnt->xyz.x - View_position.xyz.x) * View_matrix.v.fvec.xyz.x;
419         q += (pnt->xyz.y - View_position.xyz.y) * View_matrix.v.fvec.xyz.y;
420         q += (pnt->xyz.z - View_position.xyz.z) * View_matrix.v.fvec.xyz.z;
421
422         return q;
423 }
424
425