Panda3D
standardMunger.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file standardMunger.cxx
10  * @author drose
11  * @date 2005-03-21
12  */
13 
14 #include "standardMunger.h"
15 
16 #include "config_gobj.h"
17 
18 #include "displayRegion.h"
19 #include "graphicsStateGuardian.h"
20 #include "lightAttrib.h"
21 #include "materialAttrib.h"
22 #include "renderState.h"
23 
24 TypeHandle StandardMunger::_type_handle;
25 
26 /**
27  * The StandardMunger constructor accepts additional parameters that specify
28  * the GSG's preferred color format (since we might be munging the color
29  * anyway, we might as well convert it as we munge).
30  */
33  int num_components,
34  StandardMunger::NumericType numeric_type,
35  StandardMunger::Contents contents) :
36  StateMunger(gsg),
37  _num_components(num_components),
38  _numeric_type(numeric_type),
39  _contents(contents),
40  _munge_color(false),
41  _munge_color_scale(false),
42  _auto_shader(false),
43  _shader_skinning(false),
44  _remove_material(false)
45 {
46  const ShaderAttrib *shader_attrib;
47  state->get_attrib_def(shader_attrib);
48 #ifdef HAVE_CG
49  _auto_shader = shader_attrib->auto_shader();
50 #endif
51  if (shader_attrib->get_flag(ShaderAttrib::F_hardware_skinning)) {
52  _shader_skinning = true;
53  }
54 
55  if (!get_gsg()->get_runtime_color_scale() && !_auto_shader &&
56  shader_attrib->get_shader() == nullptr) {
57  // We might need to munge the colors.
58  const ColorAttrib *color_attrib;
59  const ColorScaleAttrib *color_scale_attrib;
60 
61  if (state->get_attrib(color_attrib) &&
62  color_attrib->get_color_type() != ColorAttrib::T_vertex) {
63 
64  // In this case, we don't need to munge anything as we can apply the
65  // color and color scale via glColor4f.
66 
67  } else if (state->get_attrib(color_scale_attrib) &&
68  color_scale_attrib->has_scale()) {
69  _color_scale = color_scale_attrib->get_scale();
70 
71  const TextureAttrib *tex_attrib = (const TextureAttrib *)
72  state->get_attrib(TextureAttrib::get_class_slot());
73 
74  // If the GSG says it can't cheat this RGB or alpha scale, we have to
75  // apply the color scale directly.
76  if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) ||
77  (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) {
78  _munge_color_scale = true;
79  _should_munge_state = true;
80  }
81 
82  // Known bug: if there is a material on an object that would obscure the
83  // effect of color_scale, we scale the lighting anyway, thus applying
84  // the effect even if it should be obscured. It doesn't seem worth the
85  // effort to detect this contrived situation and handle it correctly.
86  }
87  }
88 
89  // If we have no lights but do have a material, we will need to remove it so
90  // that it won't appear when we enable color scale via lighting.
91  const LightAttrib *light_attrib;
92  const MaterialAttrib *material_attrib;
94  (!state->get_attrib(light_attrib) || !light_attrib->has_any_on_light()) &&
95  state->get_attrib(material_attrib) &&
96  material_attrib->get_material() != nullptr &&
97  shader_attrib->get_shader() == nullptr) {
98  _remove_material = true;
99  _should_munge_state = true;
100  }
101 }
102 
103 /**
104  *
105  */
106 StandardMunger::
107 ~StandardMunger() {
108 }
109 
110 /**
111  * Given a source GeomVertexData, converts it as necessary for rendering.
112  */
113 CPT(GeomVertexData) StandardMunger::
114 munge_data_impl(const GeomVertexData *data) {
115  CPT(GeomVertexData) new_data = data;
116 
117  if (_munge_color) {
118  new_data = new_data->set_color(_color, _num_components, _numeric_type,
119  _contents);
120  } else if (_munge_color_scale) {
121  new_data = new_data->scale_color(_color_scale, _num_components,
122  _numeric_type, _contents);
123  }
124 
125  GeomVertexAnimationSpec animation = new_data->get_format()->get_animation();
126  if ((_shader_skinning && animation.get_animation_type() != AT_none) ||
127  (_auto_shader && hardware_animated_vertices &&
128  !basic_shaders_only && animation.get_animation_type() == AT_panda)) {
129  animation.set_hardware(4, true);
130 
131  } else if (hardware_animated_vertices &&
132  animation.get_animation_type() == AT_panda &&
133  new_data->get_slider_table() == nullptr) {
134  // Maybe we can animate the vertices with hardware.
135  const TransformBlendTable *table = new_data->get_transform_blend_table();
136  if (table != nullptr &&
137  table->get_num_transforms() != 0 &&
139  get_gsg()->get_max_vertex_transforms()) {
140  if (matrix_palette &&
141  table->get_num_transforms() <= get_gsg()->get_max_vertex_transform_indices()) {
142 
143  if (table->get_num_transforms() == table->get_max_simultaneous_transforms()) {
144  // We can support an indexed palette, but since that won't save us
145  // any per-vertex blends, go ahead and do a plain old nonindexed
146  // table instead.
147  animation.set_hardware(table->get_num_transforms(), false);
148 
149  } else {
150  // We can support an indexed palette, and that means we can reduce
151  // the number of blends we have to specify for each vertex.
152  animation.set_hardware(table->get_max_simultaneous_transforms(), true);
153  }
154 
155  } else if (table->get_num_transforms() <=
156  get_gsg()->get_max_vertex_transforms()) {
157  // We can't support an indexed palette, but we have few enough
158  // transforms that we can do a nonindexed table.
159  animation.set_hardware(table->get_num_transforms(), false);
160  }
161  }
162  }
163 
164  CPT(GeomVertexFormat) orig_format = new_data->get_format();
165  CPT(GeomVertexFormat) new_format = munge_format(orig_format, animation);
166 
167  if (new_format == orig_format) {
168  // Trivial case.
169  return new_data;
170  }
171 
172  return new_data->convert_to(new_format);
173 }
174 
175 /**
176  * Converts a Geom and/or its data as necessary.
177  */
178 void StandardMunger::
179 munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data,
180  Thread *) {
181  int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
182 
183  int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
184  if (unsupported_bits != 0) {
185  // Even beyond munging the vertex format, we have to convert the Geom
186  // itself into a new primitive type the GSG can render directly. If we
187  // don't support a strip cut index, it might be faster to just decompose
188  // it rather than draw them one by one.
189  if ((unsupported_bits & Geom::GR_composite_bits) != 0 ||
190  (unsupported_bits & Geom::GR_strip_cut_index) != 0) {
191 
192  // This decomposes everything in the primitive, so that if (for
193  // instance) the primitive contained both strips and fans, but the GSG
194  // didn't support fans, it would decompose the strips too. To handle
195  // this correctly, we'd need a separate decompose_fans() and
196  // decompose_strips() call; but for now, we'll just say it's good
197  // enough. In practice, we don't have any GSG's that can support strips
198  // without also supporting fans.
199  geom = geom->decompose();
200 
201  // Decomposing might produce an indexed Geom, so re-check the
202  // unsupported bits.
203  unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
204  }
205  if ((unsupported_bits & Geom::GR_shade_model_bits) != 0) {
206  // Rotate the vertices to account for different shade-model expectations
207  // (e.g. SM_flat_last_vertex to SM_flat_first_vertex)
208  geom = geom->rotate();
209  }
210  if ((unsupported_bits & Geom::GR_indexed_bits) != 0) {
211  // Convert indexed geometry to nonindexed geometry.
212  PT(Geom) new_geom = geom->make_copy();
213  new_geom->set_vertex_data(vertex_data);
214  new_geom->make_nonindexed(false);
215  geom = new_geom;
216  vertex_data = new_geom->get_vertex_data();
217  }
218  }
219 }
220 
221 /**
222  * Converts a Geom and/or its data as necessary.
223  */
224 void StandardMunger::
225 premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
226  int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
227 
228  int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
229  if (unsupported_bits != 0) {
230  // Even beyond munging the vertex format, we have to convert the Geom
231  // itself into a new primitive type the GSG can render directly. If we
232  // don't support a strip cut index, it might be faster to just decompose
233  // it rather than draw them one by one.
234  if ((unsupported_bits & Geom::GR_composite_bits) != 0 ||
235  (unsupported_bits & Geom::GR_strip_cut_index) != 0) {
236 
237  // This decomposes everything in the primitive, so that if (for
238  // instance) the primitive contained both strips and fans, but the GSG
239  // didn't support fans, it would decompose the strips too. To handle
240  // this correctly, we'd need a separate decompose_fans() and
241  // decompose_strips() call; but for now, we'll just say it's good
242  // enough. In practice, we don't have any GSG's that can support strips
243  // without also supporting fans.
244  geom = geom->decompose();
245 
246  // Decomposing might produce an indexed Geom, so re-check the
247  // unsupported bits.
248  unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
249  }
250  if ((unsupported_bits & Geom::GR_shade_model_bits) != 0) {
251  // Rotate the vertices to account for different shade-model expectations
252  // (e.g. SM_flat_last_vertex to SM_flat_first_vertex)
253  geom = geom->rotate();
254  }
255  if ((unsupported_bits & Geom::GR_indexed_bits) != 0) {
256  // Convert indexed geometry to nonindexed geometry.
257  PT(Geom) new_geom = geom->make_copy();
258  new_geom->set_vertex_data(vertex_data);
259  new_geom->make_nonindexed(false);
260  geom = new_geom;
261  vertex_data = new_geom->get_vertex_data();
262  }
263  }
264 }
265 
266 /**
267  * Called to compare two GeomMungers who are known to be of the same type, for
268  * an apples-to-apples comparison. This will never be called on two pointers
269  * of a different type.
270  */
271 int StandardMunger::
272 compare_to_impl(const GeomMunger *other) const {
273  const StandardMunger *om = (const StandardMunger *)other;
274 
275  if (_munge_color != om->_munge_color) {
276  return (int)_munge_color - (int)om->_munge_color;
277  }
278  if (_munge_color_scale != om->_munge_color_scale) {
279  return (int)_munge_color_scale - (int)om->_munge_color_scale;
280  }
281  if (_munge_color) {
282  int compare = _color.compare_to(om->_color);
283  if (compare != 0) {
284  return compare;
285  }
286  }
287  if (_munge_color_scale) {
288  int compare = _color_scale.compare_to(om->_color_scale);
289  if (compare != 0) {
290  return compare;
291  }
292  }
293  if (_shader_skinning != om->_shader_skinning) {
294  return (int)_shader_skinning - (int)om->_shader_skinning;
295  }
296  if (_auto_shader != om->_auto_shader) {
297  return (int)_auto_shader - (int)om->_auto_shader;
298  }
299  if (_remove_material != om->_remove_material) {
300  return (int)_remove_material - (int)om->_remove_material;
301  }
302 
303  return StateMunger::compare_to_impl(other);
304 }
305 
306 /**
307  * Compares two GeomMungers, considering only whether they would produce a
308  * different answer to munge_format(), munge_data(), or munge_geom(). (They
309  * still might be different in other ways, but if they would produce the same
310  * answer, this function consider them to be the same.)
311  */
312 int StandardMunger::
313 geom_compare_to_impl(const GeomMunger *other) const {
314  const StandardMunger *om = (const StandardMunger *)other;
315 
316  if (_munge_color != om->_munge_color) {
317  return (int)_munge_color - (int)om->_munge_color;
318  }
319  if (_munge_color_scale != om->_munge_color_scale) {
320  return (int)_munge_color_scale - (int)om->_munge_color_scale;
321  }
322  if (_munge_color) {
323  int compare = _color.compare_to(om->_color);
324  if (compare != 0) {
325  return compare;
326  }
327  }
328  if (_munge_color_scale) {
329  int compare = _color_scale.compare_to(om->_color_scale);
330  if (compare != 0) {
331  return compare;
332  }
333  }
334  if (_shader_skinning != om->_shader_skinning) {
335  return (int)_shader_skinning - (int)om->_shader_skinning;
336  }
337 
338  return StateMunger::geom_compare_to_impl(other);
339 }
340 
341 /**
342  * Given an input state, returns the munged state.
343  */
344 CPT(RenderState) StandardMunger::
345 munge_state_impl(const RenderState *state) {
346  CPT(RenderState) munged_state = state;
347 
348  if (_munge_color) {
349  munged_state = munged_state->remove_attrib(ColorAttrib::get_class_slot());
350  munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
351  } else if (_munge_color_scale) {
352  munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
353  }
354 
355  if (_remove_material) {
356  munged_state = munged_state->remove_attrib(MaterialAttrib::get_class_slot());
357  }
358 
359  return munged_state;
360 }
Geom
A container for geometry primitives.
Definition: geom.h:54
Geom::make_copy
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
Definition: geom.cxx:100
Geom::set_vertex_data
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
Definition: geom.cxx:171
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
config_gobj.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ColorScaleAttrib::has_rgb_scale
bool has_rgb_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the RGB components (ignoring alpha),...
Definition: colorScaleAttrib.I:61
StandardMunger::StandardMunger
StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, int num_components, NumericType numeric_type, Contents contents)
The StandardMunger constructor accepts additional parameters that specify the GSG's preferred color f...
Definition: standardMunger.cxx:32
GeomVertexAnimationSpec::get_animation_type
get_animation_type
Returns the type of animation represented by this spec.
Definition: geomVertexAnimationSpec.h:45
ShaderAttrib::auto_shader
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
Definition: shaderAttrib.I:71
ShaderAttrib
Definition: shaderAttrib.h:39
GeomVertexAnimationSpec::set_hardware
void set_hardware(int num_transforms, bool indexed_transforms)
Specifies that vertex animation is to be performed by the graphics hardware (or at least by the graph...
Definition: geomVertexAnimationSpec.I:102
GraphicsStateGuardian::get_supported_geom_rendering
virtual int get_supported_geom_rendering() const
Returns the union of Geom::GeomRendering values that this particular GSG can support directly.
Definition: graphicsStateGuardian.cxx:347
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
Geom::get_geom_rendering
get_geom_rendering
Returns the set of GeomRendering bits that represent the rendering properties required to properly re...
Definition: geom.h:76
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
materialAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ColorScaleAttrib::has_alpha_scale
bool has_alpha_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the alpha component (ignoring RGB),...
Definition: colorScaleAttrib.I:70
displayRegion.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexAnimationSpec
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
Definition: geomVertexAnimationSpec.h:38
ColorScaleAttrib::has_scale
has_scale
Returns true if the ColorScaleAttrib has a non-identity scale, false otherwise (in which case it migh...
Definition: colorScaleAttrib.h:47
GraphicsStateGuardian::get_alpha_scale_via_texture
bool get_alpha_scale_via_texture() const
Returns true if this particular GSG can implement (or would prefer to implement) an alpha scale via a...
Definition: graphicsStateGuardian.I:756
MaterialAttrib
Indicates which, if any, material should be applied to geometry.
Definition: materialAttrib.h:27
standardMunger.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
ColorAttrib::get_color_type
get_color_type
Returns the type of color specified by this ColorAttrib.
Definition: colorAttrib.h:46
LightAttrib::has_any_on_light
bool has_any_on_light() const
Returns true if any light is turned on by the attrib, false otherwise.
Definition: lightAttrib.I:63
MaterialAttrib::get_material
get_material
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated.
Definition: materialAttrib.h:40
TransformBlendTable::get_num_transforms
get_num_transforms
Returns the number of unique VertexTransform objects represented in the table.
Definition: transformBlendTable.h:75
GraphicsStateGuardian::get_color_scale_via_lighting
bool get_color_scale_via_lighting() const
Returns true if this particular GSG can implement (or would prefer to implement) set color and/or col...
Definition: graphicsStateGuardian.I:746
StateMunger
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition: stateMunger.h:26
ColorScaleAttrib
Applies a scale to colors in the scene graph and on vertices.
Definition: colorScaleAttrib.h:27
GraphicsStateGuardianBase
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Definition: graphicsStateGuardianBase.h:110
StandardMunger
Performs some generic munging that is appropriate for all GSG types; for instance,...
Definition: standardMunger.h:31
TransformBlendTable::get_max_simultaneous_transforms
get_max_simultaneous_transforms
Returns the maximum number of unique VertexTransform objects that are applied to any one vertex simul...
Definition: transformBlendTable.h:76
lightAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LightAttrib
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
Definition: lightAttrib.h:30
TextureAttrib
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
StandardMunger::get_gsg
GraphicsStateGuardian * get_gsg() const
Returns a pointer to the GSG that created this munger.
Definition: standardMunger.I:18
ColorAttrib
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
CPT
CPT(GeomVertexData) StandardMunger
Given a source GeomVertexData, converts it as necessary for rendering.
Definition: standardMunger.cxx:113
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
TransformBlendTable
This structure collects together the different combinations of transforms and blend amounts used by a...
Definition: transformBlendTable.h:45
graphicsStateGuardian.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ColorScaleAttrib::get_scale
get_scale
Returns the scale to be applied to colors.
Definition: colorScaleAttrib.h:47
GeomMunger
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50