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