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.2 2002/06/09 04:41:25 relnev
19 * added copyright header
21 * Revision 1.1.1.1 2002/05/03 03:28:10 root
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.
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.
33 * 6 3/15/99 6:45p Daveb
34 * Put in rough nebula bitmap support.
36 * 5 1/29/99 12:47a Dave
37 * Put in sounds for beam weapon. A bunch of interface screens (tech
40 * 4 12/07/98 5:51p Dave
41 * Finally got d3d fog working! Now we just need to tweak values.
43 * 3 12/06/98 2:36p Dave
44 * Drastically improved nebula fogging.
46 * 2 10/07/98 10:53a Dave
49 * 1 10/07/98 10:51a Dave
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.
55 * 20 2/05/98 9:21p John
56 * Some new Direct3D code. Added code to monitor a ton of stuff in the
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.
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
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.
71 * 16 4/29/97 9:55a John
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.
77 * 14 3/06/97 5:36p Mike
78 * Change vec_normalize_safe() back to vec_normalize().
79 * Spruce up docking a bit.
81 * 13 3/06/97 10:56a Mike
82 * Write error checking version of vm_vec_normalize().
83 * Fix resultant problems.
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
93 #include "3dinternal.h"
98 //Codes a vector. Returns the codes of a point.
99 ubyte g3_code_vector(vector * p)
118 if ( G3_user_clip ) {
119 // Check if behind user plane
120 if ( g3_point_behind_user_plane(p)) {
129 //code a point. fills in the p3_codes field of the point, and returns the codes
130 ubyte g3_code_vertex(vertex *p)
149 if ( G3_user_clip ) {
150 // Check if behind user plane
151 if ( g3_point_behind_user_plane((vector *)&p->x)) {
156 return p->codes = cc;
160 MONITOR( NumRotations );
162 ubyte g3_rotate_vertex(vertex *dest,vector *src)
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);
172 float tx, ty, tz, x,y,z;
175 MONITOR_INC( NumRotations, 1 );
177 tx = src->x - View_position.x;
178 ty = src->y - View_position.y;
179 tz = src->z - View_position.z;
181 x = tx * View_matrix.rvec.x;
182 x += ty * View_matrix.rvec.y;
183 x += tz * View_matrix.rvec.z;
185 y = tx * View_matrix.uvec.x;
186 y += ty * View_matrix.uvec.y;
187 y += tz * View_matrix.uvec.z;
189 z = tx * View_matrix.fvec.x;
190 z += ty * View_matrix.fvec.y;
191 z += tz * View_matrix.fvec.z;
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;
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;
214 dest->flags = 0; // not projected
221 ubyte g3_rotate_faraway_vertex(vertex *dest,vector *src)
223 Assert( G3_count == 1 );
225 MONITOR_INC( NumRotations, 1 );
227 vm_vec_rotate( (vector *)&dest->x, src, &View_matrix );
228 dest->flags = 0; //not projected
229 return g3_code_vertex(dest);
233 //rotates a point. returns codes. does not check if already rotated
234 ubyte g3_rotate_vector(vector *dest,vector *src)
238 Assert( G3_count == 1 );
240 MONITOR_INC( NumRotations, 1 );
242 vm_vec_sub(&tempv,src,&View_position);
243 vm_vec_rotate(dest,&tempv,&View_matrix);
244 return g3_code_vector(dest);
247 ubyte g3_project_vector(vector *p, float *sx, float *sy )
251 Assert( G3_count == 1 );
253 if ( p->z <= MIN_Z ) return PF_OVERFLOW;
257 *sx = (Canvas_width + (p->x*Canvas_width*w))*0.5f;
258 *sy = (Canvas_height - (p->y*Canvas_height*w))*0.5f;
262 //projects a point. Checks for overflow.
264 int g3_project_vertex(vertex *p)
268 Assert( G3_count == 1 );
270 if ( p->flags & PF_PROJECTED )
273 //if ( p->z < MIN_Z ) {
274 if ( p->z <= MIN_Z ) {
275 p->flags |= PF_OVERFLOW;
277 // w = (p->z == 0.0f) ? 100.0f : 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;
282 if(gr_screen.mode == GR_GLIDE){
283 if ( w > 61439.0f ) w = 61439.0f;
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 Assert( G3_count == 1 );
302 tempv.x = ((float)sx - Canv_w2) / Canv_w2;
303 tempv.y = -((float)sy - Canv_h2) / Canv_h2;
306 tempv.x = tempv.x * Matrix_scale.z / Matrix_scale.x;
307 tempv.y = tempv.y * Matrix_scale.z / Matrix_scale.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.x = ((float)sx - Canv_w2) / Canv_w2;
321 tempv.y = -((float)sy - Canv_h2) / Canv_h2;
324 tempv.x = tempv.x * Matrix_scale.z / Matrix_scale.x;
325 tempv.y = tempv.y * Matrix_scale.z / Matrix_scale.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 Assert( G3_count == 1 );
334 return vm_vec_rotate(dest,src,&View_matrix);
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);
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.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);
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.rvec.x,dx);
374 dest->y = fixmul(View_matrix.uvec.x,dx);
375 dest->z = fixmul(View_matrix.fvec.x,dx);
380 vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy)
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);
389 vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz)
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);
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->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;