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