FS2_Open
Open source remastering of the Freespace 2 engine
modelrender.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Freespace Open 2013. All rights reserved.
3  *
4  * All source code herein is the property of Freespace Open. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 #include <algorithm>
11 
12 #include "asteroid/asteroid.h"
13 #include "cmdline/cmdline.h"
15 #include "graphics/gropengldraw.h"
18 #include "graphics/tmapper.h"
19 #include "io/timer.h"
20 #include "math/staticrand.h"
21 #include "model/modelrender.h"
22 #include "nebula/neb.h"
23 #include "particle/particle.h"
24 #include "render/3dinternal.h"
25 #include "ship/ship.h"
26 #include "ship/shipfx.h"
27 #include "weapon/weapon.h"
28 
29 extern int Model_texturing;
30 extern int Model_polys;
31 extern int tiling;
32 extern float model_radius;
33 
34 extern const int MAX_ARC_SEGMENT_POINTS;
35 extern int Num_arc_segment_points;
36 extern vec3d Arc_segment_points[];
37 
38 extern bool Scene_framebuffer_in_frame;
39 
40 extern void interp_render_arc_segment( vec3d *v1, vec3d *v2, int depth );
41 
43 extern float Interp_thrust_scale;
44 
45 draw_list *draw_list::Target = NULL;
46 
48 
50  Model_flags(MR_NORMAL),
51  Debug_flags(0),
52  Objnum(-1),
53  Detail_level_locked(-1),
54  Depth_scale(1500.0f),
55  Warp_bitmap(-1),
56  Warp_alpha(-1.0f),
57  Xparent_alpha(1.0f),
58  Forced_bitmap(-1),
59  Insignia_bitmap(-1),
60  Replacement_textures(NULL),
61  Team_color_set(false),
62  Clip_plane_set(false),
63  Animated_effect(-1),
64  Animated_timer(0.0f),
65  Thruster_info()
66 {
67  Warp_scale.xyz.x = 1.0f;
68  Warp_scale.xyz.y = 1.0f;
69  Warp_scale.xyz.z = 1.0f;
70 
71  Clip_normal = vmd_zero_vector;
72  Clip_pos = vmd_zero_vector;
73 
74  if ( !Model_texturing )
75  Model_flags |= MR_NO_TEXTURING;
76 
77  if ( !Model_polys ) {
78  Model_flags |= MR_NO_POLYS;
79  }
80 }
81 
83 {
84  return Model_flags;
85 }
86 
88 {
89  return Debug_flags;
90 }
91 
93 {
94  return Objnum;
95 }
96 
98 {
99  return Detail_level_locked;
100 }
101 
103 {
104  return Depth_scale;
105 }
106 
108 {
109  return Warp_bitmap;
110 }
111 
113 {
114  return Warp_alpha;
115 }
116 
118 {
119  return Warp_scale;
120 }
121 
123 {
124  return Color;
125 }
127 {
128  return Xparent_alpha;
129 }
130 
132 {
133  return Forced_bitmap;
134 }
135 
137 {
138  return Insignia_bitmap;
139 }
140 
142 {
143  return Replacement_textures;
144 }
145 
147 {
148  return Current_team_color;
149 }
150 
152 {
153  return Clip_pos;
154 }
155 
157 {
158  return Clip_normal;
159 }
160 
162 {
163  return Animated_effect;
164 }
165 
167 {
168  return Animated_timer;
169 }
170 
171 void model_render_params::set_animated_effect(int effect_num, float timer)
172 {
173  Animated_effect = effect_num;
174  Animated_timer = timer;
175 }
176 
178 {
179  Clip_plane_set = true;
180 
181  Clip_normal = normal;
182  Clip_pos = pos;
183 }
184 
186 {
187  return Clip_plane_set;
188 }
189 
191 {
192  Team_color_set = true;
193 
194  Current_team_color = clr;
195 }
196 
197 void model_render_params::set_team_color(const SCP_string &team, const SCP_string &secondaryteam, fix timestamp, int fadetime)
198 {
199  Team_color_set = model_get_team_color(&Current_team_color, team, secondaryteam, timestamp, fadetime);
200 }
201 
203 {
204  return Team_color_set;
205 }
206 
208 {
209  Replacement_textures = textures;
210 }
211 
213 {
214  Insignia_bitmap = bitmap;
215 }
216 
218 {
219  Forced_bitmap = bitmap;
220 }
221 
223 {
224  Xparent_alpha = alpha;
225 }
226 
228 {
229  Color = clr;
230 }
231 
232 void model_render_params::set_color(int r, int g, int b)
233 {
234  gr_init_color( &Color, r, g, b );
235 }
236 
238 {
239  Warp_bitmap = bitmap;
240  Warp_alpha = alpha;
241  Warp_scale = scale;
242 }
243 
245 {
246  Depth_scale = scale;
247 }
248 
250 {
251  Debug_flags = flags;
252 }
253 
255 {
256  Objnum = num;
257 }
258 
260 {
261  Model_flags = flags;
262 }
263 
265 {
266  Detail_level_locked = detail_level_lock;
267 }
268 
270 {
271  Thruster_info = info;
272 
273  CLAMP(Thruster_info.length.xyz.z, 0.1f, 1.0f);
274 }
275 
277 {
278  return Thruster_info;
279 }
280 
282 {
283  Submodel_matrices.clear();
284 
285  Current_offset = 0;
286 }
287 
289 {
290  matrix4 init_mat;
291 
292  memset(&init_mat, 0, sizeof(matrix4));
293 
294  init_mat.a1d[0] = 1.0f;
295  init_mat.a1d[5] = 1.0f;
296  init_mat.a1d[10] = 1.0f;
297  init_mat.a1d[15] = 1.0f; // set this to zero to indicate it's not to be drawn in the shader
298 
299  Current_offset = Submodel_matrices.size();
300 
301  for ( int i = 0; i < n_models; ++i ) {
302  Submodel_matrices.push_back(init_mat);
303  }
304 }
305 
307 {
308  Submodel_matrices[Current_offset + model_id] = transform;
309 }
310 
312 {
313  Submodel_matrices.push_back(mat);
314 }
315 
317 {
318  return Current_offset;
319 }
320 
321 void model_batch_buffer::allocate_memory()
322 {
323  uint size = Submodel_matrices.size() * sizeof(matrix4);
324 
325  if ( Mem_alloc == NULL || Mem_alloc_size < size ) {
326  if ( Mem_alloc != NULL ) {
327  vm_free(Mem_alloc);
328  }
329 
330  Mem_alloc = vm_malloc(size);
331  }
332 
333  Mem_alloc_size = size;
334  memcpy(Mem_alloc, &Submodel_matrices[0], size);
335 }
336 
338 {
339  if ( Submodel_matrices.size() == 0 ) {
340  return;
341  }
342 
343  allocate_memory();
344 
345  gr_update_transform_buffer(Mem_alloc, Mem_alloc_size);
346 }
347 
349 {
350  reset();
351 }
352 
354 {
355  Current_set_clip_plane = -1;
356 
357  Dirty_render_state = true;
358 
359  Current_render_state = render_state();
360 
361  Current_textures[TM_BASE_TYPE] = -1;
362  Current_textures[TM_GLOW_TYPE] = -1;
363  Current_textures[TM_SPECULAR_TYPE] = -1;
364  Current_textures[TM_NORMAL_TYPE] = -1;
365  Current_textures[TM_HEIGHT_TYPE] = -1;
366  Current_textures[TM_MISC_TYPE] = -1;
367 
368  Clip_planes.clear();
369  Render_states.clear();
370  Render_elements.clear();
371  Render_keys.clear();
372 
374 
375  Current_scale.xyz.x = 1.0f;
376  Current_scale.xyz.y = 1.0f;
377  Current_scale.xyz.z = 1.0f;
378 }
379 
380 void draw_list::sort_draws()
381 {
382  Target = this;
383  std::sort(Target->Render_keys.begin(), Target->Render_keys.end(), draw_list::sort_draw_pair);
384 }
385 
387 {
388  TransformBufferHandler.set_num_models(n_models);
389 }
390 
392 {
394 
395  memset(&transform, 0, sizeof(matrix4));
396 
397  // set basis
398  transform.a1d[0] = Current_transform.basis.a1d[0] * Current_scale.xyz.x;
399  transform.a1d[1] = Current_transform.basis.a1d[1];
400  transform.a1d[2] = Current_transform.basis.a1d[2];
401 
402  transform.a1d[4] = Current_transform.basis.a1d[3];
403  transform.a1d[5] = Current_transform.basis.a1d[4] * Current_scale.xyz.y;
404  transform.a1d[6] = Current_transform.basis.a1d[5];
405 
406  transform.a1d[8] = Current_transform.basis.a1d[6];
407  transform.a1d[9] = Current_transform.basis.a1d[7];
408  transform.a1d[10] = Current_transform.basis.a1d[8] * Current_scale.xyz.z;
409 
410  // set position
411  transform.a1d[12] = Current_transform.origin.a1d[0];
412  transform.a1d[13] = Current_transform.origin.a1d[1];
413  transform.a1d[14] = Current_transform.origin.a1d[2];
414 
415  // set visibility
416  transform.a1d[15] = 0.0f;
417 
418  TransformBufferHandler.set_model_transform(transform, model_num);
419 }
420 
421 void draw_list::set_depth_mode(int depth_set)
422 {
423 // if ( !dirty_render_state && depth_set != current_render_state.depth_mode ) {
424 // dirty_render_state = true;
425 // }
426 
427  Current_depth_mode = depth_set;
428 }
429 
430 void draw_list::add_arc(vec3d *v1, vec3d *v2, color *primary, color *secondary, float arc_width)
431 {
432  arc_effect new_arc;
433 
434  new_arc.transformation = Current_transform;
435  new_arc.v1 = *v1;
436  new_arc.v2 = *v2;
437  new_arc.primary = *primary;
438  new_arc.secondary = *secondary;
439  new_arc.width = arc_width;
440 
441  Arcs.push_back(new_arc);
442 }
443 
444 void draw_list::set_light_filter(int objnum, vec3d *pos, float rad)
445 {
446  Scene_light_handler.setLightFilter(objnum, pos, rad);
447 
448  Dirty_render_state = true;
449  Current_render_state.lights = Scene_light_handler.bufferLights();
450 }
451 
453 {
454  Current_render_state.light_factor = factor;
455 }
456 
457 void draw_list::set_clip_plane(const vec3d &position, const vec3d &normal)
458 {
459  clip_plane_state clip_normal;
460 
461  clip_normal.point = position;
462  clip_normal.normal = normal;
463 
464  Clip_planes.push_back(clip_normal);
465 
466  Current_render_state.clip_plane_handle = Clip_planes.size() - 1;
467 }
468 
470 {
471  Current_render_state.clip_plane_handle = -1;
472 }
473 
475 {
476  Current_render_state.thrust_scale = scale;
477 }
478 
480 {
481  // need to do a check to see if the top render state matches the current.
482  //if ( dirty_render_state ) {
483  Render_states.push_back(Current_render_state);
484  //}
485 
486  Dirty_render_state = false;
487 
488  queued_buffer_draw draw_data;
489 
490  draw_data.render_state_handle = Render_states.size() - 1;
491  draw_data.buffer = buffer;
492  draw_data.texi = texi;
493  draw_data.flags = tmap_flags;
494 
495  draw_data.clr = gr_screen.current_color;
496  draw_data.alpha = Current_alpha;
497  draw_data.blend_filter = Current_blend_filter;
498  draw_data.depth_mode = Current_depth_mode;
499 
500  if ( tmap_flags & TMAP_FLAG_BATCH_TRANSFORMS ) {
501  draw_data.transformation = transform();
502 
503  draw_data.scale.xyz.x = 1.0f;
504  draw_data.scale.xyz.y = 1.0f;
505  draw_data.scale.xyz.z = 1.0f;
506 
507  draw_data.transform_buffer_offset = TransformBufferHandler.get_buffer_offset();
508  } else {
509  draw_data.transformation = Current_transform;
510  draw_data.scale = Current_scale;
511  draw_data.transform_buffer_offset = -1;
512  }
513 
514  draw_data.texture_maps[TM_BASE_TYPE] = Current_textures[TM_BASE_TYPE];
515  draw_data.texture_maps[TM_GLOW_TYPE] = Current_textures[TM_GLOW_TYPE];
516  draw_data.texture_maps[TM_SPECULAR_TYPE] = Current_textures[TM_SPECULAR_TYPE];
517  draw_data.texture_maps[TM_NORMAL_TYPE] = Current_textures[TM_NORMAL_TYPE];
518  draw_data.texture_maps[TM_HEIGHT_TYPE] = Current_textures[TM_HEIGHT_TYPE];
519  draw_data.texture_maps[TM_MISC_TYPE] = Current_textures[TM_MISC_TYPE];
520 
521  draw_data.sdr_flags = determine_shader_flags(&Current_render_state, &draw_data, buffer, tmap_flags);
522 
523  Render_elements.push_back(draw_data);
524 
525  Render_keys.push_back(Render_elements.size() - 1);
526 }
527 
528 uint draw_list::determine_shader_flags(render_state *state, queued_buffer_draw *draw_info, vertex_buffer *buffer, int tmap_flags)
529 {
530  bool texture = (tmap_flags & TMAP_FLAG_TEXTURED) && (buffer->flags & VB_FLAG_UV1);
531  bool fog = false;
532  bool use_thrust_scale = false;
533 
534  if ( state->fog_mode == GR_FOGMODE_FOG ) {
535  fog = true;
536  }
537 
538  if ( draw_info->thrust_scale > 0.0f ) {
539  use_thrust_scale = true;
540  }
541 
543  state->lighting,
544  fog,
545  texture,
547  use_thrust_scale,
548  tmap_flags & TMAP_FLAG_BATCH_TRANSFORMS && draw_info->transform_buffer_offset >= 0 && buffer->flags & VB_FLAG_MODEL_ID,
549  state->using_team_color,
550  tmap_flags,
551  draw_info->texture_maps[TM_SPECULAR_TYPE],
552  draw_info->texture_maps[TM_GLOW_TYPE],
553  draw_info->texture_maps[TM_NORMAL_TYPE],
554  draw_info->texture_maps[TM_HEIGHT_TYPE],
555  ENVMAP,
556  draw_info->texture_maps[TM_MISC_TYPE]
557  );
558 }
559 
560 void draw_list::render_buffer(queued_buffer_draw &render_elements)
561 {
562  // get the render state for this draw call
563  int render_state_num = render_elements.render_state_handle;
564 
565  render_state &draw_state = Render_states[render_state_num];
566 
567  // set clip plane if necessary
568  if ( draw_state.clip_plane_handle >= 0 && draw_state.clip_plane_handle != Current_set_clip_plane ) {
569  if ( Current_set_clip_plane >= 0 ) {
571  }
572 
573  Current_set_clip_plane = draw_state.clip_plane_handle;
574 
575  clip_plane_state *clip_plane = &Clip_planes[Current_set_clip_plane];
576 
577  g3_start_user_clip_plane(&clip_plane->point, &clip_plane->normal);
578  } else if ( draw_state.clip_plane_handle < 0 && Current_set_clip_plane >= 0 ) {
579  // stop the clip plane if this draw call doesn't have clip plane and clip plane is set.
580  Current_set_clip_plane = -1;
582  }
583 
584  gr_set_animated_effect(draw_state.animated_effect, draw_state.animated_timer);
585 
586  if ( draw_state.using_team_color ) {
587  gr_set_team_color(&draw_state.tm_color);
588  } else {
589  gr_set_team_color(NULL);
590  }
591 
593 
594  gr_fog_set(draw_state.fog_mode, draw_state.r, draw_state.g, draw_state.b, draw_state.fog_near, draw_state.fog_far);
595 
596  gr_zbuffer_set(render_elements.depth_mode);
597 
598  gr_set_cull(draw_state.cull_mode);
599 
600  gr_set_fill_mode(draw_state.fill_mode);
601 
602  gr_center_alpha(draw_state.center_alpha);
603 
605 
606  gr_set_color_fast(&draw_state.clr);
607 
608  gr_set_light_factor(draw_state.light_factor);
609 
610  if ( draw_state.lighting ) {
611  Scene_light_handler.setLights(&draw_state.lights);
612  } else {
613  gr_set_lighting(false, false);
614 
615  Scene_light_handler.resetLightState();
616  }
617 
618  gr_set_buffer(draw_state.buffer_id);
619 
620  gr_zbias(draw_state.zbias);
621 
622  gr_set_thrust_scale(draw_state.thrust_scale);
623 
624  g3_start_instance_matrix(&render_elements.transformation.origin, &render_elements.transformation.basis);
625 
626  gr_push_scale_matrix(&render_elements.scale);
627 
628  gr_set_bitmap(render_elements.texture_maps[TM_BASE_TYPE], render_elements.blend_filter, GR_BITBLT_MODE_NORMAL, render_elements.alpha);
629 
630  GLOWMAP = render_elements.texture_maps[TM_GLOW_TYPE];
631  SPECMAP = render_elements.texture_maps[TM_SPECULAR_TYPE];
632  NORMMAP = render_elements.texture_maps[TM_NORMAL_TYPE];
633  HEIGHTMAP = render_elements.texture_maps[TM_HEIGHT_TYPE];
634  MISCMAP = render_elements.texture_maps[TM_MISC_TYPE];
635 
636  gr_render_buffer(0, render_elements.buffer, render_elements.texi, render_elements.flags);
637 
638  GLOWMAP = -1;
639  SPECMAP = -1;
640  NORMMAP = -1;
641  HEIGHTMAP = -1;
642  MISCMAP = -1;
643 
645 
646  g3_done_instance(true);
647 }
648 
650 {
651  matrix basis_world;
652 
653  // get the world basis of our current local space.
654  vm_matrix_x_matrix(&basis_world, &Object_matrix, &Current_transform.basis);
655 
656  vec3d eye_pos_local;
657  vm_vec_sub(&eye_pos_local, &Eye_position, &Current_transform.origin);
658 
659  vec3d return_val;
660  vm_vec_rotate(&return_val, &eye_pos_local, &basis_world);
661 
662  return return_val;
663 }
664 
666 {
667  Current_transform = transform();
668  Transform_stack.clear();
669 }
670 
672 {
673  matrix basis;
674  vec3d origin;
675 
676  if ( orient == NULL ) {
677  basis = vmd_identity_matrix;
678  } else {
679  basis = *orient;
680  }
681 
682  if ( pos == NULL ) {
683  origin = vmd_zero_vector;
684  } else {
685  origin = *pos;
686  }
687 
688  if ( Transform_stack.size() == 0 ) {
689  Current_transform.basis = basis;
690  Current_transform.origin = origin;
691 
692  Transform_stack.push_back(Current_transform);
693 
694  return;
695  }
696 
697  vec3d tempv;
698  transform newTransform = Current_transform;
699 
700  vm_vec_unrotate(&tempv, &origin, &Current_transform.basis);
701  vm_vec_add2(&newTransform.origin, &tempv);
702 
703  vm_matrix_x_matrix(&newTransform.basis, &Current_transform.basis, &basis);
704 
705  Current_transform = newTransform;
706  Transform_stack.push_back(Current_transform);
707 }
708 
710 {
711  Assert( Transform_stack.size() > 0 );
712 
713  Transform_stack.pop_back();
714 
715  if ( Transform_stack.size() > 0 ) {
716  Current_transform = Transform_stack.back();
717  } else {
718  Current_transform = transform();
719  }
720 }
721 
723 {
724  if ( scale == NULL ) {
725  Current_scale.xyz.x = 1.0f;
726  Current_scale.xyz.y = 1.0f;
727  Current_scale.xyz.z = 1.0f;
728  return;
729  }
730 
731  Current_scale = *scale;
732 }
733 
734 void draw_list::set_buffer(int buffer)
735 {
736 // if ( !dirty_render_state && current_render_state.buffer_id != buffer) {
737 // dirty_render_state = true;
738 // }
739 
740  Current_render_state.buffer_id = buffer;
741 }
742 
744 {
745 // if ( !dirty_render_state && ( current_render_state.alpha != alpha && current_render_state.blend_filter != filter ) ) {
746 // dirty_render_state = true;
747 // }
748 
749 // current_blend_filter = GR_ALPHABLEND_NONE;
750 // current_alpha = 1.0f;
751 
752  Current_blend_filter = filter;
753  Current_alpha = alpha;
754 }
755 
756 void draw_list::set_texture(int texture_type, int texture_handle)
757 {
758  Assert(texture_type > -1);
759  Assert(texture_type < TM_NUM_TYPES);
760 
761  Current_textures[texture_type] = texture_handle;
762 }
763 
765 {
766  Current_render_state.cull_mode = mode;
767 }
768 
770 {
771  Current_render_state.zbias = bias;
772 }
773 
774 void draw_list::set_lighting(bool lighting)
775 {
776  Current_render_state.lighting = lighting;
777 }
778 
780 {
781  Current_render_state.using_team_color = true;
782  Current_render_state.tm_color = clr;
783 }
784 
786 {
787  Current_render_state.using_team_color = false;
788 }
789 
790 void draw_list::set_color(const color &clr)
791 {
792  Current_render_state.clr = clr;
793 }
794 
796 {
797  Current_render_state.animated_timer = time;
798 }
799 
801 {
802  Current_render_state.animated_effect = effect;
803 }
804 
806 {
807  Current_render_state.texture_addressing = addressing;
808 }
809 
810 void draw_list::set_fog(int fog_mode, int r, int g, int b, float fog_near, float fog_far)
811 {
812  Current_render_state.fog_mode = fog_mode;
813  Current_render_state.r = r;
814  Current_render_state.g = g;
815  Current_render_state.b = b;
816  Current_render_state.fog_near = fog_near;
817  Current_render_state.fog_far = fog_far;
818 }
819 
821 {
822  Current_render_state.fill_mode = mode;
823 }
824 
825 void draw_list::set_center_alpha(int center_alpha)
826 {
827  Current_render_state.center_alpha = center_alpha;
828 }
829 
831 {
832  reset();
833 
834  for ( int i = 0; i < Num_lights; ++i ) {
835  if ( Lights[i].type == LT_DIRECTIONAL || !Deferred_lighting ) {
836  Scene_light_handler.addLight(&Lights[i]);
837  }
838  }
839 
840  TransformBufferHandler.reset();
841 }
842 
843 void draw_list::init_render(bool sort)
844 {
845  if ( sort ) {
846  sort_draws();
847  }
848 
849  TransformBufferHandler.submit_buffer_data();
850 }
851 
852 void draw_list::render_all(int depth_mode)
853 {
854  Scene_light_handler.resetLightState();
855 
856  for ( size_t i = 0; i < Render_keys.size(); ++i ) {
857  int render_index = Render_keys[i];
858 
859  if ( depth_mode == -1 || Render_elements[render_index].depth_mode == depth_mode ) {
860  render_buffer(Render_elements[render_index]);
861  }
862  }
863 
864  if ( Current_set_clip_plane >= 0 ) {
866  }
867 
868  gr_alpha_mask_set(0, 1.0f);
869 }
870 
871 void draw_list::render_arc(arc_effect &arc)
872 {
874 
875  interp_render_arc(&arc.v1, &arc.v2, &arc.primary, &arc.secondary, arc.width);
876 
877  g3_done_instance(true);
878 }
879 
881 {
883 
884  for ( size_t i = 0; i < Arcs.size(); ++i ) {
885  render_arc(Arcs[i]);
886  }
887 
888  gr_zbuffer_set(mode);
889 }
890 
891 void draw_list::add_insignia(polymodel *pm, int detail_level, int bitmap_num)
892 {
893  insignia_draw_data new_insignia;
894 
895  new_insignia.transformation = Current_transform;
896  new_insignia.pm = pm;
897  new_insignia.detail_level = detail_level;
898  new_insignia.bitmap_num = bitmap_num;
899 
900  new_insignia.clip_plane = Current_render_state.clip_plane_handle;
901 
902  Insignias.push_back(new_insignia);
903 }
904 
905 void draw_list::render_insignia(insignia_draw_data &insignia_info)
906 {
907  if ( insignia_info.clip_plane >= 0 ) {
908  clip_plane_state &plane_data = Clip_planes[insignia_info.clip_plane];
909 
910  vec3d tmp;
911  vm_vec_sub(&tmp, &insignia_info.transformation.origin, &plane_data.point);
912  vm_vec_normalize(&tmp);
913 
914  if ( vm_vec_dot(&tmp, &plane_data.normal) < 0.0f) {
915  return;
916  }
917  }
918 
919  g3_start_instance_matrix(&insignia_info.transformation.origin, &insignia_info.transformation.basis);
920 
921  model_render_insignias(insignia_info.pm, insignia_info.detail_level, insignia_info.bitmap_num);
922 
923  g3_done_instance(true);
924 }
925 
927 {
929  gr_zbias(1);
930 
931  for ( size_t i = 0; i < Insignias.size(); ++i ) {
932  render_insignia(Insignias[i]);
933  }
934 
935  gr_zbias(0);
936  gr_zbuffer_set(mode);
937 }
938 
939 void draw_list::add_outline(vertex* vert_array, int n_verts, color *clr)
940 {
941  outline_draw draw_info;
942 
943  draw_info.vert_array = vert_array;
944  draw_info.n_verts = n_verts;
945  draw_info.clr = *clr;
946  draw_info.transformation = Current_transform;
947 
948  Outlines.push_back(draw_info);
949 }
950 
952 {
953  gr_clear_states();
955 
956  for ( size_t i = 0; i < Outlines.size(); ++i ) {
957  render_outline(Outlines[i]);
958  }
959 
960  gr_zbuffer_set(mode);
961 }
962 
963 void draw_list::render_outline(outline_draw &outline_info)
964 {
965  g3_start_instance_matrix(&outline_info.transformation.origin, &outline_info.transformation.basis);
966 
967  gr_set_color_fast(&outline_info.clr);
968 
969  gr_render(outline_info.n_verts, outline_info.vert_array, TMAP_HTL_3D_UNLIT | TMAP_FLAG_LINES);
970 
971  g3_done_instance(true);
972 }
973 
974 bool draw_list::sort_draw_pair(const int a, const int b)
975 {
976  queued_buffer_draw *draw_call_a = &Target->Render_elements[a];
977  queued_buffer_draw *draw_call_b = &Target->Render_elements[b];
978 
979  render_state *render_state_a = &Target->Render_states[draw_call_a->render_state_handle];
980  render_state *render_state_b = &Target->Render_states[draw_call_b->render_state_handle];
981 
982  if ( draw_call_a->depth_mode != draw_call_b->depth_mode ) {
983  return draw_call_a->depth_mode > draw_call_b->depth_mode;
984  }
985 
986  if ( render_state_a->clip_plane_handle != render_state_b->clip_plane_handle ) {
987  return render_state_a->clip_plane_handle < render_state_b->clip_plane_handle;
988  }
989 
990  if ( draw_call_a->blend_filter != draw_call_b->blend_filter ) {
991  return draw_call_a->blend_filter < draw_call_b->blend_filter;
992  }
993 
994  if ( draw_call_a->sdr_flags != draw_call_b->sdr_flags ) {
995  return draw_call_a->sdr_flags < draw_call_b->sdr_flags;
996  }
997 
998  if ( render_state_a->buffer_id != render_state_b->buffer_id) {
999  return render_state_a->buffer_id < render_state_b->buffer_id;
1000  }
1001 
1002  if ( draw_call_a->texture_maps[TM_BASE_TYPE] != draw_call_b->texture_maps[TM_BASE_TYPE] ) {
1003  return draw_call_a->texture_maps[TM_BASE_TYPE] < draw_call_b->texture_maps[TM_BASE_TYPE];
1004  }
1005 
1006  if ( draw_call_a->texture_maps[TM_SPECULAR_TYPE] != draw_call_b->texture_maps[TM_SPECULAR_TYPE] ) {
1007  return draw_call_a->texture_maps[TM_SPECULAR_TYPE] < draw_call_b->texture_maps[TM_SPECULAR_TYPE];
1008  }
1009 
1010  if ( draw_call_a->texture_maps[TM_GLOW_TYPE] != draw_call_b->texture_maps[TM_GLOW_TYPE] ) {
1011  return draw_call_a->texture_maps[TM_GLOW_TYPE] < draw_call_b->texture_maps[TM_GLOW_TYPE];
1012  }
1013 
1014  if ( draw_call_a->texture_maps[TM_NORMAL_TYPE] != draw_call_b->texture_maps[TM_NORMAL_TYPE] ) {
1015  return draw_call_a->texture_maps[TM_NORMAL_TYPE] < draw_call_b->texture_maps[TM_NORMAL_TYPE];
1016  }
1017 
1018  if ( draw_call_a->texture_maps[TM_HEIGHT_TYPE] != draw_call_b->texture_maps[TM_HEIGHT_TYPE] ) {
1019  return draw_call_a->texture_maps[TM_HEIGHT_TYPE] < draw_call_b->texture_maps[TM_HEIGHT_TYPE];
1020  }
1021 
1022  if ( draw_call_a->texture_maps[TM_MISC_TYPE] != draw_call_b->texture_maps[TM_MISC_TYPE] ) {
1023  return draw_call_a->texture_maps[TM_MISC_TYPE] < draw_call_b->texture_maps[TM_MISC_TYPE];
1024  }
1025 
1026  return render_state_a->lights.index_start < render_state_b->lights.index_start;
1027 }
1028 
1030 {
1031  int i;
1032  float width = 0.9f;
1033  color primary, secondary;
1034 
1035  const int AR = 64;
1036  const int AG = 64;
1037  const int AB = 5;
1038  const int AR2 = 128;
1039  const int AG2 = 128;
1040  const int AB2 = 10;
1041 
1042  Assert( sm->num_arcs > 0 );
1043 
1044  if ( interp->get_model_flags() & MR_SHOW_OUTLINE_PRESET ) {
1045  return;
1046  }
1047 
1048  extern int Interp_lightning;
1049  if ( !Interp_lightning ) {
1050  return;
1051  }
1052 
1053  // try and scale the size a bit so that it looks equally well on smaller vessels
1054  if ( pm->rad < 500.0f ) {
1055  width *= (pm->rad * 0.01f);
1056 
1057  if ( width < 0.2f ) {
1058  width = 0.2f;
1059  }
1060  }
1061 
1062  for ( i = 0; i < sm->num_arcs; i++ ) {
1063  // pick a color based upon arc type
1064  switch ( sm->arc_type[i] ) {
1065  // "normal", FreeSpace 1 style arcs
1066  case MARC_TYPE_NORMAL:
1067  if ( (rand()>>4) & 1 ) {
1068  gr_init_color(&primary, 64, 64, 255);
1069  } else {
1070  gr_init_color(&primary, 128, 128, 255);
1071  }
1072 
1073  gr_init_color(&secondary, 200, 200, 255);
1074  break;
1075 
1076  // "EMP" style arcs
1077  case MARC_TYPE_EMP:
1078  if ( (rand()>>4) & 1 ) {
1079  gr_init_color(&primary, AR, AG, AB);
1080  } else {
1081  gr_init_color(&primary, AR2, AG2, AB2);
1082  }
1083 
1084  gr_init_color(&secondary, 255, 255, 10);
1085  break;
1086 
1087  default:
1088  Int3();
1089  }
1090 
1091  // render the actual arc segment
1092  scene->add_arc(&sm->arc_pts[i][0], &sm->arc_pts[i][1], &primary, &secondary, width);
1093  }
1094 }
1095 
1096 float model_render_determine_depth(int obj_num, int model_num, matrix* orient, vec3d* pos, int detail_level_locked)
1097 {
1098  vec3d closest_pos;
1099  float depth = model_find_closest_point( &closest_pos, model_num, -1, orient, pos, &Eye_position );
1100 
1101  if ( detail_level_locked < 0 ) {
1102  switch (Detail.detail_distance) {
1103  case 0: // lowest
1105  break;
1106  case 1: // lower than normal
1108  break;
1109  case 2: // default
1111  break;
1112  case 3: // above normal
1114  break;
1115  case 4: // even more normal
1117  break;
1118  }
1119 
1120  // nebula ?
1122  depth *= neb2_get_lod_scale(obj_num);
1123  }
1124 
1125  }
1126 
1127  return depth;
1128 }
1129 
1130 int model_render_determine_detail(float depth, int obj_num, int model_num, matrix* orient, vec3d* pos, int flags, int detail_level_locked)
1131 {
1132  int tmp_detail_level = Game_detail_level;
1133 
1134  polymodel *pm = model_get(model_num);
1135 
1137 
1138  int i;
1139 
1140  if ( pm->n_detail_levels > 1 ) {
1141  if ( detail_level_locked >= 0 ) {
1142  i = detail_level_locked+1;
1143  } else {
1144 
1145 #if MAX_DETAIL_LEVEL != 4
1146 #error Code in modelrender.cpp assumes MAX_DETAIL_LEVEL == 4
1147 #endif
1148  for ( i = 0; i < pm->n_detail_levels; i++ ) {
1149  if ( depth <= pm->detail_depth[i] ) {
1150  break;
1151  }
1152  }
1153 
1154  // If no valid detail depths specified, use highest.
1155  if ( (i > 1) && (pm->detail_depth[i-1] < 1.0f) ) {
1156  i = 1;
1157  }
1158  }
1159 
1160  int detail_level = i - 1 - tmp_detail_level;
1161 
1162  if ( detail_level < 0 ) {
1163  return 0;
1164  } else if ( detail_level >= pm->n_detail_levels ) {
1165  return pm->n_detail_levels - 1;
1166  }
1167 
1168  return detail_level;
1169  } else {
1170  return 0;
1171  }
1172 }
1173 
1174 void model_render_buffers(draw_list* scene, model_render_params* interp, vertex_buffer *buffer, polymodel *pm, int mn, int detail_level, uint tmap_flags)
1175 {
1176  if ( pm->vertex_buffer_id < 0 ) {
1177  return;
1178  }
1179 
1180  bsp_info *model = NULL;
1181  const uint model_flags = interp->get_model_flags();
1182  const int obj_num = interp->get_object_number();
1183 
1184  Assert(buffer != NULL);
1185  Assert(detail_level >= 0);
1186 
1187  if ( (mn >= 0) && (mn < pm->n_models) ) {
1188  model = &pm->submodel[mn];
1189  }
1190 
1191  bool render_as_thruster = (model != NULL) && model->is_thruster && (model_flags & MR_SHOW_THRUSTERS);
1192 
1193  vec3d scale;
1194 
1195  if ( render_as_thruster ) {
1196  scale.xyz.x = 1.0f;
1197  scale.xyz.y = 1.0f;
1198 
1199  if ( is_minimum_GLSL_version() ) {
1200  scale.xyz.z = 1.0f;
1201  scene->set_thrust_scale(interp->get_thruster_info().length.xyz.z);
1202  } else {
1203  scale.xyz.z = interp->get_thruster_info().length.xyz.z;
1204  scene->set_thrust_scale();
1205  }
1206  } else {
1207  scale = interp->get_warp_scale();
1208  scene->set_thrust_scale();
1209  }
1210 
1211  scene->set_scale(&scale);
1212 
1213  if ( tmap_flags & TMAP_FLAG_BATCH_TRANSFORMS && (mn >= 0) && (mn < pm->n_models) ) {
1214  scene->add_submodel_to_batch(mn);
1215  return;
1216  }
1217 
1218  fix base_frametime = model_render_determine_base_frametime(obj_num, model_flags);
1219 
1220  texture_info tex_replace[TM_NUM_TYPES];
1221 
1222  int no_texturing = model_flags & MR_NO_TEXTURING;
1223 
1224  int forced_texture = -2;
1225  float forced_alpha = 1.0f;
1226  int forced_blend_filter = GR_ALPHABLEND_NONE;
1227 
1228  if ( interp->get_forced_bitmap() >= 0 ) {
1229  forced_texture = interp->get_forced_bitmap();
1230  } else if ( interp->get_warp_bitmap() >= 0 ) {
1231  forced_texture = interp->get_warp_bitmap();
1232  forced_alpha = interp->get_warp_alpha();
1233  forced_blend_filter = GR_ALPHABLEND_FILTER;
1234  } else if ( render_as_thruster ) {
1235  if ( ( interp->get_thruster_info().primary_bitmap >= 0 ) && ( interp->get_thruster_info().length.xyz.z > 0.0f ) ) {
1236  forced_texture = interp->get_thruster_info().primary_bitmap;
1237  } else {
1238  forced_texture = -1;
1239  }
1240 
1241  forced_alpha = 1.2f;
1242  forced_blend_filter = GR_ALPHABLEND_FILTER;
1243  } else if ( model_flags & MR_ALL_XPARENT ) {
1244  forced_alpha = interp->get_alpha();
1245  forced_blend_filter = GR_ALPHABLEND_FILTER;
1246  }
1247 
1248  int texture_maps[TM_NUM_TYPES] = {-1, -1, -1, -1, -1, -1};
1249  size_t buffer_size = buffer->tex_buf.size();
1250  const int *replacement_textures = interp->get_replacement_textures();
1251 
1252  for ( size_t i = 0; i < buffer_size; i++ ) {
1253  int tmap_num = buffer->tex_buf[i].texture;
1254  texture_map *tmap = &pm->maps[tmap_num];
1255  int rt_begin_index = tmap_num*TM_NUM_TYPES;
1256  float alpha = 1.0f;
1257  int blend_filter = GR_ALPHABLEND_NONE;
1258 
1259  texture_maps[TM_BASE_TYPE] = -1;
1260  texture_maps[TM_GLOW_TYPE] = -1;
1261  texture_maps[TM_SPECULAR_TYPE] = -1;
1262  texture_maps[TM_NORMAL_TYPE] = -1;
1263  texture_maps[TM_HEIGHT_TYPE] = -1;
1264  texture_maps[TM_MISC_TYPE] = -1;
1265 
1266  if (forced_texture != -2) {
1267  texture_maps[TM_BASE_TYPE] = forced_texture;
1268  alpha = forced_alpha;
1269  } else if ( !no_texturing ) {
1270  // pick the texture, animating it if necessary
1271  if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_BASE_TYPE] == REPLACE_WITH_INVISIBLE) ) {
1272  // invisible textures aren't rendered, but we still have to skip assigning the underlying model texture
1273  texture_maps[TM_BASE_TYPE] = -1;
1274  } else if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_BASE_TYPE] >= 0) ) {
1275  // an underlying texture is replaced with a real new texture
1276  tex_replace[TM_BASE_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_BASE_TYPE]);
1277  texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tex_replace[TM_BASE_TYPE], base_frametime);
1278  } else {
1279  // we just use the underlying texture
1280  texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tmap->textures[TM_BASE_TYPE], base_frametime);
1281  }
1282 
1283  if ( texture_maps[TM_BASE_TYPE] < 0 ) {
1284  continue;
1285  }
1286 
1287  // doing glow maps?
1288  if ( !(model_flags & MR_NO_GLOWMAPS) ) {
1289  texture_info *tglow = &tmap->textures[TM_GLOW_TYPE];
1290 
1291  if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_GLOW_TYPE] >= 0) ) {
1292  tex_replace[TM_GLOW_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_GLOW_TYPE]);
1293  texture_maps[TM_GLOW_TYPE] = model_interp_get_texture(&tex_replace[TM_GLOW_TYPE], base_frametime);
1294  } else if (tglow->GetTexture() >= 0) {
1295  // shockwaves are special, their current frame has to come out of the shockwave code to get the timing correct
1296  if ( (obj_num >= 0) && (Objects[obj_num].type == OBJ_SHOCKWAVE) && (tglow->GetNumFrames() > 1) ) {
1297  texture_maps[TM_GLOW_TYPE] = tglow->GetTexture() + shockwave_get_framenum(Objects[obj_num].instance, tglow->GetNumFrames());
1298  } else {
1299  texture_maps[TM_GLOW_TYPE] = model_interp_get_texture(tglow, base_frametime);
1300  }
1301  }
1302  }
1303 
1304  if ( (Detail.lighting > 2) && (detail_level < 2) ) {
1305  // likewise, etc.
1306  texture_info *spec_map = &tmap->textures[TM_SPECULAR_TYPE];
1307  texture_info *norm_map = &tmap->textures[TM_NORMAL_TYPE];
1308  texture_info *height_map = &tmap->textures[TM_HEIGHT_TYPE];
1309  texture_info *misc_map = &tmap->textures[TM_MISC_TYPE];
1310 
1311  if (replacement_textures != NULL) {
1312  if (replacement_textures[rt_begin_index + TM_SPECULAR_TYPE] >= 0) {
1313  tex_replace[TM_SPECULAR_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_SPECULAR_TYPE]);
1314  spec_map = &tex_replace[TM_SPECULAR_TYPE];
1315  }
1316 
1317  if (replacement_textures[rt_begin_index + TM_NORMAL_TYPE] >= 0) {
1318  tex_replace[TM_NORMAL_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_NORMAL_TYPE]);
1319  norm_map = &tex_replace[TM_NORMAL_TYPE];
1320  }
1321 
1322  if (replacement_textures[rt_begin_index + TM_HEIGHT_TYPE] >= 0) {
1323  tex_replace[TM_HEIGHT_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_HEIGHT_TYPE]);
1324  height_map = &tex_replace[TM_HEIGHT_TYPE];
1325  }
1326 
1327  if (replacement_textures[rt_begin_index + TM_MISC_TYPE] >= 0) {
1328  tex_replace[TM_MISC_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_MISC_TYPE]);
1329  misc_map = &tex_replace[TM_MISC_TYPE];
1330  }
1331  }
1332 
1333  texture_maps[TM_SPECULAR_TYPE] = model_interp_get_texture(spec_map, base_frametime);
1334  texture_maps[TM_NORMAL_TYPE] = model_interp_get_texture(norm_map, base_frametime);
1335  texture_maps[TM_HEIGHT_TYPE] = model_interp_get_texture(height_map, base_frametime);
1336  texture_maps[TM_MISC_TYPE] = model_interp_get_texture(misc_map, base_frametime);
1337  }
1338  } else {
1339  alpha = forced_alpha;
1340 
1341  //Check for invisible or transparent textures so they don't show up in the shadow maps - Valathil
1342  if ( Rendering_to_shadow_map ) {
1343  if ( (replacement_textures != NULL) && (replacement_textures[rt_begin_index + TM_BASE_TYPE] >= 0) ) {
1344  tex_replace[TM_BASE_TYPE] = texture_info(replacement_textures[rt_begin_index + TM_BASE_TYPE]);
1345  texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tex_replace[TM_BASE_TYPE], base_frametime);
1346  } else {
1347  texture_maps[TM_BASE_TYPE] = model_interp_get_texture(&tmap->textures[TM_BASE_TYPE], base_frametime);
1348  }
1349 
1350  if ( texture_maps[TM_BASE_TYPE] <= 0 ) {
1351  continue;
1352  }
1353  }
1354  }
1355 
1356  if ( (texture_maps[TM_BASE_TYPE] == -1) && !no_texturing ) {
1357  continue;
1358  }
1359 
1360  uint alpha_flag = 0;
1361 
1362  // trying to get transparent textures-Bobboau
1363  if (tmap->is_transparent) {
1364  // for special shockwave/warp map usage
1365  alpha = (interp->get_warp_alpha() != -1.0f) ? interp->get_warp_alpha() : 0.8f;
1366  blend_filter = GR_ALPHABLEND_FILTER;
1367  } else if ( buffer->flags & VB_FLAG_TRANS ) {
1368  blend_filter = GR_ALPHABLEND_FILTER;
1369  }
1370 
1371  if (forced_blend_filter != GR_ALPHABLEND_NONE) {
1372  blend_filter = forced_blend_filter;
1373  }
1374 
1375  if (blend_filter != GR_ALPHABLEND_NONE ) {
1376  scene->set_depth_mode(GR_ZBUFF_READ);
1377  alpha_flag |= TMAP_FLAG_ALPHA;
1378  } else {
1379  if ( (model_flags & MR_NO_ZBUFFER) || (model_flags & MR_ALL_XPARENT) ) {
1380  scene->set_depth_mode(GR_ZBUFF_NONE);
1381  alpha_flag |= TMAP_FLAG_ALPHA;
1382  } else {
1383  scene->set_depth_mode(GR_ZBUFF_FULL);
1384  }
1385  }
1386 
1387  scene->set_blend_filter(blend_filter, alpha);
1388 
1389  scene->set_texture(TM_BASE_TYPE, texture_maps[TM_BASE_TYPE]);
1390  scene->set_texture(TM_GLOW_TYPE, texture_maps[TM_GLOW_TYPE]);
1391  scene->set_texture(TM_SPECULAR_TYPE, texture_maps[TM_SPECULAR_TYPE]);
1392  scene->set_texture(TM_NORMAL_TYPE, texture_maps[TM_NORMAL_TYPE]);
1393  scene->set_texture(TM_HEIGHT_TYPE, texture_maps[TM_HEIGHT_TYPE]);
1394  scene->set_texture(TM_MISC_TYPE, texture_maps[TM_MISC_TYPE]);
1395 
1396  scene->add_buffer_draw(buffer, i, tmap_flags | alpha_flag, interp);
1397  }
1398 }
1399 
1400 void model_render_children_buffers(draw_list* scene, model_render_params* interp, polymodel* pm, polymodel_instance *pmi, int mn, int detail_level, uint tmap_flags, bool trans_buffer)
1401 {
1402  int i;
1403 
1404  if ( (mn < 0) || (mn >= pm->n_models) ) {
1405  Int3();
1406  return;
1407  }
1408 
1409  bsp_info *model = &pm->submodel[mn];
1410  submodel_instance *smi = NULL;
1411 
1412  if ( pmi != NULL ) {
1413  smi = &pmi->submodel[mn];
1414  }
1415 
1416  if ( smi != NULL ) {
1417  if ( smi->blown_off ) {
1418  return;
1419  }
1420  } else if ( model->blown_off ) {
1421  return;
1422  }
1423 
1424  const uint model_flags = interp->get_model_flags();
1425 
1426  if (model->is_thruster) {
1427  if ( !( model_flags & MR_SHOW_THRUSTERS ) ) {
1428  return;
1429  }
1430 
1431  scene->set_lighting(false);
1432  }
1433 
1434  vec3d view_pos = scene->get_view_position();
1435 
1436  if ( !model_render_check_detail_box(&view_pos, pm, mn, model_flags) ) {
1437  return;
1438  }
1439 
1440  // Get submodel rotation data and use submodel orientation matrix
1441  // to put together a matrix describing the final orientation of
1442  // the submodel relative to its parent
1443  angles ang = model->angs;
1444 
1445  if ( smi != NULL ) {
1446  ang = smi->angs;
1447  }
1448 
1449  // Add barrel rotation if needed
1450  if ( model->gun_rotation ) {
1451  if ( pm->gun_submodel_rotation > PI2 ) {
1452  pm->gun_submodel_rotation -= PI2;
1453  } else if ( pm->gun_submodel_rotation < 0.0f ) {
1454  pm->gun_submodel_rotation += PI2;
1455  }
1456 
1457  ang.b += pm->gun_submodel_rotation;
1458  }
1459 
1460  // Compute final submodel orientation by using the orientation matrix
1461  // and the rotation angles.
1462  // By using this kind of computation, the rotational angles can always
1463  // be computed relative to the submodel itself, instead of relative
1464  // to the parent
1465  matrix rotation_matrix = model->orientation;
1466  vm_rotate_matrix_by_angles(&rotation_matrix, &ang);
1467 
1468  matrix inv_orientation;
1469  vm_copy_transpose(&inv_orientation, &model->orientation);
1470 
1471  matrix submodel_matrix;
1472  vm_matrix_x_matrix(&submodel_matrix, &rotation_matrix, &inv_orientation);
1473 
1474  scene->push_transform(&model->offset, &submodel_matrix);
1475 
1476  if ( (model_flags & MR_SHOW_OUTLINE || model_flags & MR_SHOW_OUTLINE_HTL || model_flags & MR_SHOW_OUTLINE_PRESET) &&
1477  pm->submodel[mn].outline_buffer != NULL ) {
1478  color outline_color = interp->get_color();
1479  scene->add_outline(pm->submodel[mn].outline_buffer, pm->submodel[mn].n_verts_outline, &outline_color);
1480  } else {
1481  if ( trans_buffer && pm->submodel[mn].trans_buffer.flags & VB_FLAG_TRANS ) {
1482  model_render_buffers(scene, interp, &pm->submodel[mn].trans_buffer, pm, mn, detail_level, tmap_flags);
1483  } else {
1484  model_render_buffers(scene, interp, &pm->submodel[mn].buffer, pm, mn, detail_level, tmap_flags);
1485  }
1486  }
1487 
1488  if ( model->num_arcs ) {
1489  model_render_add_lightning( scene, interp, pm, &pm->submodel[mn] );
1490  }
1491 
1492  i = model->first_child;
1493 
1494  while ( i >= 0 ) {
1495  if ( !pm->submodel[i].is_thruster ) {
1496  model_render_children_buffers( scene, interp, pm, pmi, i, detail_level, tmap_flags, trans_buffer );
1497  }
1498 
1499  i = pm->submodel[i].next_sibling;
1500  }
1501 
1502  if ( model->is_thruster ) {
1503  scene->set_lighting(true);
1504  }
1505 
1506  scene->pop_transform();
1507 }
1508 
1510 {
1511  if ( flags & MR_IS_ASTEROID ) {
1512  // Dim it based on distance
1513  float depth = vm_vec_dist_quick( pos, &Eye_position );
1514  if ( depth > interp->get_depth_scale() ) {
1515  float temp_light = interp->get_depth_scale()/depth;
1516 
1517  if ( temp_light > 1.0f ) {
1518  return 1.0f;
1519  }
1520 
1521  return temp_light;
1522  }
1523  }
1524 
1525  return 1.0f;
1526 }
1527 
1529 {
1530  float box_scale = 1.2f;
1531 
1532  // scale the render box settings based on the "Model Detail" slider
1533  switch ( Detail.detail_distance ) {
1534  case 0: // 1st dot is 20%
1535  box_scale = 0.2f;
1536  break;
1537  case 1: // 2nd dot is 50%
1538  box_scale = 0.5f;
1539  break;
1540  case 2: // 3rd dot is 80%
1541  box_scale = 0.8f;
1542  break;
1543  case 3: // 4th dot is 100% (this is the default setting for "High" and "Very High" settings)
1544  box_scale = 1.0f;
1545  break;
1546  case 4: // 5th dot (max) is 120%
1547  default:
1548  box_scale = 1.2f;
1549  break;
1550  }
1551 
1552  return box_scale;
1553 }
1554 
1556 {
1557  // Goober5000
1558  fix base_frametime = 0;
1559 
1560  if ( objnum >= 0 ) {
1561  object *objp = &Objects[objnum];
1562 
1563  if ( objp->type == OBJ_SHIP ) {
1564  base_frametime = Ships[objp->instance].base_texture_anim_frametime;
1565  }
1566  } else if ( flags & MR_SKYBOX ) {
1567  base_frametime = Skybox_timestamp;
1568  }
1569 
1570  return base_frametime;
1571 }
1572 
1573 bool model_render_determine_autocenter(vec3d *auto_back, polymodel *pm, int detail_level, uint flags)
1574 {
1575  if ( flags & MR_AUTOCENTER ) {
1576  // standard autocenter using data in model
1577  if ( pm->flags & PM_FLAG_AUTOCEN ) {
1578  *auto_back = pm->autocenter;
1579  vm_vec_scale(auto_back, -1.0f);
1580  return true;
1581  } else if ( flags & MR_IS_MISSILE ) {
1582  // fake autocenter if we are a missile and don't already have autocen info
1583  auto_back->xyz.x = -( (pm->submodel[pm->detail[detail_level]].max.xyz.x + pm->submodel[pm->detail[detail_level]].min.xyz.x) / 2.0f );
1584  auto_back->xyz.y = -( (pm->submodel[pm->detail[detail_level]].max.xyz.y + pm->submodel[pm->detail[detail_level]].min.xyz.y) / 2.0f );
1585  auto_back->xyz.z = -( (pm->submodel[pm->detail[detail_level]].max.xyz.z + pm->submodel[pm->detail[detail_level]].min.xyz.z) / 2.0f );
1586  return true;
1587  }
1588  }
1589 
1590  return false;
1591 }
1592 
1594 {
1595  Assert(pm != NULL);
1596 
1597  bsp_info *model = &pm->submodel[submodel_num];
1598 
1599  float box_scale = model_render_determine_box_scale();
1600 
1601  if ( !( flags & MR_FULL_DETAIL ) && model->use_render_box ) {
1602  vec3d box_min, box_max, offset;
1603 
1604  if (model->use_render_box_offset) {
1605  offset = model->render_box_offset;
1606  } else {
1607  model_find_submodel_offset(&offset, pm->id, submodel_num);
1608  }
1609 
1610  vm_vec_copy_scale(&box_min, &model->render_box_min, box_scale);
1611  vm_vec_copy_scale(&box_max, &model->render_box_max, box_scale);
1612 
1613  if ( (-model->use_render_box + in_box(&box_min, &box_max, &offset, view_pos)) ) {
1614  return false;
1615  }
1616  }
1617 
1618  if ( !(flags & MR_FULL_DETAIL) && model->use_render_sphere ) {
1619  float sphere_radius = model->render_sphere_radius * box_scale;
1620 
1621  // TODO: doesn't consider submodel rotations yet -zookeeper
1622  vec3d offset;
1623 
1624  if (model->use_render_sphere_offset) {
1625  offset = model->render_sphere_offset;
1626  } else {
1627  model_find_submodel_offset(&offset, pm->id, submodel_num);
1628  }
1629 
1630  if ( (-model->use_render_sphere + in_sphere(&offset, sphere_radius, view_pos)) ) {
1631  return false;
1632  }
1633  }
1634 
1635  return true;
1636 }
1637 
1639 {
1640  draw_list model_list;
1641 
1642  model_list.init();
1643 
1644  submodel_render_queue(render_info, &model_list, model_num, submodel_num, orient, pos);
1645 
1646  model_list.render_all();
1647 
1648  gr_zbias(0);
1650  gr_set_cull(0);
1652 
1653  gr_clear_states();
1654  gr_set_buffer(-1);
1655 
1657  gr_set_lighting(false, false);
1658 }
1659 
1661 {
1662  polymodel * pm;
1663 
1664  //MONITOR_INC( NumModelsRend, 1 );
1665 
1666  if ( !( Game_detail_flags & DETAIL_FLAG_MODELS ) ) return;
1667 
1668  if ( render_info->is_clip_plane_set() ) {
1669  scene->set_clip_plane(render_info->get_clip_plane_pos(), render_info->get_clip_plane_normal());
1670  } else {
1671  scene->set_clip_plane();
1672  }
1673 
1674  if ( render_info->is_team_color_set() ) {
1675  scene->set_team_color(render_info->get_team_color());
1676  } else {
1677  scene->set_team_color();
1678  }
1679 
1680  uint flags = render_info->get_model_flags();
1681  int objnum = render_info->get_object_number();
1682 
1683  pm = model_get(model_num);
1684 
1685  // Set the flags we will pass to the tmapper
1686  uint tmap_flags = TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB;
1687 
1688  // if we're in nebula mode
1690  tmap_flags |= TMAP_FLAG_PIXEL_FOG;
1691  }
1692 
1693  if ( !( flags & MR_NO_TEXTURING ) ) {
1694  tmap_flags |= TMAP_FLAG_TEXTURED;
1695 
1696  if ( ( pm->flags & PM_FLAG_ALLOW_TILING ) && tiling )
1697  tmap_flags |= TMAP_FLAG_TILED;
1698 
1699  if ( !( flags & MR_NO_CORRECT ) ) {
1700  tmap_flags |= TMAP_FLAG_CORRECT;
1701  }
1702  }
1703 
1704  if ( render_info->get_animated_effect_num() >= 0 ) {
1705  tmap_flags |= TMAP_ANIMATED_SHADER;
1706  scene->set_animated_effect(render_info->get_animated_effect_num());
1707  scene->set_animated_timer(render_info->get_animated_effect_timer());
1708  }
1709 
1710  bool is_outlines_only_htl = !Cmdline_nohtl && (flags & MR_NO_POLYS) && (flags & MR_SHOW_OUTLINE_HTL);
1711 
1712  //set to true since D3d and OGL need the api matrices set
1713  scene->push_transform(pos, orient);
1714 
1715 
1716  vec3d auto_back = ZERO_VECTOR;
1717  bool set_autocen = model_render_determine_autocenter(&auto_back, pm, render_info->get_detail_level_lock(), flags);
1718 
1719  if ( set_autocen ) {
1720  scene->push_transform(&auto_back, NULL);
1721  }
1722 
1723  if (is_outlines_only_htl) {
1725 
1726  color outline_color = render_info->get_color();
1727  gr_set_color_fast( &outline_color );
1728 
1729  tmap_flags &= ~TMAP_FLAG_RGB;
1730  } else {
1732  }
1733 
1734  scene->set_light_factor(1.0f);
1735 
1736  if ( !( flags & MR_NO_LIGHTING ) ) {
1737  scene->set_light_filter(-1, pos, pm->submodel[submodel_num].rad);
1738  scene->set_lighting(true);
1739  } else {
1740  scene->set_lighting(false);
1741  }
1742 
1743  // fixes disappearing HUD in OGL - taylor
1744  scene->set_cull_mode(1);
1745 
1746  // RT - Put this here to fog debris
1747  if( tmap_flags & TMAP_FLAG_PIXEL_FOG ) {
1748  float fog_near, fog_far;
1749  object *obj = NULL;
1750 
1751  if (objnum >= 0)
1752  obj = &Objects[objnum];
1753 
1754  neb2_get_adjusted_fog_values(&fog_near, &fog_far, obj);
1755  unsigned char r, g, b;
1756  neb2_get_fog_color(&r, &g, &b);
1757 
1758  scene->set_fog(GR_FOGMODE_FOG, r, g, b, fog_near, fog_far);
1759  } else {
1760  scene->set_fog(GR_FOGMODE_NONE, 0, 0, 0);
1761  }
1762 
1764  scene->set_zbias(-1024);
1765  } else {
1766  scene->set_zbias(0);
1767  }
1768 
1769  scene->set_buffer(pm->vertex_buffer_id);
1770 
1771  vec3d view_pos = scene->get_view_position();
1772 
1773  if ( model_render_check_detail_box(&view_pos, pm, submodel_num, flags) ) {
1774  model_render_buffers(scene, render_info, &pm->submodel[submodel_num].buffer, pm, submodel_num, 0, tmap_flags);
1775 
1776  if ( pm->flags & PM_FLAG_TRANS_BUFFER && pm->submodel[submodel_num].trans_buffer.flags & VB_FLAG_TRANS ) {
1777  model_render_buffers(scene, render_info, &pm->submodel[submodel_num].trans_buffer, pm, submodel_num, 0, tmap_flags);
1778  }
1779  }
1780 
1781  if ( pm->submodel[submodel_num].num_arcs ) {
1782  model_render_add_lightning( scene, render_info, pm, &pm->submodel[submodel_num] );
1783  }
1784 
1785  if ( set_autocen ) {
1786  scene->pop_transform();
1787  }
1788 
1789  scene->pop_transform();
1790 }
1791 
1792 void model_render_glowpoint(int point_num, vec3d *pos, matrix *orient, glow_point_bank *bank, glow_point_bank_override *gpo, polymodel *pm, ship* shipp, bool use_depth_buffer)
1793 {
1794  glow_point *gpt = &bank->points[point_num];
1795  vec3d loc_offset = gpt->pnt;
1796  vec3d loc_norm = gpt->norm;
1797  vec3d world_pnt;
1798  vec3d world_norm;
1799  vec3d tempv;
1800  vec3d submodel_static_offset; // The associated submodel's static offset in the ship's frame of reference
1801  bool submodel_rotation = false;
1802 
1803  if ( bank->submodel_parent > 0 && pm->submodel[bank->submodel_parent].can_move && (gameseq_get_state_idx(GS_STATE_LAB) == -1) && shipp != NULL ) {
1804  model_find_submodel_offset(&submodel_static_offset, Ship_info[shipp->ship_info_index].model_num, bank->submodel_parent);
1805 
1806  submodel_rotation = true;
1807  }
1808 
1809  if ( submodel_rotation ) {
1810  vm_vec_sub(&loc_offset, &gpt->pnt, &submodel_static_offset);
1811 
1812  tempv = loc_offset;
1813  find_submodel_instance_point_normal(&loc_offset, &loc_norm, shipp->model_instance_num, bank->submodel_parent, &tempv, &loc_norm);
1814  }
1815 
1816  vm_vec_unrotate(&world_pnt, &loc_offset, orient);
1817  vm_vec_add2(&world_pnt, pos);
1818 
1819  vm_vec_unrotate(&world_norm, &loc_norm, orient);
1820 
1821  if ( shipp != NULL ) {
1822  if ( (shipp->flags & (SF_ARRIVING) ) && (shipp->warpin_effect) && Ship_info[shipp->ship_info_index].warpin_type != WT_HYPERSPACE) {
1823  vec3d warp_pnt, tmp;
1824  matrix warp_orient;
1825 
1826  shipp->warpin_effect->getWarpPosition(&warp_pnt);
1827  shipp->warpin_effect->getWarpOrientation(&warp_orient);
1828  vm_vec_sub( &tmp, &world_pnt, &warp_pnt );
1829 
1830  if ( vm_vec_dot( &tmp, &warp_orient.vec.fvec ) < 0.0f ) {
1831  return;
1832  }
1833  }
1834 
1835  if ( (shipp->flags & (SF_DEPART_WARP) ) && (shipp->warpout_effect) && Ship_info[shipp->ship_info_index].warpout_type != WT_HYPERSPACE) {
1836  vec3d warp_pnt, tmp;
1837  matrix warp_orient;
1838 
1839  shipp->warpout_effect->getWarpPosition(&warp_pnt);
1840  shipp->warpout_effect->getWarpOrientation(&warp_orient);
1841  vm_vec_sub( &tmp, &world_pnt, &warp_pnt );
1842 
1843  if ( vm_vec_dot( &tmp, &warp_orient.vec.fvec ) > 0.0f ) {
1844  return;
1845  }
1846  }
1847  }
1848 
1849  switch ((gpo && gpo->type_override)?gpo->type:bank->type)
1850  {
1851  case 0:
1852  {
1853  float d,pulse = 1.0f;
1854 
1855  if ( IS_VEC_NULL(&world_norm) ) {
1856  d = 1.0f; //if given a nul vector then always show it
1857  } else {
1858  vm_vec_sub(&tempv,&View_position,&world_pnt);
1859  vm_vec_normalize(&tempv);
1860 
1861  d = vm_vec_dot(&tempv,&world_norm);
1862  d -= 0.25;
1863  }
1864 
1865  float w = gpt->radius;
1866  if (d > 0.0f) {
1867  vertex p;
1868 
1869  d *= 3.0f;
1870 
1871  if (d > 1.0f)
1872  d = 1.0f;
1873 
1874 
1875  // fade them in the nebula as well
1877  //vec3d npnt;
1878  //vm_vec_add(&npnt, &loc_offset, pos);
1879 
1880  d *= (1.0f - neb2_get_fog_intensity(&world_pnt));
1881  w *= 1.5; //make it bigger in a nebula
1882  }
1883 
1884  if (!Cmdline_nohtl) {
1885  g3_transfer_vertex(&p, &world_pnt);
1886  } else {
1887  g3_rotate_vertex(&p, &world_pnt);
1888  }
1889 
1890  p.r = p.g = p.b = p.a = (ubyte)(255.0f * MAX(d,0.0f));
1891 
1892  if((gpo && gpo->glow_bitmap_override)?(gpo->glow_bitmap > -1):(bank->glow_bitmap > -1)) {
1894 
1895  if (use_depth_buffer)
1896  gpflags |= TMAP_FLAG_SOFT_QUAD;
1897 
1899  (gpo && gpo->glow_bitmap_override)?gpo->glow_bitmap:bank->glow_bitmap,
1900  gpflags,
1901  &p,
1902  0,
1903  (w * 0.5f),
1904  d * pulse,
1905  w
1906  );
1907  }
1908  } //d>0.0f
1909  if ( gpo && gpo->pulse_type ) {
1910  int period;
1911 
1912  if(gpo->pulse_period_override) {
1913  period = gpo->pulse_period;
1914  } else {
1915  if(gpo->on_time_override) {
1916  period = 2 * gpo->on_time;
1917  } else {
1918  period = 2 * bank->on_time;
1919  }
1920  }
1921 
1922  int x = 0;
1923 
1924  if ( (gpo && gpo->off_time_override) ? gpo->off_time : bank->off_time ) {
1925  x = (timestamp() - ((gpo && gpo->disp_time_override)?gpo->disp_time:bank->disp_time)) % ( ((gpo && gpo->on_time_override)?gpo->on_time:bank->on_time) + ((gpo && gpo->off_time_override)?gpo->off_time:bank->off_time) ) - ((gpo && gpo->off_time_override)?gpo->off_time:bank->off_time);
1926  } else {
1927  x = (timestamp() - ((gpo && gpo->disp_time_override)?gpo->disp_time:bank->disp_time)) % gpo->pulse_period;
1928  }
1929 
1930  switch ( gpo->pulse_type ) {
1931 
1932  case PULSE_SIN:
1933  pulse = gpo->pulse_bias + gpo->pulse_amplitude * pow(sin( PI2 / period * x),gpo->pulse_exponent);
1934  break;
1935 
1936  case PULSE_COS:
1937  pulse = gpo->pulse_bias + gpo->pulse_amplitude * pow(cos( PI2 / period * x),gpo->pulse_exponent);
1938  break;
1939 
1940  case PULSE_SHIFTTRI:
1941  x += period / 4;
1942  if((gpo && gpo->off_time_override)?gpo->off_time:bank->off_time) {
1943  x %= ( ((gpo && gpo->on_time_override)?gpo->on_time:bank->on_time) + ((gpo && gpo->off_time_override)?gpo->off_time:bank->off_time) );
1944  } else {
1945  x %= gpo->pulse_period;
1946  }
1947 
1948  case PULSE_TRI:
1949  float inv;
1950  if( x > period / 2) {
1951  inv = -1;
1952  } else {
1953  inv = 1;
1954  }
1955  if( x > period / 4) {
1956  pulse = gpo->pulse_bias + gpo->pulse_amplitude * inv * pow( 1.0f - ((x - period / 4.0f) * 4 / period) ,gpo->pulse_exponent);
1957  } else {
1958  pulse = gpo->pulse_bias + gpo->pulse_amplitude * inv * pow( (x * 4.0f / period) ,gpo->pulse_exponent);
1959  }
1960  break;
1961  }
1962  }
1963 
1964  if ( Deferred_lighting && gpo && gpo->is_lightsource ) {
1965  if ( gpo->lightcone ) {
1966  vec3d cone_dir_rot;
1967  vec3d cone_dir_model;
1968  vec3d cone_dir_world;
1969  vec3d cone_dir_screen;
1970  vec3d unused;
1971 
1972  if ( gpo->rotating ) {
1973  vm_rot_point_around_line(&cone_dir_rot, &gpo->cone_direction, PI * timestamp() * 0.000033333f * gpo->rotation_speed, &vmd_zero_vector, &gpo->rotation_axis);
1974  } else {
1975  cone_dir_rot = gpo->cone_direction;
1976  }
1977 
1978  find_submodel_instance_point_normal(&unused, &cone_dir_model, shipp->model_instance_num, bank->submodel_parent, &unused, &cone_dir_rot);
1979  vm_vec_unrotate(&cone_dir_world, &cone_dir_model, orient);
1980  vm_vec_rotate(&cone_dir_screen, &cone_dir_world, &Eye_matrix);
1981  cone_dir_screen.xyz.z = -cone_dir_screen.xyz.z;
1982  light_add_cone(&world_pnt, &cone_dir_screen, gpo->cone_angle, gpo->cone_inner_angle, gpo->dualcone, 1.0f, w * gpo->radius_multi, 1, pulse * gpo->light_color.xyz.x + (1.0f-pulse) * gpo->light_mix_color.xyz.x, pulse * gpo->light_color.xyz.y + (1.0f-pulse) * gpo->light_mix_color.xyz.y, pulse * gpo->light_color.xyz.z + (1.0f-pulse) * gpo->light_mix_color.xyz.z, -1);
1983  } else {
1984  light_add_point(&world_pnt, 1.0f, w * gpo->radius_multi, 1, pulse * gpo->light_color.xyz.x + (1.0f-pulse) * gpo->light_mix_color.xyz.x, pulse * gpo->light_color.xyz.y + (1.0f-pulse) * gpo->light_mix_color.xyz.y, pulse * gpo->light_color.xyz.z + (1.0f-pulse) * gpo->light_mix_color.xyz.z, -1);
1985  }
1986  }
1987  break;
1988  }
1989 
1990  case 1:
1991  {
1992  vertex verts[4];
1993  vec3d fvec, top1, bottom1, top2, bottom2, start, end;
1994 
1995  vm_vec_add2(&loc_norm, &loc_offset);
1996 
1997  vm_vec_rotate(&start, &loc_offset, orient);
1998  vm_vec_rotate(&end, &loc_norm, orient);
1999  vm_vec_sub(&fvec, &end, &start);
2000 
2001  vm_vec_normalize(&fvec);
2002 
2003  moldel_calc_facing_pts(&top1, &bottom1, &fvec, &loc_offset, gpt->radius, 1.0f, &View_position);
2004  moldel_calc_facing_pts(&top2, &bottom2, &fvec, &loc_norm, gpt->radius, 1.0f, &View_position);
2005 
2006  int idx = 0;
2007 
2008  if ( Cmdline_nohtl ) {
2009  g3_rotate_vertex(&verts[0], &bottom1);
2010  g3_rotate_vertex(&verts[1], &bottom2);
2011  g3_rotate_vertex(&verts[2], &top2);
2012  g3_rotate_vertex(&verts[3], &top1);
2013 
2014  for ( idx = 0; idx < 4; idx++ ) {
2015  g3_project_vertex(&verts[idx]);
2016  }
2017  } else {
2018  g3_transfer_vertex(&verts[0], &bottom1);
2019  g3_transfer_vertex(&verts[1], &bottom2);
2020  g3_transfer_vertex(&verts[2], &top2);
2021  g3_transfer_vertex(&verts[3], &top1);
2022  }
2023 
2024  verts[0].texture_position.u = 0.0f;
2025  verts[0].texture_position.v = 0.0f;
2026 
2027  verts[1].texture_position.u = 1.0f;
2028  verts[1].texture_position.v = 0.0f;
2029 
2030  verts[2].texture_position.u = 1.0f;
2031  verts[2].texture_position.v = 1.0f;
2032 
2033  verts[3].texture_position.u = 0.0f;
2034  verts[3].texture_position.v = 1.0f;
2035 
2036  vm_vec_sub(&tempv,&View_position,&loc_offset);
2037  vm_vec_normalize(&tempv);
2038 
2041  } else {
2043  }
2044 
2045  break;
2046  }
2047  }
2048 }
2049 
2051 {
2052  int time = timestamp();
2053  glow_point_bank_override *gpo = NULL;
2054  bool override_all = false;
2056  ship_info *sip = NULL;
2057  ship *shipp = NULL;
2058 
2059  if ( Glowpoint_override ) {
2060  return;
2061  }
2062 
2063  if ( objnum > -1 ) {
2064  object *objp = &Objects[objnum];
2065 
2066  if ( objp != NULL && objp->type == OBJ_SHIP ) {
2067  shipp = &Ships[Objects[objnum].instance];
2068  sip = &Ship_info[shipp->ship_info_index];
2069  gpoi = sip->glowpoint_bank_override_map.find(-1);
2070 
2071  if (gpoi != sip->glowpoint_bank_override_map.end()) {
2072  override_all = true;
2074  }
2075  }
2076  }
2077 
2078  for ( int i = 0; i < pm->n_glow_point_banks; i++ ) { //glow point blink code -Bobboau
2079  glow_point_bank *bank = &pm->glow_point_banks[i];
2080 
2081  if ( !override_all && sip ) {
2082  gpoi = sip->glowpoint_bank_override_map.find(i);
2083 
2084  if ( gpoi != sip->glowpoint_bank_override_map.end() ) {
2086  } else {
2087  gpo = NULL;
2088  }
2089  }
2090 
2091  if ( bank->glow_timestamp == 0 ) {
2092  bank->glow_timestamp=time;
2093  }
2094 
2095  if ( ( gpo && gpo->off_time_override ) ? gpo->off_time : bank->off_time ) {
2096  if ( bank->is_on ) {
2097  if( ((gpo && gpo->on_time_override) ? gpo->on_time : bank->on_time) > ((time - ((gpo && gpo->disp_time_override) ? gpo->disp_time : bank->disp_time)) % (((gpo && gpo->on_time_override) ? gpo->on_time : bank->on_time) + ((gpo && gpo->off_time_override) ? gpo->off_time : bank->off_time))) ){
2098  bank->glow_timestamp = time;
2099  bank->is_on = 0;
2100  }
2101  } else {
2102  if( ((gpo && gpo->off_time_override)?gpo->off_time:bank->off_time) < ((time - ((gpo && gpo->disp_time_override)?gpo->disp_time:bank->disp_time)) % (((gpo && gpo->on_time_override)?gpo->on_time:bank->on_time) + ((gpo && gpo->off_time_override)?gpo->off_time:bank->off_time))) ){
2103  bank->glow_timestamp = time;
2104  bank->is_on = 1;
2105  }
2106  }
2107  }
2108  }
2109 }
2110 
2111 void model_render_glow_points(polymodel *pm, ship *shipp, matrix *orient, vec3d *pos, bool use_depth_buffer = true)
2112 {
2113  if ( Rendering_to_shadow_map ) {
2114  return;
2115  }
2116 
2117  int i, j;
2118 
2119  int cull = gr_set_cull(0);
2120 
2121  glow_point_bank_override *gpo = NULL;
2122  bool override_all = false;
2124  ship_info *sip = NULL;
2125 
2126  if ( shipp ) {
2127  sip = &Ship_info[shipp->ship_info_index];
2128  gpoi = sip->glowpoint_bank_override_map.find(-1);
2129 
2130  if(gpoi != sip->glowpoint_bank_override_map.end()) {
2131  override_all = true;
2133  }
2134  }
2135 
2136  for (i = 0; i < pm->n_glow_point_banks; i++ ) {
2137  glow_point_bank *bank = &pm->glow_point_banks[i];
2138 
2139  if(!override_all && sip) {
2140  gpoi = sip->glowpoint_bank_override_map.find(i);
2141  if(gpoi != sip->glowpoint_bank_override_map.end()) {
2143  } else {
2144  gpo = NULL;
2145  }
2146  }
2147 
2148  //Only continue if there actually is a glowpoint bitmap available
2149  if (bank->glow_bitmap == -1)
2150  continue;
2151 
2152  if (pm->submodel[bank->submodel_parent].blown_off)
2153  continue;
2154 
2155  if ((gpo && gpo->off_time_override && !gpo->off_time)?gpo->is_on:bank->is_on) {
2156  if ( (shipp != NULL) && !(shipp->glow_point_bank_active[i]) )
2157  continue;
2158 
2159  for (j = 0; j < bank->num_points; j++) {
2160  Assert( bank->points != NULL );
2161  int flick;
2162 
2163  if (pm->submodel[pm->detail[0]].num_arcs) {
2164  flick = static_rand( timestamp() % 20 ) % (pm->submodel[pm->detail[0]].num_arcs + j); //the more damage, the more arcs, the more likely the lights will fail
2165  } else {
2166  flick = 1;
2167  }
2168 
2169  if (flick == 1) {
2170  model_render_glowpoint(j, pos, orient, bank, gpo, pm, shipp, use_depth_buffer);
2171  } // flick
2172  } // for slot
2173  } // bank is on
2174  } // for bank
2175 
2176  gr_set_cull(cull);
2177 }
2178 
2180 {
2181  int i, j;
2182  int n_q = 0;
2183  size_t k;
2184  vec3d norm, norm2, fvec, pnt, npnt;
2185  thruster_bank *bank = NULL;
2186  vertex p;
2187  bool do_render = false;
2188 
2189  if ( Rendering_to_shadow_map ) {
2190  return;
2191  }
2192 
2193  if ( pm == NULL ) {
2194  Int3();
2195  return;
2196  }
2197 
2198  if ( !(interp->get_model_flags() & MR_SHOW_THRUSTERS) ) {
2199  return;
2200  }
2201 
2202  // get an initial count to figure out how man geo batchers we need allocated
2203  for (i = 0; i < pm->n_thrusters; i++ ) {
2204  bank = &pm->thrusters[i];
2205  n_q += bank->num_points;
2206  }
2207 
2208  if (n_q <= 0) {
2209  return;
2210  }
2211 
2212  const mst_info& thruster_info = interp->get_thruster_info();
2213 
2214  // primary_thruster_batcher
2215  if (thruster_info.primary_glow_bitmap >= 0) {
2216  do_render = true;
2217  }
2218 
2219  // secondary_thruster_batcher
2220  if (thruster_info.secondary_glow_bitmap >= 0) {
2221  do_render = true;
2222  }
2223 
2224  // tertiary_thruster_batcher
2225  if (thruster_info.tertiary_glow_bitmap >= 0) {
2226  do_render = true;
2227  }
2228 
2229  if (do_render == false) {
2230  return;
2231  }
2232 
2233  // this is used for the secondary thruster glows
2234  // it only needs to be calculated once so I'm doing it here -Bobboau
2235  norm.xyz.z = -1.0f;
2236  norm.xyz.x = 1.0f;
2237  norm.xyz.y = -1.0f;
2238  norm.xyz.x *= thruster_info.rotvel.xyz.y/2;
2239  norm.xyz.y *= thruster_info.rotvel.xyz.x/2;
2240  vm_vec_normalize(&norm);
2241 
2242  for (i = 0; i < pm->n_thrusters; i++ ) {
2243  vec3d submodel_static_offset; // The associated submodel's static offset in the ship's frame of reference
2244  bool submodel_rotation = false;
2245 
2246  bank = &pm->thrusters[i];
2247 
2248  // don't draw this thruster if the engine is destroyed or just not on
2249  if ( !model_should_render_engine_glow(objnum, bank->obj_num) )
2250  continue;
2251 
2252  // If bank is attached to a submodel, prepare to account for rotations
2253  //
2254  // TODO: This won't work in the ship lab, because the lab code doesn't
2255  // set the the necessary submodel instance info needed here. The second
2256  // condition is thus a hack to disable the feature while in the lab, and
2257  // can be removed if the lab is re-structured accordingly. -zookeeper
2258  if ( bank->submodel_num > -1 && pm->submodel[bank->submodel_num].can_move && (gameseq_get_state_idx(GS_STATE_LAB) == -1) ) {
2259  model_find_submodel_offset(&submodel_static_offset, Ship_info[shipp->ship_info_index].model_num, bank->submodel_num);
2260 
2261  submodel_rotation = true;
2262  }
2263 
2264  for (j = 0; j < bank->num_points; j++) {
2265  Assert( bank->points != NULL );
2266 
2267  float d, D;
2268  vec3d tempv;
2269  glow_point *gpt = &bank->points[j];
2270  vec3d loc_offset = gpt->pnt;
2271  vec3d loc_norm = gpt->norm;
2272  vec3d world_pnt;
2273  vec3d world_norm;
2274 
2275  if ( submodel_rotation ) {
2276  vm_vec_sub(&loc_offset, &gpt->pnt, &submodel_static_offset);
2277 
2278  tempv = loc_offset;
2279  find_submodel_instance_point_normal(&loc_offset, &loc_norm, shipp->model_instance_num, bank->submodel_num, &tempv, &loc_norm);
2280  }
2281 
2282  vm_vec_unrotate(&world_pnt, &loc_offset, orient);
2283  vm_vec_add2(&world_pnt, pos);
2284 
2285  if (shipp) {
2286  // if ship is warping out, check position of the engine glow to the warp plane
2287  if ( (shipp->flags & (SF_ARRIVING) ) && (shipp->warpin_effect) && Ship_info[shipp->ship_info_index].warpin_type != WT_HYPERSPACE) {
2288  vec3d warp_pnt, tmp;
2289  matrix warp_orient;
2290 
2291  shipp->warpin_effect->getWarpPosition(&warp_pnt);
2292  shipp->warpin_effect->getWarpOrientation(&warp_orient);
2293  vm_vec_sub( &tmp, &world_pnt, &warp_pnt );
2294 
2295  if ( vm_vec_dot( &tmp, &warp_orient.vec.fvec ) < 0.0f ) {
2296  break;
2297  }
2298  }
2299 
2300  if ( (shipp->flags & (SF_DEPART_WARP) ) && (shipp->warpout_effect) && Ship_info[shipp->ship_info_index].warpout_type != WT_HYPERSPACE) {
2301  vec3d warp_pnt, tmp;
2302  matrix warp_orient;
2303 
2304  shipp->warpout_effect->getWarpPosition(&warp_pnt);
2305  shipp->warpout_effect->getWarpOrientation(&warp_orient);
2306  vm_vec_sub( &tmp, &world_pnt, &warp_pnt );
2307 
2308  if ( vm_vec_dot( &tmp, &warp_orient.vec.fvec ) > 0.0f ) {
2309  break;
2310  }
2311  }
2312  }
2313 
2314  vm_vec_sub(&tempv, &View_position, &world_pnt);
2315  vm_vec_normalize(&tempv);
2316  vm_vec_unrotate(&world_norm, &loc_norm, orient);
2317  D = d = vm_vec_dot(&tempv, &world_norm);
2318 
2319  // ADAM: Min throttle draws rad*MIN_SCALE, max uses max.
2320 #define NOISE_SCALE 0.5f
2321 #define MIN_SCALE 3.4f
2322 #define MAX_SCALE 4.7f
2323 
2324  float magnitude;
2325  vec3d scale_vec = { { { 1.0f, 0.0f, 0.0f } } };
2326 
2327  // normalize banks, in case of incredibly big normals
2328  if ( !IS_VEC_NULL_SQ_SAFE(&world_norm) )
2329  vm_vec_copy_normalize(&scale_vec, &world_norm);
2330 
2331  // adjust for thrust
2332  (scale_vec.xyz.x *= thruster_info.length.xyz.x) -= 0.1f;
2333  (scale_vec.xyz.y *= thruster_info.length.xyz.y) -= 0.1f;
2334  (scale_vec.xyz.z *= thruster_info.length.xyz.z) -= 0.1f;
2335 
2336  // get magnitude, which we will use as the scaling reference
2337  magnitude = vm_vec_normalize(&scale_vec);
2338 
2339  // get absolute value
2340  if (magnitude < 0.0f)
2341  magnitude *= -1.0f;
2342 
2343  float scale = magnitude * (MAX_SCALE - MIN_SCALE) + MIN_SCALE;
2344 
2345  if (d > 0.0f){
2346  // Make glow bitmap fade in/out quicker from sides.
2347  d *= 3.0f;
2348 
2349  if (d > 1.0f)
2350  d = 1.0f;
2351  }
2352 
2353  float fog_int = 1.0f;
2354 
2355  // fade them in the nebula as well
2357  vm_vec_unrotate(&npnt, &gpt->pnt, orient);
2358  vm_vec_add2(&npnt, pos);
2359 
2360  fog_int = (1.0f - (neb2_get_fog_intensity(&npnt)));
2361 
2362  if (fog_int > 1.0f)
2363  fog_int = 1.0f;
2364 
2365  d *= fog_int;
2366 
2367  if (d > 1.0f)
2368  d = 1.0f;
2369  }
2370 
2371  float w = gpt->radius * (scale + thruster_info.glow_noise * NOISE_SCALE);
2372 
2373  // these lines are used by the tertiary glows, thus we will need to project this all of the time
2374  if (Cmdline_nohtl) {
2375  g3_rotate_vertex( &p, &world_pnt );
2376  } else {
2377  g3_transfer_vertex( &p, &world_pnt );
2378  }
2379 
2380  // start primary thruster glows
2381  if ( (thruster_info.primary_glow_bitmap >= 0) && (d > 0.0f) ) {
2382  p.r = p.g = p.b = p.a = (ubyte)(255.0f * d);
2384  thruster_info.primary_glow_bitmap,
2386  &p,
2387  0,
2388  (w * 0.5f * thruster_info.glow_rad_factor),
2389  1.0f,
2390  (w * 0.325f)
2391  );
2392  }
2393 
2394  // start tertiary thruster glows
2395  if (thruster_info.tertiary_glow_bitmap >= 0) {
2396  p.screen.xyw.w -= w;
2397  p.r = p.g = p.b = p.a = (ubyte)(255.0f * fog_int);
2399  thruster_info.tertiary_glow_bitmap,
2401  &p,
2402  (magnitude * 4),
2403  (w * 0.6f * thruster_info.tertiary_glow_rad_factor),
2404  1.0f,
2405  (-(D > 0) ? D : -D)
2406  );
2407  }
2408 
2409  // begin secondary glows
2410  if (thruster_info.secondary_glow_bitmap >= 0) {
2411  pnt = world_pnt;
2412  scale = magnitude * (MAX_SCALE - (MIN_SCALE / 2)) + (MIN_SCALE / 2);
2413  vm_vec_unrotate(&world_norm, &norm, orient);
2414  d = vm_vec_dot(&tempv, &world_norm);
2415  d += 0.75f;
2416  d *= 3.0f;
2417 
2418  if (d > 1.0f)
2419  d = 1.0f;
2420 
2421  if (d > 0.0f) {
2422  vm_vec_add(&norm2, &world_norm, &pnt);
2423  vm_vec_sub(&fvec, &norm2, &pnt);
2424  vm_vec_normalize(&fvec);
2425 
2426  float wVal = gpt->radius * scale * 2;
2427 
2428  vm_vec_scale_add(&norm2, &pnt, &fvec, wVal * 2 * thruster_info.glow_length_factor);
2429 
2431  vm_vec_add(&npnt, &pnt, pos);
2432  d *= fog_int;
2433  }
2434 
2435  batch_add_beam(thruster_info.secondary_glow_bitmap,
2437  &pnt, &norm2, wVal*thruster_info.secondary_glow_rad_factor*0.5f, d
2438  );
2439  if (Scene_framebuffer_in_frame && thruster_info.draw_distortion) {
2440  vm_vec_scale_add(&norm2, &pnt, &fvec, wVal * 2 * thruster_info.distortion_length_factor);
2441  int dist_bitmap;
2442  if (thruster_info.distortion_bitmap > 0) {
2443  dist_bitmap = thruster_info.distortion_bitmap;
2444  }
2445  else {
2446  dist_bitmap = thruster_info.secondary_glow_bitmap;
2447  }
2448  float mag = vm_vec_mag(&gpt->pnt);
2449  mag -= (float)((int)mag);//Valathil - Get a fairly random but constant number to offset the distortion texture
2450  distortion_add_beam(dist_bitmap,
2452  &pnt, &norm2, wVal*thruster_info.distortion_rad_factor*0.5f, 1.0f, mag
2453  );
2454  }
2455  }
2456  }
2457 
2458  // begin particles
2459  if (shipp) {
2460  ship_info *sip = &Ship_info[shipp->ship_info_index];
2461  particle_emitter pe;
2462  thruster_particles *tp;
2463  size_t num_particles = 0;
2464 
2465  if (thruster_info.use_ab)
2466  num_particles = sip->afterburner_thruster_particles.size();
2467  else
2468  num_particles = sip->normal_thruster_particles.size();
2469 
2470  for (k = 0; k < num_particles; k++) {
2471  if (thruster_info.use_ab)
2472  tp = &sip->afterburner_thruster_particles[k];
2473  else
2474  tp = &sip->normal_thruster_particles[k];
2475 
2477 
2478  vm_vec_unrotate(&npnt, &gpt->pnt, orient);
2479  vm_vec_add2(&npnt, pos);
2480 
2481  // Where the particles emit from
2482  pe.pos = npnt;
2483  // Initial velocity of all the particles
2484  pe.vel = Objects[shipp->objnum].phys_info.desired_vel;
2485  pe.min_vel = v * 0.75f;
2486  pe.max_vel = v * 1.25f;
2487  // What normal the particle emit around
2488  pe.normal = orient->vec.fvec;
2489  vm_vec_negate(&pe.normal);
2490 
2491  // Lowest number of particles to create
2492  pe.num_low = tp->n_low;
2493  // Highest number of particles to create
2494  pe.num_high = tp->n_high;
2495  pe.min_rad = gpt->radius * tp->min_rad;
2496  pe.max_rad = gpt->radius * tp->max_rad;
2497  // How close they stick to that normal 0=on normal, 1=180, 2=360 degree
2498  pe.normal_variance = tp->variance;
2499  pe.min_life = 0.0f;
2500  pe.max_life = 1.0f;
2501 
2503  }
2504  }
2505  }
2506  }
2507 }
2508 
2509 void model_render_debug_children(polymodel *pm, int mn, int detail_level, uint debug_flags)
2510 {
2511  int i;
2512 
2513  if ( (mn < 0) || (mn >= pm->n_models) ) {
2514  Int3();
2515  return;
2516  }
2517 
2518  bsp_info *model = &pm->submodel[mn];
2519 
2520  if ( model->blown_off ) {
2521  return;
2522  }
2523 
2524  // Get submodel rotation data and use submodel orientation matrix
2525  // to put together a matrix describing the final orientation of
2526  // the submodel relative to its parent
2527  angles ang = model->angs;
2528 
2529  // Add barrel rotation if needed
2530  if ( model->gun_rotation ) {
2531  if ( pm->gun_submodel_rotation > PI2 ) {
2532  pm->gun_submodel_rotation -= PI2;
2533  } else if ( pm->gun_submodel_rotation < 0.0f ) {
2534  pm->gun_submodel_rotation += PI2;
2535  }
2536 
2537  ang.b += pm->gun_submodel_rotation;
2538  }
2539 
2540  // Compute final submodel orientation by using the orientation matrix
2541  // and the rotation angles.
2542  // By using this kind of computation, the rotational angles can always
2543  // be computed relative to the submodel itself, instead of relative
2544  // to the parent
2545  matrix rotation_matrix = model->orientation;
2546  vm_rotate_matrix_by_angles(&rotation_matrix, &ang);
2547 
2548  matrix inv_orientation;
2549  vm_copy_transpose(&inv_orientation, &model->orientation);
2550 
2551  matrix submodel_matrix;
2552  vm_matrix_x_matrix(&submodel_matrix, &rotation_matrix, &inv_orientation);
2553 
2554  g3_start_instance_matrix(&model->offset, &submodel_matrix, true);
2555 
2556  if ( debug_flags & MR_DEBUG_PIVOTS ) {
2557  model_draw_debug_points( pm, &pm->submodel[mn], debug_flags );
2558  }
2559 
2560  i = model->first_child;
2561 
2562  while ( i >= 0 ) {
2563  model_render_debug_children( pm, i, detail_level, debug_flags );
2564 
2565  i = pm->submodel[i].next_sibling;
2566  }
2567 
2568  g3_done_instance(true);
2569 }
2570 
2571 void model_render_debug(int model_num, matrix *orient, vec3d * pos, uint flags, uint debug_flags, int objnum, int detail_level_locked )
2572 {
2573  polymodel *pm = model_get(model_num);
2574 
2575  g3_start_instance_matrix(pos, orient, true);
2576 
2577  if ( debug_flags & MR_DEBUG_RADIUS ) {
2578  if ( !( flags & MR_SHOW_OUTLINE_PRESET ) ) {
2579  gr_set_color(0,64,0);
2581  }
2582  }
2583  float depth = model_render_determine_depth(objnum, model_num, orient, pos, detail_level_locked);
2584  int detail_level = model_render_determine_detail(depth, objnum, model_num, orient, pos, flags, detail_level_locked);
2585 
2586  vec3d auto_back = ZERO_VECTOR;
2587  bool set_autocen = model_render_determine_autocenter(&auto_back, pm, detail_level, flags);
2588 
2589  if ( set_autocen ) {
2590  g3_start_instance_matrix(&auto_back, NULL, true);
2591  }
2592 
2593  uint save_gr_zbuffering_mode = gr_zbuffer_set(GR_ZBUFF_READ);
2594 
2595  int i = pm->submodel[pm->detail[detail_level]].first_child;
2596 
2597  while ( i >= 0 ) {
2598  model_render_debug_children( pm, i, detail_level, flags );
2599 
2600  i = pm->submodel[i].next_sibling;
2601  }
2602 
2603  if ( debug_flags & MR_DEBUG_PIVOTS ) {
2604  model_draw_debug_points( pm, NULL, flags );
2605  model_draw_debug_points( pm, &pm->submodel[pm->detail[detail_level]], flags );
2606 
2607  if ( pm->flags & PM_FLAG_AUTOCEN ) {
2608  gr_set_color(255, 255, 255);
2609  g3_draw_sphere_ez(&pm->autocenter, pm->rad / 4.5f);
2610  }
2611  }
2612 
2613  if ( debug_flags & MR_DEBUG_SHIELDS ) {
2614  model_render_shields(pm, flags);
2615  }
2616 
2617  if ( debug_flags & MR_DEBUG_PATHS ) {
2618  if ( Cmdline_nohtl ) model_draw_paths(model_num, flags);
2619  else model_draw_paths_htl(model_num, flags);
2620  }
2621 
2622  if ( debug_flags & MR_DEBUG_BAY_PATHS ) {
2623  if ( Cmdline_nohtl ) model_draw_bay_paths(model_num);
2624  else model_draw_bay_paths_htl(model_num);
2625  }
2626 
2627  if ( (flags & MR_AUTOCENTER) && (set_autocen) ) {
2628  g3_done_instance(true);
2629  }
2630 
2631  g3_done_instance(true);
2632 
2633  gr_zbuffer_set(save_gr_zbuffering_mode);
2634 }
2635 
2636 void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d * pos, int render, bool sort)
2637 {
2638  draw_list model_list;
2639 
2640  model_list.init();
2641 
2642  model_render_queue(render_info, &model_list, model_num, orient, pos);
2643 
2644  model_list.init_render(sort);
2645 
2646  switch ( render ) {
2647  case MODEL_RENDER_OPAQUE:
2648  model_list.render_all(GR_ZBUFF_FULL);
2649  break;
2650  case MODEL_RENDER_TRANS:
2651  model_list.render_all(GR_ZBUFF_READ);
2652  model_list.render_all(GR_ZBUFF_NONE);
2653  break;
2654  case MODEL_RENDER_ALL:
2655  model_list.render_all();
2656  break;
2657  }
2658 
2659  model_list.render_outlines();
2660  model_list.render_insignias();
2661  model_list.render_arcs();
2662 
2663  gr_zbias(0);
2664  gr_set_cull(0);
2667 
2668  gr_clear_states();
2669  gr_set_buffer(-1);
2670 
2672  gr_set_lighting(false, false);
2673 
2675 
2676  if ( render_info->get_debug_flags() ) {
2677  model_render_debug(model_num, orient, pos, render_info->get_model_flags(), render_info->get_debug_flags(), render_info->get_object_number(), render_info->get_detail_level_lock());
2678  }
2679 }
2680 
2682 {
2683  int i;
2684 
2685  const int objnum = interp->get_object_number();
2686  const int model_flags = interp->get_model_flags();
2687 
2688  polymodel *pm = model_get(model_num);
2689  polymodel_instance *pmi = NULL;
2690 
2691  float light_factor = model_render_determine_light_factor(interp, pos, model_flags);
2692 
2693  if ( light_factor < (1.0f/32.0f) ) {
2694  // If it is too far, exit
2695  return;
2696  }
2697 
2698  scene->set_light_factor(light_factor);
2699 
2700  if ( interp->is_clip_plane_set() ) {
2701  scene->set_clip_plane(interp->get_clip_plane_pos(), interp->get_clip_plane_normal());
2702  } else {
2703  scene->set_clip_plane();
2704  }
2705 
2706  if ( interp->is_team_color_set() ) {
2707  scene->set_team_color(interp->get_team_color());
2708  } else {
2709  scene->set_team_color();
2710  }
2711 
2712  if ( model_flags & MR_FORCE_CLAMP ) {
2714  } else {
2716  }
2717 
2718  model_render_set_glow_points(pm, objnum);
2719 
2720  if ( !(model_flags & MR_NO_LIGHTING) ) {
2721  scene->set_light_filter( objnum, pos, pm->rad );
2722  }
2723 
2724  ship *shipp = NULL;
2725  object *objp = NULL;
2726 
2727  if (objnum >= 0) {
2728  objp = &Objects[objnum];
2729 
2730  if (objp->type == OBJ_SHIP) {
2731  shipp = &Ships[objp->instance];
2732  pmi = model_get_instance(shipp->model_instance_num);
2733  }
2734  else if (pm->flags & PM_FLAG_HAS_INTRINSIC_ROTATE) {
2735  if (objp->type == OBJ_ASTEROID)
2737  else if (objp->type == OBJ_WEAPON)
2739  else
2740  Warning(LOCATION, "Unsupported object type %d for rendering intrinsic-rotate submodels!", objp->type);
2741  }
2742  }
2743 
2744  // is this a skybox with a rotating submodel?
2745  extern int Nmodel_num, Nmodel_instance_num;
2746  if (model_num == Nmodel_num && Nmodel_instance_num >= 0)
2747  pmi = model_get_instance(Nmodel_instance_num);
2748 
2749  // Set the flags we will pass to the tmapper
2750  uint tmap_flags = TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB;
2751 
2752  // if we're in nebula mode, fog everything except for the warp holes and other non-fogged models
2754  tmap_flags |= TMAP_FLAG_PIXEL_FOG;
2755  }
2756 
2757  if ( !(model_flags & MR_NO_TEXTURING) ) {
2758  tmap_flags |= TMAP_FLAG_TEXTURED;
2759 
2760  if ( (pm->flags & PM_FLAG_ALLOW_TILING) && tiling)
2761  tmap_flags |= TMAP_FLAG_TILED;
2762 
2763  if ( !(model_flags & MR_NO_CORRECT) ) {
2764  tmap_flags |= TMAP_FLAG_CORRECT;
2765  }
2766  }
2767 
2768  if ( model_flags & MR_DESATURATED ) {
2769  tmap_flags |= TMAP_FLAG_DESATURATE;
2770  }
2771 
2772  if ( interp->get_animated_effect_num() >= 0 ) {
2773  tmap_flags |= TMAP_ANIMATED_SHADER;
2774  scene->set_animated_effect(interp->get_animated_effect_num());
2776  }
2777 
2778  bool is_outlines_only = (model_flags & MR_NO_POLYS) && ((model_flags & MR_SHOW_OUTLINE_PRESET) || (model_flags & MR_SHOW_OUTLINE));
2779  bool is_outlines_only_htl = !Cmdline_nohtl && (model_flags & MR_NO_POLYS) && (model_flags & MR_SHOW_OUTLINE_HTL);
2780 
2781  scene->push_transform(pos, orient);
2782 
2783  float depth = model_render_determine_depth(objnum, model_num, orient, pos, interp->get_detail_level_lock());
2784  int detail_level = model_render_determine_detail(depth, objnum, model_num, orient, pos, model_flags, interp->get_detail_level_lock());
2785 
2786  // If we're rendering attached weapon models, check against the ships' tabled Weapon Model Draw Distance (which defaults to 200)
2787  if ( model_flags & MR_ATTACHED_MODEL && shipp != NULL ) {
2788  if (depth > Ship_info[shipp->ship_info_index].weapon_model_draw_distance) {
2789  scene->pop_transform();
2790  return;
2791  }
2792  }
2793 
2794 // #ifndef NDEBUG
2795 // if ( Interp_detail_level == 0 ) {
2796 // MONITOR_INC( NumHiModelsRend, 1 );
2797 // } else if ( Interp_detail_level == pm->n_detail_levels-1 ) {
2798 // MONITOR_INC( NumLowModelsRend, 1 );
2799 // } else {
2800 // MONITOR_INC( NumMedModelsRend, 1 );
2801 // }
2802 // #endif
2803 
2804  vec3d auto_back = ZERO_VECTOR;
2805  bool set_autocen = model_render_determine_autocenter(&auto_back, pm, detail_level, model_flags);
2806 
2807  if ( set_autocen ) {
2808  scene->push_transform(&auto_back, NULL);
2809  }
2810 
2811  if ( tmap_flags & TMAP_FLAG_PIXEL_FOG ) {
2812  float fog_near = 10.0f, fog_far = 1000.0f;
2813  neb2_get_adjusted_fog_values(&fog_near, &fog_far, objp);
2814 
2815  unsigned char r, g, b;
2816  neb2_get_fog_color(&r, &g, &b);
2817 
2818  scene->set_fog(GR_FOGMODE_FOG, r, g, b, fog_near, fog_far);
2819  } else {
2820  scene->set_fog(GR_FOGMODE_NONE, 0, 0, 0);
2821  }
2822 
2823  if ( is_outlines_only_htl ) {
2825 
2826  tmap_flags &= ~TMAP_FLAG_RGB;
2827  } else {
2829  }
2830 
2831  scene->set_color(interp->get_color());
2832 
2833  if ( model_flags & MR_EDGE_ALPHA ) {
2834  scene->set_center_alpha(-1);
2835  } else if ( model_flags & MR_CENTER_ALPHA ) {
2836  scene->set_center_alpha(1);
2837  } else {
2838  scene->set_center_alpha(0);
2839  }
2840 
2841  if ( ( model_flags & MR_NO_CULL ) || ( model_flags & MR_ALL_XPARENT ) || ( interp->get_warp_bitmap() >= 0 ) ) {
2842  scene->set_cull_mode(0);
2843  } else {
2844  scene->set_cull_mode(1);
2845  }
2846 
2847  if ( !(model_flags & MR_NO_LIGHTING) ) {
2848  scene->set_lighting(true);
2849  } else {
2850  scene->set_lighting(false);
2851  }
2852 
2853  if (is_outlines_only_htl || (!Cmdline_nohtl && !is_outlines_only)) {
2854  scene->set_buffer(pm->vertex_buffer_id);
2855  }
2856 
2857  if ( Rendering_to_shadow_map ) {
2858  scene->set_zbias(-1024);
2859  } else {
2860  scene->set_zbias(0);
2861  }
2862 
2863  if ( !Cmdline_no_batching && !(model_flags & MR_NO_BATCH) && pm->flags & PM_FLAG_BATCHED
2864  && !(is_outlines_only || is_outlines_only_htl) ) {
2865  // always set batched rendering on if supported
2866  tmap_flags |= TMAP_FLAG_BATCH_TRANSFORMS;
2867  }
2868 
2869  if ( (tmap_flags & TMAP_FLAG_BATCH_TRANSFORMS) ) {
2870  scene->start_model_batch(pm->n_models);
2871  model_render_buffers(scene, interp, &pm->detail_buffers[detail_level], pm, -1, detail_level, tmap_flags);
2872  }
2873 
2874  // Draw the subobjects
2875  bool draw_thrusters = false;
2876  bool trans_buffer = false;
2877  i = pm->submodel[pm->detail[detail_level]].first_child;
2878 
2879  while( i >= 0 ) {
2880  if ( !pm->submodel[i].is_thruster ) {
2881  model_render_children_buffers( scene, interp, pm, pmi, i, detail_level, tmap_flags, trans_buffer );
2882  } else {
2883  draw_thrusters = true;
2884  }
2885 
2886  i = pm->submodel[i].next_sibling;
2887  }
2888 
2889  model_radius = pm->submodel[pm->detail[detail_level]].rad;
2890 
2891  //*************************** draw the hull of the ship *********************************************
2892  vec3d view_pos = scene->get_view_position();
2893 
2894  if ( model_render_check_detail_box(&view_pos, pm, pm->detail[detail_level], model_flags) ) {
2895  int detail_model_num = pm->detail[detail_level];
2896 
2897  if ( (is_outlines_only || is_outlines_only_htl) && pm->submodel[detail_model_num].outline_buffer != NULL ) {
2898  color outline_color = interp->get_color();
2899  scene->add_outline(pm->submodel[detail_model_num].outline_buffer, pm->submodel[detail_model_num].n_verts_outline, &outline_color);
2900  } else {
2901  model_render_buffers(scene, interp, &pm->submodel[detail_model_num].buffer, pm, detail_model_num, detail_level, tmap_flags);
2902 
2903  if ( pm->submodel[detail_model_num].num_arcs ) {
2904  model_render_add_lightning( scene, interp, pm, &pm->submodel[detail_model_num] );
2905  }
2906  }
2907  }
2908 
2909  // make sure batch rendering is unconditionally off.
2910  tmap_flags &= ~TMAP_FLAG_BATCH_TRANSFORMS;
2911 
2912  if ( pm->flags & PM_FLAG_TRANS_BUFFER && !(is_outlines_only || is_outlines_only_htl) ) {
2913  trans_buffer = true;
2914  i = pm->submodel[pm->detail[detail_level]].first_child;
2915 
2916  while( i >= 0 ) {
2917  if ( !pm->submodel[i].is_thruster ) {
2918  model_render_children_buffers( scene, interp, pm, pmi, i, detail_level, tmap_flags, trans_buffer );
2919  }
2920 
2921  i = pm->submodel[i].next_sibling;
2922  }
2923 
2924  view_pos = scene->get_view_position();
2925 
2926  if ( model_render_check_detail_box(&view_pos, pm, pm->detail[detail_level], model_flags) ) {
2927  int detail_model_num = pm->detail[detail_level];
2928  model_render_buffers(scene, interp, &pm->submodel[detail_model_num].trans_buffer, pm, detail_model_num, detail_level, tmap_flags);
2929  }
2930  }
2931 
2932  // Draw the thruster subobjects
2933  if ( draw_thrusters && !(is_outlines_only || is_outlines_only_htl) ) {
2934  i = pm->submodel[pm->detail[detail_level]].first_child;
2935  trans_buffer = false;
2936 
2937  while( i >= 0 ) {
2938  if (pm->submodel[i].is_thruster) {
2939  model_render_children_buffers( scene, interp, pm, pmi, i, detail_level, tmap_flags, trans_buffer );
2940  }
2941  i = pm->submodel[i].next_sibling;
2942  }
2943  }
2944 
2945  if ( !( model_flags & MR_NO_TEXTURING ) ) {
2946  scene->add_insignia(pm, detail_level, interp->get_insignia_bitmap());
2947  }
2948 
2949  if ( (model_flags & MR_AUTOCENTER) && (set_autocen) ) {
2950  scene->pop_transform();
2951  }
2952 
2953  scene->pop_transform();
2954 
2955  // start rendering glow points -Bobboau
2956  if ( (pm->n_glow_point_banks) && !is_outlines_only && !is_outlines_only_htl && !Glowpoint_override ) {
2957  model_render_glow_points(pm, shipp, orient, pos, Glowpoint_use_depth_buffer);
2958  }
2959 
2960  // Draw the thruster glow
2961  if ( !is_outlines_only && !is_outlines_only_htl ) {
2962  if ( ( model_flags & MR_AUTOCENTER ) && set_autocen ) {
2963  vec3d autoback_rotated;
2964 
2965  vm_vec_unrotate(&autoback_rotated, &auto_back, orient);
2966  vm_vec_add2(&autoback_rotated, pos);
2967 
2968  model_queue_render_thrusters( interp, pm, objnum, shipp, orient, &autoback_rotated );
2969  } else {
2970  model_queue_render_thrusters( interp, pm, objnum, shipp, orient, pos );
2971  }
2972  }
2973 }
vec3d max
Definition: model.h:343
int clip_plane_handle
Definition: modelrender.h:173
float model_render_determine_light_factor(model_render_params *interp, vec3d *pos, uint flags)
vec3d render_box_max
Definition: model.h:381
void add_outline(vertex *vert_array, int n_verts, color *clr)
#define TMAP_FLAG_PIXEL_FOG
Definition: tmapper.h:60
void model_render_buffers(draw_list *scene, model_render_params *interp, vertex_buffer *buffer, polymodel *pm, int mn, int detail_level, uint tmap_flags)
#define gr_zbuffer_set
Definition: 2d.h:817
bsp_info * submodel
Definition: model.h:764
void submodel_render_immediate(model_render_params *render_info, int model_num, int submodel_num, matrix *orient, vec3d *pos)
int timestamp(int delta_ms)
Definition: timer.cpp:226
struct screen3d::@234::@236 xyw
const int AG
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
int batch_add_quad(int texture, int tmap_flags, vertex *verts, float alpha)
Definition: grbatch.cpp:858
vec3d render_sphere_offset
Definition: model.h:384
const int AB2
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
#define MR_SHOW_OUTLINE_HTL
Definition: model.h:885
#define TM_BASE_TYPE
Definition: model.h:657
#define gr_alpha_mask_set
Definition: 2d.h:823
#define SF_DEPART_WARP
Definition: ship.h:449
void set_team_color(const team_color &clr)
#define TMAP_FLAG_SOFT_QUAD
Definition: tmapper.h:79
int in_sphere(vec3d *pos, float radius, vec3d *view_pos)
Definition: modelrender.h:44
const int AR
#define MR_NO_CULL
Definition: model.h:879
const int AG2
float width
Definition: modelrender.h:157
vec3d min
Definition: model.h:342
float vm_vec_mag_quick(const vec3d *v)
Definition: vecmat.cpp:371
matrix * vm_matrix_x_matrix(matrix *dest, const matrix *src0, const matrix *src1)
Definition: vecmat.cpp:1006
int Neb2_render_mode
Definition: neb.cpp:57
#define TMAP_FLAG_LINES
Definition: tmapper.h:91
#define MR_NORMAL
Definition: model.h:858
vec3d View_position
Definition: 3dsetup.cpp:20
int objnum
Definition: ship.h:537
void add_insignia(polymodel *pm, int detail_level, int bitmap_num)
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
matrix basis
Definition: modelrender.h:56
SCP_vector< thruster_particles > normal_thruster_particles
Definition: ship.h:1376
#define gr_pop_scale_matrix
Definition: 2d.h:898
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
color secondary
Definition: modelrender.h:156
int detail_distance
Definition: systemvars.h:168
int batch_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, float width, float intensity)
Definition: grbatch.cpp:968
int glow_timestamp
Definition: model.h:462
float max_rad
Definition: ship.h:970
float v
Definition: pstypes.h:135
void g3_stop_user_clip_plane()
Definition: 3dsetup.cpp:408
float vm_vec_mag(const vec3d *v)
Definition: vecmat.cpp:325
ubyte g
Definition: pstypes.h:175
bool Glowpoint_override
Definition: systemvars.cpp:75
bool Scene_framebuffer_in_frame
void set_animated_effect(int effect)
#define MR_ALL_XPARENT
Definition: model.h:877
vec3d desired_vel
Definition: physics.h:70
asteroid Asteroids[MAX_ASTEROIDS]
Definition: asteroid.cpp:63
physics_info phys_info
Definition: object.h:157
void set_thruster_info(mst_info &info)
#define MR_FORCE_CLAMP
Definition: model.h:888
#define MR_EDGE_ALPHA
Definition: model.h:882
void vm_rotate_matrix_by_angles(matrix *orient, const angles *tangles)
Definition: vecmat.cpp:1338
#define WT_HYPERSPACE
Definition: ship.h:1111
int id
Definition: model.h:732
void set_fog(int fog_mode, int r, int g, int b, float fog_near=-1.0f, float fog_far=-1.0f)
void set_team_color()
void model_render_glowpoint(int point_num, vec3d *pos, matrix *orient, glow_point_bank *bank, glow_point_bank_override *gpo, polymodel *pm, ship *shipp, bool use_depth_buffer)
#define GR_ZBUFF_READ
Definition: 2d.h:674
ubyte g3_transfer_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:84
void set_cull_mode(int mode)
float fog_near
Definition: modelrender.h:199
int model_instance_num
Definition: ship.h:802
void model_render_set_glow_points(polymodel *pm, int objnum)
int bitmap
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
int distortion_bitmap
Definition: model.h:1295
float a1d[16]
Definition: pstypes.h:130
#define MR_NO_POLYS
Definition: model.h:866
bool model_render_determine_autocenter(vec3d *auto_back, polymodel *pm, int detail_level, uint flags)
int detail[MAX_MODEL_DETAIL_LEVELS]
Definition: model.h:738
Definition: pstypes.h:88
float detail_depth[MAX_MODEL_DETAIL_LEVELS]
Definition: model.h:739
light Lights[MAX_LIGHTS]
Definition: lighting.cpp:28
void light_add_point(const vec3d *pos, float r1, float r2, float intensity, float r, float g, float b, int light_ignore_objnum, float spec_r, float spec_g, float spec_b, bool specular)
Definition: lighting.cpp:253
int Model_texturing
GLint GLint GLsizei GLsizei GLsizei depth
Definition: Glext.h:5180
int num_arcs
Definition: model.h:369
virtual int getWarpOrientation(matrix *output)
Definition: shipfx.cpp:3534
#define OBJ_ASTEROID
Definition: object.h:44
Definition: 2d.h:95
#define MR_SHOW_OUTLINE_PRESET
Definition: model.h:873
matrix Eye_matrix
Definition: 3dsetup.cpp:26
#define gr_render
Definition: 2d.h:805
#define MR_DEBUG_SHIELDS
Definition: model.h:929
#define PM_FLAG_TRANS_BUFFER
Definition: model.h:622
#define MR_NO_CORRECT
Definition: model.h:869
void set_flags(uint flags)
#define MARC_TYPE_NORMAL
Definition: model.h:252
transform transformation
Definition: modelrender.h:152
#define MR_NO_LIGHTING
Definition: model.h:867
#define MIN_SCALE
#define GR_ZBUFF_FULL
Definition: 2d.h:675
struct vec3d::@225::@227 xyz
void setLightFilter(int objnum, const vec3d *pos, float rad)
Definition: lighting.cpp:1117
CButton * team
int Model_polys
void neb2_get_fog_color(ubyte *r, ubyte *g, ubyte *b)
Definition: neb.cpp:319
#define TMAP_HTL_3D_UNLIT
Definition: tmapper.h:63
int Num_arc_segment_points
void model_render_immediate(model_render_params *render_info, int model_num, matrix *orient, vec3d *pos, int render, bool sort)
bool Deferred_lighting
float tertiary_glow_rad_factor
Definition: model.h:1304
GLclampf f
Definition: Glext.h:7097
vec3d norm
Definition: model.h:441
GLfloat bias
Definition: Glext.h:7380
void render_arcs()
#define GR_ZBUFF_NONE
Definition: 2d.h:672
void add_buffer_draw(vertex_buffer *buffer, int texi, uint tmap_flags, model_render_params *interp)
int n_glow_point_banks
Definition: model.h:810
__inline void gr_render_buffer(int start, const vertex_buffer *bufferp, int texi, int flags=TMAP_FLAG_TEXTURED)
Definition: 2d.h:877
void set_buffer(int buffer)
GLenum GLuint texture
Definition: Glext.h:5872
matrix * vm_copy_transpose(matrix *dest, const matrix *src)
Definition: vecmat.cpp:984
#define gr_set_light_factor
Definition: 2d.h:925
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
int glow_bitmap
Definition: model.h:471
float factor
Definition: lua.cpp:440
int tiling
void init()
void resetLightState()
Definition: lighting.cpp:1223
#define MR_SHOW_OUTLINE
Definition: model.h:859
#define PM_FLAG_ALLOW_TILING
Definition: model.h:620
vec3d origin
Definition: modelrender.h:57
bool Rendering_to_shadow_map
Definition: gropengltnl.cpp:88
void set_detail_level_lock(int detail_level_lock)
#define SF_ARRIVING
Definition: ship.h:453
GLenum mode
Definition: Glext.h:5794
int flags
Definition: 2d.h:307
void set_insignia_bitmap(int bitmap)
opengl_texture_state Texture
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
#define GR_FILL_MODE_SOLID
Definition: 2d.h:670
int Interp_thrust_scale_subobj
uint flags
Definition: ship.h:644
#define MR_DEBUG_BAY_PATHS
Definition: model.h:930
hull_check orient
Definition: lua.cpp:5049
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
int batch_add_bitmap_rotated(int texture, int tmap_flags, vertex *pnt, float angle, float rad, float alpha, float depth)
Definition: grbatch.cpp:793
void find_submodel_instance_point_normal(vec3d *outpnt, vec3d *outnorm, int model_instance_num, int submodel_num, const vec3d *submodel_pnt, const vec3d *submodel_norm)
Definition: modelread.cpp:4302
object * objp
Definition: lua.cpp:3105
#define MODEL_RENDER_TRANS
Definition: model.h:934
void add_matrix(matrix4 &mat)
GLenum GLenum GLenum GLenum GLenum scale
Definition: Glext.h:8503
#define PARTICLE_BITMAP
Definition: particle.h:49
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
#define TM_SPECULAR_TYPE
Definition: model.h:659
GLfloat GLfloat GLfloat v2
Definition: Glext.h:5640
GLsizeiptr size
Definition: Glext.h:5496
#define gr_set_transform_buffer_offset
Definition: 2d.h:884
#define Int3()
Definition: pstypes.h:292
#define MODEL_RENDER_OPAQUE
Definition: model.h:933
#define PULSE_SHIFTTRI
Definition: model.h:458
float model_render_determine_depth(int obj_num, int model_num, matrix *orient, vec3d *pos, int detail_level_locked)
void set_lighting(bool mode)
ship * shipp
Definition: lua.cpp:9162
struct matrix4 matrix4
int n_thrusters
Definition: model.h:771
vec3d view_pos
Definition: fredrender.cpp:103
hull_check submodel_num
Definition: lua.cpp:5048
void model_draw_paths_htl(int model_num, uint flags)
void model_render_insignias(polymodel *pm, int detail_level, int bitmap_num)
vertex_buffer buffer
Definition: model.h:374
int NORMMAP
Normal mapping.
Definition: bmpman.cpp:60
#define IS_VEC_NULL(v)
Definition: vecmat.h:28
float gun_submodel_rotation
Definition: model.h:813
float get_animated_effect_timer()
void particle_emit(particle_emitter *pe, int type, int optional_data, float range)
Definition: particle.cpp:495
thruster_bank * thrusters
Definition: model.h:775
#define TM_NUM_TYPES
Definition: model.h:663
#define TMAP_ANIMATED_SHADER
Definition: tmapper.h:76
int texture_addressing
Definition: modelrender.h:174
#define MR_ATTACHED_MODEL
Definition: model.h:890
#define PULSE_TRI
Definition: model.h:457
std::deque< bool > glow_point_bank_active
Definition: ship.h:763
GLenum type
Definition: Gl.h:1492
#define IS_VEC_NULL_SQ_SAFE(v)
Definition: vecmat.h:24
#define CLAMP(x, min, max)
Definition: pstypes.h:488
int HEIGHTMAP
Height map for normal mapping.
Definition: bmpman.cpp:61
GLint GLsizei width
Definition: Gl.h:1505
transform transformation
Definition: modelrender.h:243
void g3_start_user_clip_plane(const vec3d *plane_point, const vec3d *plane_normal)
Definition: 3dsetup.cpp:381
void pop_transform()
#define gr_set_lighting
Definition: 2d.h:924
void g3_done_instance(bool set_api=false)
Definition: 3dsetup.cpp:341
void gr_set_color(int r, int g, int b)
Definition: 2d.cpp:1188
int texture_maps[TM_NUM_TYPES]
Definition: modelrender.h:235
const vec3d & get_warp_scale()
SCP_vector< buffer_data > tex_buf
Definition: 2d.h:314
#define MR_SKYBOX
Definition: model.h:860
float light_factor
Definition: modelrender.h:186
light_indexing_info bufferLights()
Definition: lighting.cpp:1193
uv_pair texture_position
Definition: pstypes.h:174
void model_find_submodel_offset(vec3d *outpnt, int model_num, int sub_model_num)
Definition: modelread.cpp:4041
void set_alpha(float alpha)
team_color tm_color
Definition: modelrender.h:191
bool Cmdline_no_batching
Definition: cmdline.cpp:341
const int AR2
#define PM_FLAG_HAS_INTRINSIC_ROTATE
Definition: model.h:624
ubyte a
Definition: pstypes.h:175
void model_render_queue(model_render_params *interp, draw_list *scene, int model_num, matrix *orient, vec3d *pos)
void set_center_alpha(int center_alpha)
void model_draw_paths(int model_num, uint flags)
int instance
Definition: object.h:150
GLintptr offset
Definition: Glext.h:5497
matrix Object_matrix
Definition: 3dsetup.cpp:43
void set_debug_flags(uint flags)
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
int Cmdline_nohtl
Definition: cmdline.cpp:438
float a1d[3]
Definition: pstypes.h:93
#define GR_ALPHABLEND_FILTER
Definition: 2d.h:349
const float PI2
Definition: pstypes.h:305
float model_radius
Definition: modelinterp.cpp:41
WarpEffect * warpout_effect
Definition: ship.h:576
GLdouble GLdouble GLdouble r
Definition: Glext.h:5337
vec3d autocenter
Definition: model.h:755
void model_draw_bay_paths(int model_num)
struct matrix::@228::@230 vec
float neb2_get_fog_intensity(object *obj)
Definition: neb.cpp:1185
unsigned int uint
Definition: pstypes.h:64
virtual int getWarpPosition(vec3d *output)
Definition: shipfx.cpp:3525
void set_animated_timer(float time)
bsp_info * sm
Definition: lua.cpp:7079
screen3d screen
Definition: pstypes.h:173
GLboolean GLboolean g
Definition: Glext.h:5781
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
#define MR_NO_ZBUFFER
Definition: model.h:878
const int AB
#define TMAP_FLAG_GOURAUD
Definition: tmapper.h:40
bool use_ab
Definition: model.h:1297
#define PULSE_SIN
Definition: model.h:455
int gameseq_get_state_idx(char *s)
detail_levels Detail
Definition: systemvars.cpp:478
int first_frame
Definition: generic.h:19
void model_queue_render_thrusters(model_render_params *interp, polymodel *pm, int objnum, ship *shipp, matrix *orient, vec3d *pos)
float glow_noise
Definition: model.h:1298
void interp_render_arc_segment(vec3d *v1, vec3d *v2, int depth)
void reset()
int Num_lights
Definition: lighting.cpp:29
#define MR_NO_TEXTURING
Definition: model.h:868
GLboolean GLboolean GLboolean GLboolean a
Definition: Glext.h:5781
#define gr_set_thrust_scale
Definition: 2d.h:927
void render_insignias()
int off_time
Definition: model.h:464
ai_profile_t * ai_profile
Definition: missionparse.h:168
#define gr_set_buffer
Definition: 2d.h:891
void set_light_filter(int objnum, vec3d *pos, float rad)
int clip_plane(int plane_flag, vertex **src, vertex **dest, int *nv, ccodes *cc, uint flags)
Clips a plane to the viewing pyramid.
Definition: 3dclipper.cpp:222
int GLOWMAP
References a map that is a fully lit version of its index -Bobboau.
Definition: bmpman.cpp:57
polymodel * pm
Definition: modelrender.h:163
vec3d rotvel
Definition: model.h:1299
#define OBJ_WEAPON
Definition: object.h:33
int num_points
Definition: model.h:446
void moldel_calc_facing_pts(vec3d *top, vec3d *bot, vec3d *fvec, vec3d *pos, float w, float z_add, vec3d *Eyeposition)
texture_map maps[MAX_MODEL_TEXTURES]
Definition: model.h:762
bool use_render_box_offset
Definition: model.h:386
const int MAX_ARC_SEGMENT_POINTS
#define w(p)
Definition: modelsinc.h:68
void model_draw_bay_paths_htl(int model_num)
float variance
Definition: ship.h:973
void set_team_color(team_color &clr)
void submodel_render_queue(model_render_params *render_info, draw_list *scene, int model_num, int submodel_num, matrix *orient, vec3d *pos)
void vm_rot_point_around_line(vec3d *out, const vec3d *in, float angle, const vec3d *line_point, const vec3d *line_dir)
Definition: vecmat.cpp:1395
submodel_instance * submodel
Definition: model.h:100
int glow_neb_bitmap
Definition: model.h:472
vertex_buffer detail_buffers[MAX_MODEL_DETAIL_LEVELS]
Definition: model.h:817
bool can_move
Definition: model.h:328
vertex_buffer trans_buffer
Definition: model.h:375
#define vm_vec_negate(v)
Definition: vecmat.h:70
int use_render_box
Definition: model.h:385
#define VB_FLAG_MODEL_ID
Definition: 2d.h:1010
float distortion_length_factor
Definition: model.h:1307
fix Skybox_timestamp
Definition: systemvars.cpp:20
int submodel_num
Definition: model.h:452
ubyte g3_rotate_vertex(vertex *dest, const vec3d *src)
Definition: 3dmath.cpp:97
uint flags
Definition: model.h:736
bool draw_distortion
Definition: model.h:1308
int model_render_determine_detail(float depth, int obj_num, int model_num, matrix *orient, vec3d *pos, int flags, int detail_level_locked)
Definition: bmpman.h:101
GLuint buffer
Definition: Glext.h:5492
#define TMAP_FLAG_DESATURATE
Definition: tmapper.h:87
float u
Definition: pstypes.h:135
#define TMAP_FLAG_BATCH_TRANSFORMS
Definition: tmapper.h:54
int primary_glow_bitmap
Definition: model.h:1292
light_indexing_info lights
Definition: modelrender.h:185
bool use_render_sphere_offset
Definition: model.h:388
float animated_timer
Definition: modelrender.h:181
vec3d offset
Definition: model.h:330
#define TMAP_FLAG_TILED
Definition: tmapper.h:45
void init_render(bool sort=true)
#define MR_DEBUG_PIVOTS
Definition: model.h:926
fix model_render_determine_base_frametime(int objnum, uint flags)
void set_texture_addressing(int addressing)
bool setLights(const light_indexing_info *info)
Definition: lighting.cpp:1229
Definition: ship.h:534
transform transformation
Definition: modelrender.h:271
#define MR_DEBUG_PATHS
Definition: model.h:927
const GLuint * textures
Definition: Glext.h:7569
#define PULSE_COS
Definition: model.h:456
void set_color(color &clr)
int g3_project_vertex(vertex *point)
Definition: 3dmath.cpp:202
int idx
Definition: multiui.cpp:761
void model_draw_debug_points(polymodel *pm, bsp_info *submodel, uint flags)
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:959
SCP_vector< thruster_particles > afterburner_thruster_particles
Definition: ship.h:1377
float neb2_get_lod_scale(int objnum)
Definition: neb.cpp:614
#define REPLACE_WITH_INVISIBLE
Definition: model.h:693
void set_forced_bitmap(int bitmap)
#define MODEL_RENDER_ALL
Definition: model.h:935
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
bool Glowpoint_use_depth_buffer
Definition: systemvars.cpp:76
long fix
Definition: pstypes.h:54
int model_instance_num
Definition: weapon.h:166
#define MR_SHOW_THRUSTERS
Definition: model.h:864
unsigned char ubyte
Definition: pstypes.h:62
void set_replacement_textures(int *textures)
#define gr_push_scale_matrix
Definition: 2d.h:897
#define ZERO_VECTOR
Definition: vecmat.h:60
angles angs
Definition: model.h:349
color primary
Definition: modelrender.h:155
float radius
Definition: model.h:442
#define gr_set_cull
Definition: 2d.h:838
void add_submodel_to_batch(int model_num)
vec3d Arc_segment_points[]
int tertiary_glow_bitmap
Definition: model.h:1294
#define TMAP_FLAG_RGB
Definition: tmapper.h:39
#define gr_set_texture_addressing
Definition: 2d.h:871
void add_arc(vec3d *v1, vec3d *v2, color *primary, color *secondary, float arc_width)
float glow_length_factor
Definition: model.h:1305
GLuint start
Definition: Gl.h:1502
float rad
Definition: model.h:340
ubyte b
Definition: pstypes.h:175
SCP_unordered_map< int, void * > glowpoint_bank_override_map
Definition: ship.h:1455
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
Definition: vecmat.cpp:257
#define OBJ_SHIP
Definition: object.h:32
const vec3d & get_clip_plane_pos()
GLfloat GLfloat v1
Definition: Glext.h:5639
float glow_rad_factor
Definition: model.h:1302
int blown_off
Definition: model.h:346
#define TMAP_ADDRESS_WRAP
Definition: tmapper.h:94
#define TMAP_FLAG_CORRECT
Definition: tmapper.h:37
float model_render_determine_box_scale()
bool using_team_color
Definition: modelrender.h:190
void set_clip_plane()
void set_scale(vec3d *scale=NULL)
GLbitfield flags
Definition: Glext.h:6722
transform transformation
Definition: modelrender.h:162
Definition: 2d.h:109
#define vm_malloc(size)
Definition: pstypes.h:547
float detail_distance_mult[MAX_DETAIL_LEVEL+1]
Definition: ai_profiles.h:152
#define MAX_SCALE
float thrust_scale
Definition: modelrender.h:188
void set_depth_scale(float scale)
int disp_time
Definition: model.h:465
void model_render_debug_children(polymodel *pm, int mn, int detail_level, uint debug_flags)
int Game_detail_level
Definition: systemvars.cpp:51
int animated_effect
Definition: modelrender.h:182
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
void set_model_transform(matrix4 &transform, int model_id)
int primary_bitmap
Definition: model.h:1291
vec3d Eye_position
Definition: 3dsetup.cpp:27
#define TM_GLOW_TYPE
Definition: model.h:658
ubyte arc_type[MAX_ARC_EFFECTS]
Definition: model.h:371
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
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
uint Game_detail_flags
Definition: systemvars.cpp:52
int shockwave_get_framenum(int index, int num_frames)
Definition: shockwave.cpp:222
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
GLuint GLuint num
Definition: Glext.h:9089
#define gr_zbias
Definition: 2d.h:932
polymodel_instance * model_get_instance(int model_instance_num)
Definition: modelread.cpp:3154
fix base_texture_anim_frametime
Definition: ship.h:691
void model_render_children_buffers(draw_list *scene, model_render_params *interp, polymodel *pm, polymodel_instance *pmi, int mn, int detail_level, uint tmap_flags, bool trans_buffer)
opengl_state GL_state
glow_point_bank * glow_point_banks
Definition: model.h:811
#define MR_CENTER_ALPHA
Definition: model.h:883
float vm_vec_dist_quick(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:417
vertex * vert_array
Definition: modelrender.h:268
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
float rad
Definition: model.h:757
void model_render_glow_points(polymodel *pm, ship *shipp, matrix *orient, vec3d *pos, bool use_depth_buffer=true)
int n_models
Definition: model.h:744
GLuint GLenum GLenum transform
Definition: Glext.h:8878
vec3d render_box_offset
Definition: model.h:382
bool is_transparent
Definition: model.h:674
void set_color(const color &clr)
void clear_transforms()
int batch_add_bitmap(int texture, int tmap_flags, vertex *pnt, int orient, float rad, float alpha, float depth)
Definition: grbatch.cpp:724
int obj_num
Definition: model.h:451
void set_blend_filter(int filter, float alpha)
int model_instance_num
Definition: asteroid.h:101
int model_should_render_engine_glow(int objnum, int bank_obj)
#define OBJ_SHOCKWAVE
Definition: object.h:41
screen gr_screen
Definition: 2d.cpp:46
glow_point * points
Definition: model.h:447
void light_add_cone(const vec3d *pos, const vec3d *dir, float angle, float inner_angle, bool dual_cone, float r1, float r2, float intensity, float r, float g, float b, int light_ignore_objnum, float spec_r, float spec_g, float spec_b, bool specular)
Definition: lighting.cpp:1050
model_batch_buffer TransformBufferHandler
Definition: modelrender.cpp:47
#define MR_IS_ASTEROID
Definition: model.h:871
void set_warp_params(int bitmap, float alpha, vec3d &scale)
#define gr_clear_states
Definition: 2d.h:946
#define MARC_TYPE_EMP
Definition: model.h:253
vertex * outline_buffer
Definition: model.h:377
int next_sibling
Definition: model.h:362
GLuint interp
Definition: Glext.h:8983
float vm_vec_copy_normalize(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:427
void model_render_shields(polymodel *pm, uint flags)
void render_all(int depth_mode=-1)
int ship_info_index
Definition: ship.h:539
float render_sphere_radius
Definition: model.h:383
void set_light_factor(float factor)
GLfloat GLfloat p
Definition: Glext.h:8373
void neb2_get_adjusted_fog_values(float *fnear, float *ffar, object *objp)
Definition: neb.cpp:1170
bool blown_off
Definition: model.h:93
#define MR_IS_MISSILE
Definition: model.h:872
texture_info textures[TM_NUM_TYPES]
Definition: model.h:671
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
#define TMAP_FLAG_ALPHA
Definition: tmapper.h:53
#define MR_FULL_DETAIL
Definition: model.h:887
vec3d length
Definition: model.h:1300
void g3_start_instance_matrix(const vec3d *pos, const matrix *orient, bool set_api=true)
Definition: 3dsetup.cpp:249
#define TMAP_FLAG_TEXTURED
Definition: tmapper.h:36
#define VB_FLAG_TRANS
Definition: 2d.h:1011
uint gr_determine_model_shader_flags(bool lighting, bool fog, bool textured, bool in_shadow_map, bool thruster_scale, bool transform, bool team_color_set, int tmap_flags, int spec_map, int glow_map, int normal_map, int height_map, int env_map, int misc_map)
Definition: 2d.cpp:2131
int static_rand(int num)
Return a pseudo random 32 bit value given a reasonably small number.
Definition: staticrand.cpp:38
#define gr_set_fill_mode
Definition: 2d.h:933
int model_interp_get_texture(texture_info *tinfo, fix base_frametime)
const int * get_replacement_textures()
float normal_variance
Definition: particle.h:114
#define MAX_MODEL_DETAIL_LEVELS
Definition: model.h:27
uint n_verts_outline
Definition: model.h:378
#define TM_HEIGHT_TYPE
Definition: model.h:661
color current_color
Definition: 2d.h:396
#define PI
Definition: pstypes.h:303
int is_thruster
Definition: model.h:355
#define MR_DESATURATED
Definition: model.h:861
hull_check pos
Definition: lua.cpp:5050
int secondary_glow_bitmap
Definition: model.h:1293
#define MR_DEBUG_RADIUS
Definition: model.h:928
void model_render_add_lightning(draw_list *scene, model_render_params *interp, polymodel *pm, bsp_info *sm)
GLsizei GLsizei GLuint * obj
Definition: Glext.h:5619
const color & get_color()
#define GR_FOGMODE_FOG
Definition: 2d.h:356
#define DETAIL_FLAG_MODELS
Definition: systemvars.h:111
int ENVMAP
References a map that is for environment mapping -Bobboau.
Definition: bmpman.cpp:59
#define gr_reset_lighting
Definition: 2d.h:907
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
glow_point * points
Definition: model.h:470
float a1d[9]
Definition: pstypes.h:120
vec3d arc_pts[MAX_ARC_EFFECTS][2]
Definition: model.h:370
#define gr_set_animated_effect
Definition: 2d.h:944
void set_clip_plane(vec3d &pos, vec3d &normal)
void set_depth_mode(int depth_set)
#define GR_BITBLT_MODE_NORMAL
Definition: 2d.h:351
#define gr_update_transform_buffer
Definition: 2d.h:883
float secondary_glow_rad_factor
Definition: model.h:1303
#define PM_FLAG_AUTOCEN
Definition: model.h:621
void render_outlines()
int num_points
Definition: model.h:469
int SPECMAP
References a map that is for specular mapping -Bobboau.
Definition: bmpman.cpp:58
void set_animated_effect(int effect_num, float timer)
int in_box(vec3d *min, vec3d *max, vec3d *pos, vec3d *view_pos)
Definition: modelrender.h:28
void model_render_debug(int model_num, matrix *orient, vec3d *pos, uint flags, uint debug_flags, int objnum, int detail_level_locked)
void interp_render_arc(vec3d *v1, vec3d *v2, color *primary, color *secondary, float arc_width)
void set_clip_plane(const vec3d &position, const vec3d &normal)
bool is_minimum_GLSL_version()
Definition: gropengl.cpp:2064
polymodel * pm
Definition: lua.cpp:1598
const team_color & get_team_color()
WarpEffect * warpin_effect
Definition: ship.h:575
int vertex_buffer_id
Definition: model.h:815
#define MAX(a, b)
Definition: pstypes.h:299
#define NEB2_RENDER_NONE
Definition: neb.h:31
void set_zbias(int bias)
bool is_on
Definition: model.h:466
int g3_draw_sphere_ez(const vec3d *pnt, float rad)
Definition: 3ddraw.cpp:498
matrix orientation
Definition: model.h:331
vertex_buffer * buffer
Definition: modelrender.h:246
bool model_render_check_detail_box(vec3d *view_pos, polymodel *pm, int submodel_num, uint flags)
#define gr_center_alpha
Definition: 2d.h:926
#define TMAP_FLAG_DISTORTION_THRUSTER
Definition: tmapper.h:82
#define GR_ALPHABLEND_NONE
Definition: 2d.h:348
false
Definition: lua.cpp:6789
#define TMAP_ADDRESS_CLAMP
Definition: tmapper.h:96
int distortion_add_beam(int texture, int tmap_flags, vec3d *start, vec3d *end, float width, float intensity, float offset)
Definition: grbatch.cpp:1210
int MISCMAP
Utility map, to be utilized for various things shader authors can come up with.
Definition: bmpman.cpp:62
mission The_mission
#define MR_NO_BATCH
Definition: model.h:881
#define gr_set_team_color
Definition: 2d.h:948
vec3d pnt
Definition: model.h:440
vec3d get_view_position()
int model_num
Definition: lua.cpp:4996
GLclampf GLclampf GLclampf alpha
Definition: Glext.h:5177
void set_object_number(int num)
char type
Definition: object.h:146
vec3d render_box_min
Definition: model.h:380
angles angs
Definition: model.h:88
vec3d vmd_zero_vector
Definition: vecmat.cpp:24
float distortion_rad_factor
Definition: model.h:1306
#define MR_NO_GLOWMAPS
Definition: model.h:886
bool gun_rotation
Definition: model.h:389
void start_model_batch(int n_models)
int Nmodel_instance_num
Definition: starfield.cpp:167
#define LT_DIRECTIONAL
Definition: lighting.h:25
#define MR_NO_FOGGING
Definition: model.h:884
int Nmodel_num
Definition: starfield.cpp:166
void vm_vec_add(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:159
const GLdouble * v
Definition: Glext.h:5322
void gr_init_color(color *c, int r, int g, int b)
Definition: 2d.cpp:1155
matrix vmd_identity_matrix
Definition: vecmat.cpp:28
void set_texture(int texture_type, int texture_handle)
const vec3d & get_clip_plane_normal()
int submodel_parent
Definition: model.h:467
#define TM_MISC_TYPE
Definition: model.h:662
#define TM_NORMAL_TYPE
Definition: model.h:660
void push_transform(vec3d *pos, matrix *orient)
float model_find_closest_point(vec3d *outpnt, int model_num, int submodel_num, matrix *orient, vec3d *pos, vec3d *eye_pos)
bool model_get_team_color(team_color *clr, const SCP_string &team, const SCP_string &secondaryteam, fix timestamp, int fadetime)
const mst_info & get_thruster_info()
#define PM_FLAG_BATCHED
Definition: model.h:623
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: Glext.h:6566
#define VB_FLAG_UV1
Definition: 2d.h:1004
#define NOISE_SCALE
GLuint GLuint end
Definition: Gl.h:1502
#define GR_FILL_MODE_WIRE
Definition: 2d.h:669
int first_child
Definition: model.h:361
void addLight(const light *light_ptr)
Definition: lighting.cpp:1106
ubyte r
Definition: pstypes.h:175
int n_detail_levels
Definition: model.h:737
int use_render_sphere
Definition: model.h:387
float b
Definition: pstypes.h:111
void set_fill_mode(int mode)
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460
#define GR_FOGMODE_NONE
Definition: 2d.h:355
void set_num_models(int n_models)
float Interp_thrust_scale
float min_rad
Definition: ship.h:969
generic_anim thruster_bitmap
Definition: ship.h:968
void set_thrust_scale(float scale=-1.0f)
int Interp_lightning
#define MR_AUTOCENTER
Definition: model.h:875