FS2_Open
Open source remastering of the Freespace 2 engine
objectsort.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
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 the
6  * source.
7  *
8 */
9 
10 
11 
12 #include <algorithm>
13 #include <list>
14 #include <vector>
15 
16 #include "asteroid/asteroid.h"
17 #include "cmdline/cmdline.h"
18 #include "debris/debris.h"
19 #include "graphics/gropengldraw.h"
20 #include "jumpnode/jumpnode.h"
21 #include "mission/missionparse.h"
22 #include "model/modelrender.h"
23 #include "nebula/neb.h"
24 #include "object/object.h"
25 #include "parse/scripting.h"
26 #include "render/3d.h"
27 #include "ship/ship.h"
28 #include "weapon/weapon.h"
29 
30 
32 {
33 public:
34  object *obj; // a pointer to the original object
35  float z, min_z, max_z; // The object's z values relative to viewer
36 
38  obj(NULL), z(0.0f), min_z(0.0f), max_z(1.0f)
39  {
40  }
41 
42  bool operator < (const sorted_obj &other) const;
43 };
44 
45 inline bool sorted_obj::operator < (const sorted_obj &other) const
46 {
47  int model_num_a = -1;
48  int model_num_b = -1;
49 
50  if ( obj->type == OBJ_SHIP ) {
51  ship_info *sip = &Ship_info[Ships[obj->instance].ship_info_index];
52 
53  model_num_a = sip->model_num;
54  } else if ( obj->type == OBJ_WEAPON ){
55  weapon_info *wip;
56 
57  wip = &Weapon_info[Weapons[obj->instance].weapon_info_index];
58 
59  if ( wip->render_type == WRT_POF ) {
60  model_num_a = wip->model_num;
61  }
62  } else if ( obj->type == OBJ_DEBRIS ) {
63  debris *db;
64 
65  db = &Debris[obj->instance];
66  model_num_a = db->model_num;
67  } else if ( obj->type == OBJ_ASTEROID ) {
68  asteroid *asp;
69 
70  asp = &Asteroids[obj->instance];
71  model_num_a = Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype];
72  }
73 
74  if ( other.obj->type == OBJ_SHIP ) {
76 
77  model_num_b = sip->model_num;
78  } else if ( other.obj->type == OBJ_WEAPON ){
79  weapon_info *wip;
80 
82 
83  if ( wip->render_type == WRT_POF ) {
84  model_num_b = wip->model_num;
85  }
86  } else if ( other.obj->type == OBJ_DEBRIS ) {
87  debris *db;
88 
89  db = &Debris[other.obj->instance];
90  model_num_b = db->model_num;
91  } else if ( other.obj->type == OBJ_ASTEROID ) {
92  asteroid *asp;
93 
94  asp = &Asteroids[other.obj->instance];
95  model_num_b = Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype];
96  }
97 
98  if ( model_num_a == model_num_b ) {
99  return (max_z > other.max_z);
100  }
101 
102  return model_num_a < model_num_b;
103 }
104 
105 
110 // Used to (fairly) quicky find the 8 extreme
111 // points around an object.
113  { { { -1.0f, -1.0f, -1.0f } } },
114  { { { -1.0f, -1.0f, 1.0f } } },
115  { { { -1.0f, 1.0f, -1.0f } } },
116  { { { -1.0f, 1.0f, 1.0f } } },
117  { { { 1.0f, -1.0f, -1.0f } } },
118  { { { 1.0f, -1.0f, 1.0f } } },
119  { { { 1.0f, 1.0f, -1.0f } } },
120  { { { 1.0f, 1.0f, 1.0f } } }
121 };
122 
123 // See if an object is in the view cone.
124 // Returns:
125 // 0 if object isn't in the view cone
126 // 1 if object is in cone
127 // This routine could possibly be optimized. Right now, for an
128 // offscreen object, it has to rotate 8 points to determine it's
129 // offscreen. Not the best considering we're looking at a sphere.
130 int obj_in_view_cone( object * objp )
131 {
132  int i;
133  vec3d tmp,pt;
134  ubyte codes;
135 
136  // Center isn't in... are other points?
137  ubyte and_codes = 0xff;
138 
139  for (i=0; i<8; i++ ) {
140  vm_vec_scale_add( &pt, &objp->pos, &check_offsets[i], objp->radius );
141  codes=g3_rotate_vector(&tmp,&pt);
142  if ( !codes ) {
143  //mprintf(( "A point is inside, so render it.\n" ));
144  return 1; // this point is in, so return 1
145  }
146  and_codes &= codes;
147  }
148 
149  if (and_codes) {
150  //mprintf(( "All points offscreen, so don't render it.\n" ));
151  return 0; //all points off screen
152  }
153 
154  //mprintf(( "All points inside, so render it, but doesn't need clipping.\n" ));
155  return 1;
156 }
157 
158 inline bool obj_render_is_model(object *obj)
159 {
160  return obj->type == OBJ_SHIP
161  || (obj->type == OBJ_WEAPON
163  || obj->type == OBJ_ASTEROID
164  || obj->type == OBJ_DEBRIS
165  || obj->type == OBJ_JUMP_NODE;
166 }
167 
168 // Sorts all the objects by Z and renders them
169 extern int Fred_active;
170 extern int Cmdline_nohtl;
171 extern int Interp_no_flush;
172 void obj_render_all(void (*render_function)(object *objp), bool *draw_viewer_last )
173 {
174  object *objp;
175  int i;
176  float fog_near, fog_far;
177 #ifdef DYN_CLIP_DIST
178  float closest_obj = Max_draw_distance;
179  float farthest_obj = Min_draw_distance;
180 #endif
181 
182  objp = Objects;
183 
184  for (i=0;i<=Highest_object_index;i++,objp++) {
185  if ( (objp->type != OBJ_NONE) && (objp->flags&OF_RENDERS) ) {
186  objp->flags &= ~OF_WAS_RENDERED;
187 
188  if ( obj_in_view_cone(objp) ) {
189  sorted_obj osp;
190 
191  osp.obj = objp;
192 
193  vec3d to_obj;
194  vm_vec_sub( &to_obj, &objp->pos, &Eye_position );
195  osp.z = vm_vec_dot( &Eye_matrix.vec.fvec, &to_obj );
196 /*
197  if ( objp->type == OBJ_SHOCKWAVE )
198  osp.z -= 2*objp->radius;
199 */
200  // Make warp in effect draw after any ship in it
201  if ( objp->type == OBJ_FIREBALL ) {
202  //if ( fireball_is_warp(objp) ) {
203  osp.z -= 2*objp->radius;
204  //}
205  }
206 
207  osp.min_z = osp.z - objp->radius;
208  osp.max_z = osp.z + objp->radius;
209 
210  Sorted_objects.push_back(osp);
211 
212 #ifdef DYN_CLIP_DIST
213  if(objp != Viewer_obj)
214  {
215  if(osp->min_z < closest_obj)
216  closest_obj = osp->min_z;
217  if(osp->max_z > farthest_obj)
218  farthest_obj = osp->max_z;
219  }
220 #endif
221  }
222  }
223  }
224 
225  if ( Sorted_objects.empty() )
226  return;
227 
228  std::sort(Sorted_objects.begin(), Sorted_objects.end());
229 
230 #ifdef DYN_CLIP_DIST
231  if (!Cmdline_nohtl)
232  {
233  if(closest_obj < Min_draw_distance)
234  closest_obj = Min_draw_distance;
235  if(farthest_obj > Max_draw_distance)
236  farthest_obj = Max_draw_distance;
237 
238  gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, closest_obj, farthest_obj);
240  }
241 #endif
242 
244 
245  Interp_no_flush = 1;
246 
248  bool c_viewer = (!Viewer_mode || (Viewer_mode & VM_PADLOCK_ANY) || (Viewer_mode & VM_OTHER_SHIP) || (Viewer_mode & VM_TRACK));
249 
250  // now draw them
251  // only render models in this loop in order to minimize state changes
253  for (os = Sorted_objects.begin(); os != Sorted_objects.end(); ++os) {
254  object *obj = os->obj;
255 
256  obj->flags |= OF_WAS_RENDERED;
257 
258  //This is for ship cockpits. Bobb, feel free to optimize this any way you see fit
259  if ( (obj == Viewer_obj)
260  && (obj->type == OBJ_SHIP)
261  && c_viewer
263  {
264  (*draw_viewer_last) = true;
265  continue;
266  }
267 
268  // if we're fullneb, fire up the fog - this also generates a fog table
269  if (full_neb) {
270  // get the fog values
271  neb2_get_adjusted_fog_values(&fog_near, &fog_far, obj);
272 
273  // only reset fog if the fog mode has changed - since regenerating a fog table takes
274  // a bit of time
275  if((fog_near != gr_screen.fog_near) || (fog_far != gr_screen.fog_far)){
277  }
278 
279  // maybe skip rendering an object because its obscured by the nebula
280  if(neb2_skip_render(obj, os->z)){
281  continue;
282  }
283  }
284 
285  if ( obj_render_is_model(obj) ) {
286  if( ((obj->type == OBJ_SHIP) && Ships[obj->instance].shader_effect_active) || (obj->type == OBJ_FIREBALL) )
287  effect_ships.push_back(obj);
288  else
289  (*render_function)(obj);
290  }
292  {
293  object_had_transparency = false;
294  transparent_objects.push_back(obj);
295  }
296  }
298  Interp_no_flush = 0;
299 
300  // we're done rendering models so flush render states
301  gr_clear_states();
302  gr_set_buffer(-1);
303 
304  // render everything else that isn't a model
305  for (os = Sorted_objects.begin(); os != Sorted_objects.end(); ++os) {
306  object *obj = os->obj;
307 
308  obj->flags |= OF_WAS_RENDERED;
309 
310  if ( obj_render_is_model(obj) )
311  continue;
312 
313  // if we're fullneb, fire up the fog - this also generates a fog table
315  // get the fog values
316  neb2_get_adjusted_fog_values(&fog_near, &fog_far, obj);
317 
318  // only reset fog if the fog mode has changed - since regenerating a fog table takes
319  // a bit of time
320  if((GR_FOGMODE_FOG != gr_screen.current_fog_mode) || (fog_near != gr_screen.fog_near) || (fog_far != gr_screen.fog_far)) {
322  }
323 
324  // maybe skip rendering an object because its obscured by the nebula
325  if(neb2_skip_render(obj, os->z)){
326  continue;
327  }
328  }
329 
330  (*render_function)(obj);
331  }
332 
333  Sorted_objects.clear();
334 
335  //WMC - draw maneuvering thrusters
336  extern void batch_render_man_thrusters();
338 
339  // if we're fullneb, switch off the fog effet
341  gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
342  }
343 
345 }
346 
348 {
349  object *objp;
350  int i;
351  draw_list scene;
352 
353  objp = Objects;
354 
356 
357  scene.init();
358 
359  for ( i = 0; i <= Highest_object_index; i++,objp++ ) {
360  if ( (objp->type != OBJ_NONE) && ( objp->flags & OF_RENDERS ) ) {
361  objp->flags &= ~OF_WAS_RENDERED;
362 
363  if ( !obj_in_view_cone(objp) ) {
364  continue;
365  }
366 
368  vec3d to_obj;
369  vm_vec_sub( &to_obj, &objp->pos, &Eye_position );
370  float z = vm_vec_dot( &Eye_matrix.vec.fvec, &to_obj );
371 
372  if ( neb2_skip_render(objp, z) ){
373  continue;
374  }
375  }
376 
377  if ( obj_render_is_model(objp) ) {
378  if( (objp->type == OBJ_SHIP) && Ships[objp->instance].shader_effect_active ) {
379  effect_ships.push_back(objp);
380  }
381  }
382 
383  objp->flags |= OF_WAS_RENDERED;
384  profile_begin("Queue Render");
385  obj_queue_render(objp, &scene);
386  profile_end("Queue Render");
387  }
388  }
389 
390  scene.init_render();
391 
392  PROFILE("Submit Draws", scene.render_all(GR_ZBUFF_FULL));
394  gr_zbias(0);
395  gr_set_cull(0);
396 
397  gr_clear_states();
398  gr_set_buffer(-1);
400 
402  PROFILE("Apply Lights", gr_deferred_lighting_finish());
403 
405 
407  gr_set_lighting(false, false);
408 
409  // now render transparent meshes
410  PROFILE("Submit Draws", scene.render_all(GR_ZBUFF_READ));
411  PROFILE("Submit Draws", scene.render_all(GR_ZBUFF_NONE));
412 
413  // render electricity effects and insignias
414  scene.render_outlines();
415  scene.render_insignias();
416  scene.render_arcs();
417 
419  gr_zbias(0);
420  gr_set_cull(0);
422 
423  gr_clear_states();
424  gr_set_buffer(-1);
425 
427  gr_set_lighting(false, false);
428 
429  //WMC - draw maneuvering thrusters
430  extern void batch_render_man_thrusters();
432 
433  // if we're fullneb, switch off the fog effet
435  gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
436  }
437 
438  PROFILE("Draw Effects", batch_render_all());
439 
440  gr_zbias(0);
442  gr_set_cull(0);
444 
445  gr_clear_states();
446  gr_set_buffer(-1);
447 
449  gr_set_lighting(false, false);
450 
452 }
#define gr_zbuffer_set
Definition: 2d.h:817
int i
Definition: multi_pxo.cpp:466
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
int Interp_no_flush
#define SIF2_SHOW_SHIP_MODEL
Definition: ship.h:921
float Proj_fov
Definition: 3dsetup.cpp:31
int Cmdline_nohtl
Definition: cmdline.cpp:438
bool operator<(const sorted_obj &other) const
Definition: objectsort.cpp:45
#define OBJ_FIREBALL
Definition: object.h:34
int Neb2_render_mode
Definition: neb.cpp:57
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
#define MISSION_FLAG_FULLNEB
Definition: missionparse.h:70
int current_fog_mode
Definition: 2d.h:394
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
float min_z
Definition: objectsort.cpp:35
asteroid Asteroids[MAX_ASTEROIDS]
Definition: asteroid.cpp:63
SCP_vector< sorted_obj > Sorted_objects
Definition: objectsort.cpp:106
int Fred_running
Definition: fred.cpp:44
int model_num
Definition: ship.h:1189
#define GR_ZBUFF_READ
Definition: 2d.h:674
#define OF_WAS_RENDERED
Definition: object.h:113
Definition: pstypes.h:88
#define OBJ_ASTEROID
Definition: object.h:44
#define OF_RENDERS
Definition: object.h:103
matrix Eye_matrix
Definition: 3dsetup.cpp:26
#define GR_ZBUFF_FULL
Definition: 2d.h:675
#define VM_TRACK
Definition: systemvars.h:32
GLclampf f
Definition: Glext.h:7097
void render_arcs()
#define GR_ZBUFF_NONE
Definition: 2d.h:672
int model_num
Definition: debris.h:34
void init()
opengl_texture_state Texture
#define GR_FILL_MODE_SOLID
Definition: 2d.h:670
ubyte blue
Definition: 2d.h:102
object * objp
Definition: lua.cpp:3105
void profile_begin(const char *name)
Definition: profiling.cpp:80
SCP_vector< object * > transparent_objects
Definition: objectsort.cpp:108
vec3d pos
Definition: object.h:152
int render_type
Definition: weapon.h:327
int asteroid_subtype
Definition: asteroid.h:103
#define PROFILE(name, function)
Definition: systemvars.h:251
ubyte green
Definition: 2d.h:101
float max_z
Definition: objectsort.cpp:35
int weapon_info_index
Definition: weapon.h:164
#define gr_set_lighting
Definition: 2d.h:924
int asteroid_type
Definition: asteroid.h:102
#define WRT_POF
Definition: weapon.h:35
#define gr_set_view_matrix
Definition: 2d.h:895
int instance
Definition: object.h:150
Definition: debris.h:23
void batch_render_all(int stream_buffer)
Definition: grbatch.cpp:1124
#define gr_set_proj_matrix
Definition: 2d.h:893
struct matrix::@228::@230 vec
#define gr_deferred_lighting_end
Definition: 2d.h:921
float clip_aspect
Definition: 2d.h:372
void render_insignias()
#define gr_set_buffer
Definition: 2d.h:891
#define OBJ_WEAPON
Definition: object.h:33
object * obj
Definition: objectsort.cpp:34
float Max_draw_distance
Definition: 2d.cpp:85
#define OBJ_DEBRIS
Definition: object.h:37
void batch_render_man_thrusters()
Definition: ship.cpp:6668
GLdouble GLdouble z
Definition: Glext.h:5451
ubyte red
Definition: 2d.h:100
object * Viewer_obj
Definition: object.cpp:57
vec3d check_offsets[8]
Definition: objectsort.cpp:112
void init_render(bool sort=true)
debris Debris[MAX_DEBRIS_PIECES]
Definition: debris.cpp:41
ubyte g3_rotate_vector(vec3d *dest, const vec3d *src)
Definition: 3dmath.cpp:171
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
unsigned char ubyte
Definition: pstypes.h:62
#define gr_set_cull
Definition: 2d.h:838
#define OBJ_SHIP
Definition: object.h:32
color current_fog_color
Definition: 2d.h:397
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
vec3d Eye_position
Definition: 3dsetup.cpp:27
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
__inline void gr_fog_set(int fog_mode, int r, int g, int b, float fog_near=-1.0f, float fog_far=-1.0f)
Definition: 2d.h:833
void profile_end(const char *name)
Definition: profiling.cpp:130
SCP_vector< object * > effect_ships
Definition: objectsort.cpp:107
void obj_render_all(void(*render_function)(object *objp), bool *draw_viewer_last)
Definition: objectsort.cpp:172
#define gr_zbias
Definition: 2d.h:932
opengl_state GL_state
float fog_far
Definition: 2d.h:383
screen gr_screen
Definition: 2d.cpp:46
float Min_draw_distance
Definition: 2d.cpp:84
int neb2_skip_render(object *objp, float z_depth)
Definition: neb.cpp:527
#define gr_clear_states
Definition: 2d.h:946
bool shader_effect_active
Definition: ship.h:769
float fog_near
Definition: 2d.h:383
void render_all(int depth_mode=-1)
int ship_info_index
Definition: ship.h:539
int Highest_object_index
Definition: object.cpp:69
void neb2_get_adjusted_fog_values(float *fnear, float *ffar, object *objp)
Definition: neb.cpp:1170
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
int Fred_active
Definition: fred.cpp:47
#define VM_PADLOCK_ANY
Definition: systemvars.h:46
#define gr_deferred_lighting_begin
Definition: 2d.h:920
int Viewer_mode
Definition: systemvars.cpp:28
#define gr_set_fill_mode
Definition: 2d.h:933
GLsizei GLsizei GLuint * obj
Definition: Glext.h:5619
#define GR_FOGMODE_FOG
Definition: 2d.h:356
bool object_had_transparency
Definition: objectsort.cpp:109
#define gr_reset_lighting
Definition: 2d.h:907
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
int model_num
Definition: weapon.h:329
#define gr_deferred_lighting_finish
Definition: 2d.h:922
void render_outlines()
bool obj_render_is_model(object *obj)
Definition: objectsort.cpp:158
int obj_in_view_cone(object *objp)
Definition: objectsort.cpp:130
#define NEB2_RENDER_NONE
Definition: neb.h:31
#define VM_OTHER_SHIP
Definition: systemvars.h:35
#define OBJ_NONE
Definition: object.h:31
uint flags
Definition: object.h:151
float radius
Definition: object.h:154
mission The_mission
char type
Definition: object.h:146
void obj_queue_render(object *obj, draw_list *scene)
Definition: object.cpp:1625
SCP_vector< asteroid_info > Asteroid_info
Definition: asteroid.cpp:62
#define OBJ_JUMP_NODE
Definition: object.h:45
#define GR_FOGMODE_NONE
Definition: 2d.h:355
void obj_render_queue_all()
Definition: objectsort.cpp:347