2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Render/3dMath.cpp $
15 * 3d Math routines used by the Renderer lib
18 * Revision 1.3 2002/06/17 06:33:10 relnev
19 * ryan's struct patch for gcc 2.95
21 * Revision 1.2 2002/06/09 04:41:25 relnev
22 * added copyright header
24 * Revision 1.1.1.1 2002/05/03 03:28:10 root
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.
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.
36 * 6 3/15/99 6:45p Daveb
37 * Put in rough nebula bitmap support.
39 * 5 1/29/99 12:47a Dave
40 * Put in sounds for beam weapon. A bunch of interface screens (tech
43 * 4 12/07/98 5:51p Dave
44 * Finally got d3d fog working! Now we just need to tweak values.
46 * 3 12/06/98 2:36p Dave
47 * Drastically improved nebula fogging.
49 * 2 10/07/98 10:53a Dave
52 * 1 10/07/98 10:51a Dave
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.
58 * 20 2/05/98 9:21p John
59 * Some new Direct3D code. Added code to monitor a ton of stuff in the
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.
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
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.
74 * 16 4/29/97 9:55a John
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.
80 * 14 3/06/97 5:36p Mike
81 * Change vec_normalize_safe() back to vec_normalize().
82 * Spruce up docking a bit.
84 * 13 3/06/97 10:56a Mike
85 * Write error checking version of vm_vec_normalize().
86 * Fix resultant problems.
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
96 #include "3dinternal.h"
101 //Codes a vector. Returns the codes of a point.
102 ubyte g3_code_vector(vector * p)
106 if (p->xyz.x > p->xyz.z)
109 if (p->xyz.y > p->xyz.z)
112 if (p->xyz.x < -p->xyz.z)
115 if (p->xyz.y < -p->xyz.z)
118 if (p->xyz.z < MIN_Z )
121 if ( G3_user_clip ) {
122 // Check if behind user plane
123 if ( g3_point_behind_user_plane(p)) {
132 //code a point. fills in the p3_codes field of the point, and returns the codes
133 ubyte g3_code_vertex(vertex *p)
152 if ( G3_user_clip ) {
153 // Check if behind user plane
154 if ( g3_point_behind_user_plane((vector *)&p->x)) {
159 return p->codes = cc;
163 MONITOR( NumRotations );
165 ubyte g3_rotate_vertex(vertex *dest,vector *src)
169 SDL_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);
175 float tx, ty, tz, x,y,z;
178 MONITOR_INC( NumRotations, 1 );
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;
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;
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;
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;
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;
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;
217 dest->flags = 0; // not projected
224 ubyte g3_rotate_faraway_vertex(vertex *dest,vector *src)
226 SDL_assert( G3_count == 1 );
228 MONITOR_INC( NumRotations, 1 );
230 vm_vec_rotate( (vector *)&dest->x, src, &View_matrix );
231 dest->flags = 0; //not projected
232 return g3_code_vertex(dest);
236 //rotates a point. returns codes. does not check if already rotated
237 ubyte g3_rotate_vector(vector *dest,vector *src)
241 SDL_assert( G3_count == 1 );
243 MONITOR_INC( NumRotations, 1 );
245 vm_vec_sub(&tempv,src,&View_position);
246 vm_vec_rotate(dest,&tempv,&View_matrix);
247 return g3_code_vector(dest);
250 ubyte g3_project_vector(vector *p, float *sx, float *sy )
254 SDL_assert( G3_count == 1 );
256 if ( p->xyz.z <= MIN_Z ) return PF_OVERFLOW;
260 *sx = (Canvas_width + (p->xyz.x*Canvas_width*w))*0.5f;
261 *sy = (Canvas_height - (p->xyz.y*Canvas_height*w))*0.5f;
265 //projects a point. Checks for overflow.
267 int g3_project_vertex(vertex *p)
271 SDL_assert( G3_count == 1 );
273 if ( p->flags & PF_PROJECTED )
276 //if ( p->z < MIN_Z ) {
277 if ( p->z <= MIN_Z ) {
278 p->flags |= PF_OVERFLOW;
280 // w = (p->z == 0.0f) ? 100.0f : 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;
285 if ( w > 1.0f ) w = 1.0f;
288 p->flags |= PF_PROJECTED;
295 //from a 2d point, compute the vector through that point
296 void g3_point_to_vec(vector *v,int sx,int sy)
300 SDL_assert( G3_count == 1 );
302 tempv.xyz.x = ((float)sx - Canv_w2) / Canv_w2;
303 tempv.xyz.y = -((float)sy - Canv_h2) / Canv_h2;
306 tempv.xyz.x = tempv.xyz.x * Matrix_scale.xyz.z / Matrix_scale.xyz.x;
307 tempv.xyz.y = tempv.xyz.y * Matrix_scale.xyz.z / Matrix_scale.xyz.y;
309 vm_vec_normalize(&tempv);
310 vm_vec_unrotate(v, &tempv, &Unscaled_matrix);
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)
320 tempv.xyz.x = ((float)sx - Canv_w2) / Canv_w2;
321 tempv.xyz.y = -((float)sy - Canv_h2) / Canv_h2;
324 tempv.xyz.x = tempv.xyz.x * Matrix_scale.xyz.z / Matrix_scale.xyz.x;
325 tempv.xyz.y = tempv.xyz.y * Matrix_scale.xyz.z / Matrix_scale.xyz.y;
327 vm_vec_normalize(&tempv);
328 vm_vec_unrotate(v, &tempv, &Unscaled_matrix);
331 vector *g3_rotate_delta_vec(vector *dest,vector *src)
333 SDL_assert( G3_count == 1 );
334 return vm_vec_rotate(dest,src,&View_matrix);
340 // tempv.xyz.x = fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.xyz.z,Matrix_scale.xyz.x);
341 // tempv.xyz.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.xyz.z,Matrix_scale.xyz.y);
342 // tempv.xyz.z = f1_0;
344 // vm_vec_normalize(&tempv);
346 // vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
348 // vm_vec_rotate(v,&tempv,&tempm);
352 //from a 2d point, compute the vector through that point
353 void g3_point_2_vec(vector *v,int sx,int sy)
358 tempv.xyz.x = fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.xyz.z,Matrix_scale.xyz.x);
359 tempv.xyz.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.xyz.z,Matrix_scale.xyz.y);
362 vm_vec_normalize(&tempv);
364 vm_copy_transpose_matrix(&tempm,&Unscaled_matrix);
366 vm_vec_rotate(v,&tempv,&tempm);
370 //delta rotation functions
371 vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx)
373 dest->x = fixmul(View_matrix.v.rvec.xyz.x,dx);
374 dest->y = fixmul(View_matrix.v.uvec.xyz.x,dx);
375 dest->z = fixmul(View_matrix.v.fvec.xyz.x,dx);
380 vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy)
382 dest->x = fixmul(View_matrix.v.rvec.xyz.y,dy);
383 dest->y = fixmul(View_matrix.v.uvec.xyz.y,dy);
384 dest->z = fixmul(View_matrix.v.fvec.xyz.y,dy);
389 vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz)
391 dest->x = fixmul(View_matrix.v.rvec.xyz.z,dz);
392 dest->y = fixmul(View_matrix.v.uvec.xyz.z,dz);
393 dest->z = fixmul(View_matrix.v.fvec.xyz.z,dz);
400 ubyte g3_add_delta_vec(g3s_point *dest,g3s_point *src,vms_vector *deltav)
402 vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav);
404 dest->p3_flags = 0; //not projected
406 return g3_code_point(dest);
410 // calculate the depth of a point - returns the z coord of the rotated point
411 float g3_calc_point_depth(vector *pnt)
415 q = (pnt->xyz.x - View_position.xyz.x) * View_matrix.v.fvec.xyz.x;
416 q += (pnt->xyz.y - View_position.xyz.y) * View_matrix.v.fvec.xyz.y;
417 q += (pnt->xyz.z - View_position.xyz.z) * View_matrix.v.fvec.xyz.z;