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/Object/ObjectSort.cpp $
15 * Sorting code for objects.
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 * 12 8/30/99 5:01p Dave
29 * Made d3d do less state changing in the nebula. Use new chat server for
32 * 11 3/31/99 8:24p Dave
33 * Beefed up all kinds of stuff, incluging beam weapons, nebula effects
34 * and background nebulae. Added per-ship non-dimming pixel colors.
36 * 10 2/08/99 5:07p Dave
37 * FS2 chat server support. FS2 specific validated missions.
39 * 9 12/10/98 1:25p Dan
40 * Fixed fogging in fred.
42 * 8 12/10/98 11:16a Dan
43 * Fixed problem where Fred tries to fog objects (which it can't because
44 * it runs in the software renderer).
46 * 7 12/09/98 7:34p Dave
47 * Cleanup up nebula effect. Tweaked many values.
49 * 6 12/08/98 9:36a Dave
50 * Almost done nebula effect for D3D. Looks 85% as good as Glide.
52 * 5 12/07/98 5:51p Dave
53 * Finally got d3d fog working! Now we just need to tweak values.
55 * 4 12/06/98 6:53p Dave
57 * 3 12/06/98 2:36p Dave
58 * Drastically improved nebula fogging.
60 * 2 10/07/98 10:53a Dave
63 * 1 10/07/98 10:50a Dave
65 * 39 3/12/98 1:24p Mike
66 * When weapons linked, increase firing delay.
67 * Free up weapon slots for AI ships, if necessary.
68 * Backside render shield effect.
69 * Remove shield hit triangle if offscreen.
71 * 38 3/10/98 4:19p John
72 * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
73 * & Glide have popups and print screen. Took out all >8bpp software
74 * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
75 * support Fred. Made zbuffering key off of functions rather than one
78 * 37 2/13/98 2:48p Lawrance
79 * Don't modify max_z position for shockwaves
81 * 36 1/15/98 2:16p John
82 * Made bitmaps zbuffer at center minus radius.
83 * Made fireballs sort after objects they are around.
85 * 35 10/24/97 7:53p John
86 * added new code to detect if object is in view cone to fix clipping
87 * problems once and for all.
89 * 34 9/09/97 4:52p John
90 * Almost done ship warp in code
92 * 33 8/05/97 1:46p Mike
93 * Comment out code that shows spheres where wingmen should be.
95 * 32 7/16/97 5:51p Lawrance
96 * make shockwaves translucent
98 * 31 6/30/97 1:58p John
99 * made obj_render_all only sort objects in view cone. Made physics_pause
102 * 30 6/27/97 4:44p John
103 * changed sorting to be faster and sort by the real z depth (not the
104 * rotated z) in preparation for speeding up collision detection by using
107 * 29 6/24/97 6:22p John
108 * added detail flags.
109 * sped up motion debris system a bit.
111 * 28 6/20/97 4:54p John
112 * added detail levels. Started adding some code framework to optimize
115 * 27 6/19/97 6:21p John
116 * optimized object sorting.
118 * 26 5/12/97 12:27p John
119 * Restructured Graphics Library to add support for multiple renderers.
121 * 25 5/02/97 10:57a John
122 * moved non-ships zcheck out by radius.
124 * 24 5/02/97 10:56a John
125 * put back in code that draws smaller objects that are within a larger
126 * object's radius after the large object.
128 * 23 5/02/97 10:26a John
129 * made non-ship objects use minimum z for z testing.
131 * 22 3/26/97 12:38p Hoffoss
132 * JAS: made object sorting look at gr_zbuffering instead of
135 * 21 3/12/97 9:25a John
136 * fixed a bug with zbuffering. Reenabled it by default.
138 * 20 3/10/97 6:21p John
139 * Simplified rendering code a bit.
141 * 19 3/06/97 5:07p Mike
142 * turned in full zbuffering for now
144 * 18 3/04/97 12:09a Mike
145 * Clean up code. Make External_view_mode well-behaved. Add
146 * aip->repair_objnum to save/restore. Add restore_int_if() in state.cpp.
156 #include "systemvars.h"
157 #include "fireballs.h"
158 #include "missionparse.h"
161 typedef struct sorted_obj {
162 object *obj; // a pointer to the original object
163 float z, min_z, max_z; // The object's z values relative to viewer
166 int Num_sorted_objects = 0;
167 sorted_obj Sorted_objects[MAX_OBJECTS];
168 int Object_sort_order[MAX_OBJECTS];
171 // Used to (fairly) quicky find the 8 extreme
172 // points around an object.
173 vector check_offsets[8] = {
174 { -1.0f, -1.0f, -1.0f },
175 { -1.0f, -1.0f, 1.0f },
176 { -1.0f, 1.0f, -1.0f },
177 { -1.0f, 1.0f, 1.0f },
178 { 1.0f, -1.0f, -1.0f },
179 { 1.0f, -1.0f, 1.0f },
180 { 1.0f, 1.0f, -1.0f },
184 // See if an object is in the view cone.
186 // 0 if object isn't in the view cone
187 // 1 if object is in cone
188 // This routine could possibly be optimized. Right now, for an
189 // offscreen object, it has to rotate 8 points to determine it's
190 // offscreen. Not the best considering we're looking at a sphere.
191 int obj_in_view_cone( object * objp )
197 // Use this to hack out player for testing.
198 // if ( objp == Player_obj ) return 0;
200 // OLD INCORRECT CODE!!!
201 // g3_rotate_vector(&tmp,&objp->pos);
202 // codes=g3_code_vector_radius(&tmp, objp->radius);
204 // return 1; // center is in, so return 1
208 // This I commented out because it will quickly out for
209 // objects in the center, but cause one more rotation
210 // for objects outside the center. So I figured it
211 // would be best to slow down objects inside by a bit
212 // and not penalize the offscreen ones, which require
213 // 8 rotatations to throw out.
214 // g3_rotate_vector(&tmp,&objp->pos);
215 // codes=g3_code_vector(&tmp);
217 // //mprintf(( "Center is in, so render it\n" ));
218 // return 1; // center is in, so return 1
221 // Center isn't in... are other points?
223 ubyte and_codes = 0xff;
225 for (i=0; i<8; i++ ) {
226 vm_vec_scale_add( &pt, &objp->pos, &check_offsets[i], objp->radius );
227 g3_rotate_vector(&tmp,&pt);
228 codes=g3_code_vector(&tmp);
230 //mprintf(( "A point is inside, so render it.\n" ));
231 return 1; // this point is in, so return 1
237 //mprintf(( "All points offscreen, so don't render it.\n" ));
238 return 0; //all points off screen
241 //mprintf(( "All points inside, so render it, but doesn't need clipping.\n" ));
246 // Sorts all the objects by Z and renders them
247 extern int Fred_active;
248 void obj_render_all(void (*render_function)(object *objp) )
252 float fog_near, fog_far;
255 Num_sorted_objects = 0;
256 for (i=0;i<=Highest_object_index;i++,objp++) {
257 if ( (objp->type != OBJ_NONE) && (objp->flags&OF_RENDERS) ) {
258 objp->flags &= ~OF_WAS_RENDERED;
260 if ( obj_in_view_cone(objp) ) {
261 sorted_obj * osp = &Sorted_objects[Num_sorted_objects];
262 Object_sort_order[Num_sorted_objects] = Num_sorted_objects;
263 Num_sorted_objects++;
267 vm_vec_sub( &to_obj, &objp->pos, &Eye_position );
268 osp->z = vm_vec_dot( &Eye_matrix.v.fvec, &to_obj );
270 if ( objp->type == OBJ_SHOCKWAVE )
271 osp->z -= 2*objp->radius;
273 // Make warp in effect draw after any ship in it
274 if ( objp->type == OBJ_FIREBALL ) {
275 //if ( fireball_is_warp(objp) ) {
276 osp->z -= 2*objp->radius;
280 osp->min_z = osp->z - objp->radius;
281 osp->max_z = osp->z + objp->radius;
287 // Sort them by their maximum z value
288 if ( Num_sorted_objects > 1 ) {
289 incr = Num_sorted_objects / 2;
291 for (i=incr; i<Num_sorted_objects; i++ ) {
294 // compare element j and j+incr
295 if ( (Sorted_objects[Object_sort_order[j]].max_z < Sorted_objects[Object_sort_order[j+incr]].max_z) ) {
296 // If not in correct order, them swap 'em
298 tmp = Object_sort_order[j];
299 Object_sort_order[j] = Object_sort_order[j+incr];
300 Object_sort_order[j+incr] = tmp;
311 gr_zbuffer_set( GR_ZBUFF_FULL );
314 for (i=0; i<Num_sorted_objects; i++) {
315 sorted_obj * os = &Sorted_objects[Object_sort_order[i]];
316 os->obj->flags |= OF_WAS_RENDERED;
318 // if we're fullneb, fire up the fog - this also generates a fog table
319 if((The_mission.flags & MISSION_FLAG_FULLNEB) && (Neb2_render_mode != NEB2_RENDER_NONE) && !Fred_running){
320 // get the fog values
321 neb2_get_fog_values(&fog_near, &fog_far, os->obj);
323 // only reset fog if the fog mode has changed - since regenerating a fog table takes
325 if((fog_near != gr_screen.fog_near) || (fog_far != gr_screen.fog_far)){
326 gr_fog_set(GR_FOGMODE_FOG, gr_screen.current_fog_color.red, gr_screen.current_fog_color.green, gr_screen.current_fog_color.blue, fog_near, fog_far);
329 // maybe skip rendering an object because its obscured by the nebula
330 if(neb2_skip_render(os->obj, os->z)){
335 (*render_function)(os->obj);
338 // if we're fullneb, switch off the fog effet
339 if((The_mission.flags & MISSION_FLAG_FULLNEB) && (Neb2_render_mode != NEB2_RENDER_NONE)){
340 gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
343 /* Show spheres where wingmen should be flying
345 extern void render_wing_phantoms_all();
346 render_wing_phantoms_all();