Panda3D
Loading...
Searching...
No Matches
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"
20#include "lightAttrib.h"
21#include "materialAttrib.h"
22#include "renderState.h"
23
24TypeHandle 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 */
106StandardMunger::
107~StandardMunger() {
108}
109
110/**
111 * Given a source GeomVertexData, converts it as necessary for rendering.
112 */
113CPT(GeomVertexData) StandardMunger::
114munge_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 */
178void StandardMunger::
179munge_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 */
224void StandardMunger::
225premunge_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 */
271int StandardMunger::
272compare_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 */
312int StandardMunger::
313geom_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 */
344CPT(RenderState) StandardMunger::
345munge_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}
Indicates what color should be applied to renderable geometry.
Definition colorAttrib.h:27
get_color_type
Returns the type of color specified by this ColorAttrib.
Definition colorAttrib.h:46
Applies a scale to colors in the scene graph and on vertices.
bool has_alpha_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the alpha component (ignoring RGB),...
has_scale
Returns true if the ColorScaleAttrib has a non-identity scale, false otherwise (in which case it migh...
bool has_rgb_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the RGB components (ignoring alpha),...
get_scale
Returns the scale to be applied to colors.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition geomMunger.h:50
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
get_animation_type
Returns the type of animation represented by this spec.
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...
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This class defines the physical layout of the vertex data stored within a Geom.
A container for geometry primitives.
Definition geom.h:54
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
Definition geom.cxx:100
void set_vertex_data(const GeomVertexData *data)
Replaces the Geom's underlying vertex data table with a completely new table.
Definition geom.cxx:171
get_geom_rendering
Returns the set of GeomRendering bits that represent the rendering properties required to properly re...
Definition geom.h:76
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
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...
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...
virtual int get_supported_geom_rendering() const
Returns the union of Geom::GeomRendering values that this particular GSG can support directly.
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
Definition lightAttrib.h:30
bool has_any_on_light() const
Returns true if any light is turned on by the attrib, false otherwise.
Definition lightAttrib.I:63
Indicates which, if any, material should be applied to geometry.
get_material
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
Performs some generic munging that is appropriate for all GSG types; for instance,...
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...
GraphicsStateGuardian * get_gsg() const
Returns a pointer to the GSG that created this munger.
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition stateMunger.h:26
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
A thread; that is, a lightweight process.
Definition thread.h:46
This structure collects together the different combinations of transforms and blend amounts used by a...
get_max_simultaneous_transforms
Returns the maximum number of unique VertexTransform objects that are applied to any one vertex simul...
get_num_transforms
Returns the number of unique VertexTransform objects represented in the table.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.