2 * $Logfile: /Freespace2/code/Render/3dSetup.cpp $
7 * Code to setup matrix instancing and viewers
10 * Revision 1.1 2002/05/03 03:28:10 root
14 * 2 10/07/98 10:53a Dave
17 * 1 10/07/98 10:51a Dave
19 * 23 5/24/98 11:32a John
20 * safely handled null vector being passed to start_user_clip_plane.
22 * 22 3/18/98 4:53p John
23 * Fixed some bugs with docked ships warping out
25 * 21 3/18/98 4:33p John
26 * Called vm_vec_normalize_safe to prevent assert from bogus docked
29 * 20 3/16/98 5:02p John
32 * 19 3/16/98 4:51p John
33 * Added low-level code to clip all polygons against an arbritary plane.
34 * Took out all old model_interp_zclip and used this new method instead.
36 * 18 3/10/98 4:19p John
37 * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
38 * & Glide have popups and print screen. Took out all >8bpp software
39 * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
40 * support Fred. Made zbuffering key off of functions rather than one
43 * 17 1/19/98 6:15p John
44 * Fixed all my Optimized Build compiler warnings
46 * 16 11/24/97 12:04p John
48 * 15 11/07/97 7:24p John
49 * changed lighting to take two ranges.
50 * In textest, added test code to draw nebulas
52 * 14 10/29/97 5:05p John
53 * Changed dynamic lighting to only rotate and calculate lighting for
54 * point lights that are close to an object. Changed lower framerate cap
57 * 13 4/29/97 12:24p Adam
58 * JAS: Added code for delayed point to vec. Fixed some FRED
59 * sequencing problems with g3_start_frame / g3_end_frame.
61 * 12 4/29/97 9:55a John
63 * 11 4/08/97 5:18p John
64 * First rev of decent (dynamic, correct) lighting in FreeSpace.
66 * 10 3/24/97 3:26p John
67 * Cleaned up and restructured model_collide code and fvi code. In fvi
68 * made code that finds uvs work.. Added bm_get_pixel to BmpMan.
70 * 9 3/10/97 2:25p John
71 * Made pofview zbuffer. Made textest work with new model code. Took
72 * out some unnecessary Asserts in the 3d clipper.
75 * 8 2/17/97 5:18p John
76 * Added a bunch of RCS headers to a bunch of old files that don't have
83 #include "3dinternal.h"
85 #include "2d.h" // Needed for w,h,aspect of canvas
89 matrix View_matrix; // The matrix to convert local coordinates to screen
90 vector View_position; // The offset to convert local coordinates to screen
91 matrix Unscaled_matrix; // View_matrix before scaling
93 matrix Light_matrix; // Used to rotate world points into current local coordinates
94 vector Light_base; // Used to rotate world points into current local coordinates
96 matrix Eye_matrix; // Where the viewer's eye is pointing in World coordinates
97 vector Eye_position; // Where the viewer's eye is at in World coordinates
99 float View_zoom; // The zoom factor
101 vector Window_scale; // Scaling for window aspect
102 vector Matrix_scale; // How the matrix is scaled, window_scale * zoom
104 int Canvas_width; // The actual width
105 int Canvas_height; // The actual height
107 float Canv_w2; // Canvas_width / 2
108 float Canv_h2; // Canvas_height / 2
110 //vertex buffers for polygon drawing and clipping
111 vertex * Vbuf0[TMAP_MAX_VERTS];
112 vertex * Vbuf1[TMAP_MAX_VERTS];
114 #define MAX_INSTANCE_DEPTH 5
116 struct instance_context {
121 } instance_stack[MAX_INSTANCE_DEPTH];
123 int instance_depth = 0;
126 int G3_frame_count = 0;
129 // Pass true for zbuffer_flag to turn on zbuffering
130 void g3_start_frame_func(int zbuffer_flag, char * filename, int lineno)
136 //Uncomment this to figure out who called g3_start_frame without calling g3_end_frame.
137 // mprintf(( "g3_start_frame called from %s, line %d\n", filename, lineno ));
139 Assert( G3_count == 0 );
142 // Clear any user-defined clip planes
143 g3_stop_user_clip_plane();
145 // Get the values from the 2d...
146 width = gr_screen.clip_width;
147 height = gr_screen.clip_height;
148 aspect = gr_screen.aspect;
150 //set int w,h & fixed-point w,h/2
151 Canvas_width = width;
152 Canv_w2 = (float)width / 2.0f;
153 Canvas_height = height;
154 Canv_h2 = (float)height / 2.0f;
156 //compute aspect ratio for this canvas
158 s = aspect*(float)Canvas_height/(float)Canvas_width;
160 if (s <= 0) { //scale x
162 Window_scale.y = 1.0f;
165 Window_scale.y = 1.0f / s;
166 Window_scale.x = 1.0f;
169 Window_scale.z = 1.0f; //always 1
174 gr_zbuffer_clear(TRUE);
176 gr_zbuffer_clear(FALSE);
181 //init_interface_vars_to_assembler(); //for the texture-mapper
185 //this doesn't do anything, but is here for completeness
186 void g3_end_frame(void)
189 Assert( G3_count == 0 );
192 // Assert(free_point_num==0);
196 void scale_matrix(void);
198 //set view from x,y,z, viewer matrix, and zoom. Must call one of g3_set_view_*()
199 void g3_set_view_matrix(vector *view_pos,matrix *view_matrix,float zoom)
201 Assert( G3_count == 1 );
204 View_position = *view_pos;
206 View_matrix = *view_matrix;
208 Eye_matrix = View_matrix;
209 Eye_position = *view_pos;
213 Light_matrix = vmd_identity_matrix;
221 //set view from x,y,z & p,b,h, zoom. Must call one of g3_set_view_*()
222 void g3_set_view_angles(vector *view_pos,angles *view_orient,float zoom)
226 Assert( G3_count == 1 );
228 vm_angles_2_matrix(&tmp,view_orient);
229 g3_set_view_matrix(view_pos,&tmp,zoom);
233 //performs aspect scaling on global view matrix
234 void scale_matrix(void)
236 Unscaled_matrix = View_matrix; //so we can use unscaled if we want
238 Matrix_scale = Window_scale;
240 if (View_zoom <= 1.0) //zoom in by scaling z
242 Matrix_scale.z = Matrix_scale.z*View_zoom;
244 else { //zoom out by scaling x&y
246 float s = (float)1.0 / View_zoom;
248 Matrix_scale.x = Matrix_scale.x*s;
249 Matrix_scale.y = Matrix_scale.y*s;
252 //now scale matrix elements
254 vm_vec_scale(&View_matrix.rvec,Matrix_scale.x);
255 vm_vec_scale(&View_matrix.uvec,Matrix_scale.y);
256 vm_vec_scale(&View_matrix.fvec,Matrix_scale.z);
260 ubyte g3_rotate_vertex_popped(vertex *dest,vector *src)
264 Assert( G3_count == 1 );
266 Assert( instance_depth > 0 );
268 vm_vec_sub(&tempv,src,&instance_stack[0].p);
269 vm_vec_rotate( (vector *)&dest->x, &tempv, &instance_stack[0].m );
270 dest->flags = 0; //not projected
271 return g3_code_vertex(dest);
275 //instance at specified point with specified orientation
276 //if matrix==NULL, don't modify matrix. This will be like doing an offset
277 //if pos==NULL, no position change
278 void g3_start_instance_matrix(vector *pos,matrix *orient)
283 Assert( G3_count == 1 );
285 Assert(instance_depth<MAX_INSTANCE_DEPTH);
287 instance_stack[instance_depth].m = View_matrix;
288 instance_stack[instance_depth].p = View_position;
289 instance_stack[instance_depth].lm = Light_matrix;
290 instance_stack[instance_depth].lb = Light_base;
293 // Make sure orient is valid
295 orient = &vmd_identity_matrix; // Assume no change in orient
299 //step 1: subtract object position from view position
300 vm_vec_sub2(&View_position,pos);
302 //step 2: rotate view vector through object matrix
303 vm_vec_rotate(&tempv,&View_position,orient);
304 View_position = tempv;
306 // No movement, leave View_position alone
309 //step 3: rotate object matrix through view_matrix (vm = ob * vm)
310 vm_copy_transpose_matrix(&tempm2,orient);
312 vm_matrix_x_matrix(&tempm,&tempm2,&View_matrix);
316 // Update the lighting matrix
317 matrix saved_orient = Light_matrix;
318 vector saved_base = Light_base;
321 vm_vec_unrotate(&Light_base,pos,&saved_orient );
322 vm_vec_add2(&Light_base, &saved_base );
324 // No movement, light_base doesn't change.
327 vm_matrix_x_matrix(&Light_matrix,&saved_orient, orient);
332 //instance at specified point with specified orientation
333 //if angles==NULL, don't modify matrix. This will be like doing an offset
334 void g3_start_instance_angles(vector *pos,angles *orient)
338 Assert( G3_count == 1 );
341 g3_start_instance_matrix(pos,NULL);
345 vm_angles_2_matrix(&tm,orient);
347 g3_start_instance_matrix(pos,&tm);
352 //pops the old context
353 void g3_done_instance()
355 Assert( G3_count == 1 );
359 Assert(instance_depth >= 0);
361 View_position = instance_stack[instance_depth].p;
362 View_matrix = instance_stack[instance_depth].m;
363 Light_matrix = instance_stack[instance_depth].lm;
364 Light_base = instance_stack[instance_depth].lb;
368 int G3_user_clip = 0;
369 vector G3_user_clip_normal;
370 vector G3_user_clip_point;
372 // Enables clipping with an arbritary plane. This will be on
373 // until g3_stop_clip_plane is called or until next frame.
374 // The points passed should be relative to the instance. Probably
375 // that means world coordinates.
377 This works like any other clip plane... if this is enabled and you
378 rotate a point, the CC_OFF_USER bit will be set in the clipping codes.
379 It is completely handled by most g3_draw primitives, except maybe lines.
381 As far as performance, when enabled, it will slow down each point
382 rotation (or g3_code_vertex call) by a vector subtraction and dot
383 product. It won't slow anything down for polys that are completely
384 clipped on or off by the plane, and will slow each clipped polygon by
385 not much more than any other clipping we do.
387 void g3_start_user_clip_plane( vector *plane_point, vector *plane_normal )
389 float mag = vm_vec_mag( plane_normal );
390 if ( (mag < 0.1f) || (mag > 1.5f ) ) {
391 // Invalid plane_normal passed in. Get Allender (since it is
392 // probably a ship warp in bug:) or John.
398 // G3_user_clip_normal = *plane_normal;
399 // G3_user_clip_point = *plane_point;
402 vm_vec_rotate(&G3_user_clip_normal, plane_normal, &View_matrix );
403 vm_vec_normalize(&G3_user_clip_normal);
406 vm_vec_sub(&tempv,plane_point,&View_position);
407 vm_vec_rotate(&G3_user_clip_point,&tempv,&View_matrix );
410 // Stops arbritary plane clipping
411 void g3_stop_user_clip_plane()
416 // Returns TRUE if point is behind user plane
417 int g3_point_behind_user_plane( vector *pnt )
419 if ( G3_user_clip ) {
421 vm_vec_sub( &tmp, pnt, &G3_user_clip_point );
422 if ( vm_vec_dot( &tmp, &G3_user_clip_normal ) <= 0.0f ) {