Panda3D

dxGeomMunger9.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 dxGeomMunger9.cxx
10 * @author drose
11 * @date 2005-03-11
12 */
13
14 #include "dxGeomMunger9.h"
15 #include "geomVertexReader.h"
16 #include "geomVertexWriter.h"
17 #include "config_dxgsg9.h"
18
19 GeomMunger *DXGeomMunger9::_deleted_chain = nullptr;
20 TypeHandle DXGeomMunger9::_type_handle;
21
22 /**
23 *
24 */
25 DXGeomMunger9::
26 DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state) :
27 StandardMunger(gsg, state, 1, NT_packed_dabc, C_color),
28 _texture(nullptr),
29 _tex_gen(nullptr)
30 {
31 const TextureAttrib *texture = nullptr;
32 const TexGenAttrib *tex_gen = nullptr;
33 state->get_attrib(texture);
34 state->get_attrib(tex_gen);
35 _texture = texture;
36 _tex_gen = tex_gen;
37
38 if (!gsg->get_color_scale_via_lighting()) {
39 // We might need to munge the colors, if we are overriding the vertex
40 // colors and the GSG can't cheat the color via lighting.
41
42 const ColorAttrib *color_attrib;
43 const ShaderAttrib *shader_attrib;
44 state->get_attrib_def(shader_attrib);
45
46 if (!shader_attrib->auto_shader() &&
47 shader_attrib->get_shader() == nullptr &&
48 state->get_attrib(color_attrib) &&
49 color_attrib->get_color_type() != ColorAttrib::T_vertex) {
50
51 if (color_attrib->get_color_type() == ColorAttrib::T_off) {
52 _color.set(1, 1, 1, 1);
53 } else {
54 _color = color_attrib->get_color();
55 }
56
57 const ColorScaleAttrib *color_scale_attrib;
58 if (state->get_attrib(color_scale_attrib) &&
59 color_scale_attrib->has_scale()) {
60 _color.componentwise_mult(color_scale_attrib->get_scale());
61 }
62 _munge_color = true;
63 _should_munge_state = true;
64 }
65 }
66
67 _filtered_texture = nullptr;
68 _reffed_filtered_texture = false;
69 if (texture != nullptr) {
70 _filtered_texture = texture->filter_to_max(gsg->get_max_texture_stages());
71 if (_filtered_texture != texture) {
72 _filtered_texture->ref();
73 _reffed_filtered_texture = true;
74 }
75 }
76 // Set a callback to unregister ourselves when either the Texture or the
77 // TexGen object gets deleted.
78 _texture.add_callback(this);
79 _tex_gen.add_callback(this);
80 }
81
82 /**
83 *
84 */
85 DXGeomMunger9::
86 ~DXGeomMunger9() {
87 if (_reffed_filtered_texture) {
88 unref_delete(_filtered_texture);
89 _reffed_filtered_texture = false;
90 }
91
92 _texture.remove_callback(this);
93 _tex_gen.remove_callback(this);
94 }
95
96 /**
97 * This callback is set to be made whenever the associated _texture or
98 * _tex_gen attributes are destructed, in which case the GeomMunger is invalid
99 * and should no longer be used.
100 */
101 void DXGeomMunger9::
102 wp_callback(void *) {
103 unregister_myself();
104
105 if (_reffed_filtered_texture) {
106 unref_delete(_filtered_texture);
107 _reffed_filtered_texture = false;
108 }
109 }
110
111 /**
112 * Given a source GeomVertexFormat, converts it if necessary to the
113 * appropriate format for rendering.
114 */
115 CPT(GeomVertexFormat) DXGeomMunger9::
116 munge_format_impl(const GeomVertexFormat *orig,
117 const GeomVertexAnimationSpec &animation) {
118 if (dxgsg9_cat.is_debug()) {
119 if (animation.get_animation_type() != AT_none) {
120 dxgsg9_cat.debug()
121 << "preparing animation type " << animation << " for " << *orig
122 << "\n";
123 }
124 }
125 // We have to build a completely new format that includes only the
126 // appropriate components, in the appropriate order, in just one array.
127 PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
128 new_format->set_animation(animation);
129 PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
130
131 const GeomVertexColumn *vertex_type = orig->get_vertex_column();
132 const GeomVertexColumn *normal_type = orig->get_normal_column();
133 const GeomVertexColumn *color_type = orig->get_color_column();
134
135 if (vertex_type != nullptr) {
136 new_array_format->add_column
137 (InternalName::get_vertex(), 3, NT_float32,
138 vertex_type->get_contents());
139 new_format->remove_column(vertex_type->get_name());
140
141 } else {
142 // If we don't have a vertex type, not much we can do.
143 return orig;
144 }
145
146 if (animation.get_animation_type() == AT_hardware &&
147 animation.get_num_transforms() > 0) {
148 if (animation.get_num_transforms() > 1) {
149 // If we want hardware animation, we need to reserve space for the blend
150 // weights.
151 new_array_format->add_column
152 (InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
153 NT_float32, C_other);
154 }
155
156 if (animation.get_indexed_transforms()) {
157 // Also, if we'll be indexing into the transform table, reserve space
158 // for the index.
159 new_array_format->add_column
160 (InternalName::get_transform_index(), 1,
161 NT_packed_dcba, C_index);
162 }
163
164 // Make sure the old weights and indices are removed, just in case.
165 new_format->remove_column(InternalName::get_transform_weight());
166 new_format->remove_column(InternalName::get_transform_index());
167
168 // And we don't need the transform_blend table any more.
169 new_format->remove_column(InternalName::get_transform_blend());
170 }
171
172 if (normal_type != nullptr) {
173 new_array_format->add_column
174 (InternalName::get_normal(), 3, NT_float32, C_normal);
175 new_format->remove_column(normal_type->get_name());
176 }
177
178 if (color_type != nullptr) {
179 new_array_format->add_column
180 (InternalName::get_color(), 1, NT_packed_dabc, C_color);
181 new_format->remove_column(color_type->get_name());
182 }
183
184 // To support multitexture, we will need to add all of the relevant texcoord
185 // types, and in the order specified by the TextureAttrib.
186
187 // Now set up each of the active texture coordinate stages--or at least
188 // those for which we're not generating texture coordinates automatically.
189
190 if (_filtered_texture != nullptr) {
191 int num_stages = _filtered_texture->get_num_on_ff_stages();
192 vector_int ff_tc_index(num_stages, 0);
193
194 // Be sure we add the texture coordinates in the right order, as specified
195 // by the attrib. To ensure this, we first walk through the stages of the
196 // attrib and get the index numbers in the appropriate order.
197 int si, tc_index;
198 int max_tc_index = -1;
199 for (si = 0; si < num_stages; ++si) {
200 int tc_index = _filtered_texture->get_ff_tc_index(si);
201 nassertr(tc_index < num_stages, orig);
202 ff_tc_index[tc_index] = si;
203 max_tc_index = std::max(tc_index, max_tc_index);
204 }
205
206 // Now walk through the texture coordinates in the order they will appear
207 // on the final geometry. For each one, get the texture coordinate name
208 // from the associated stage.
209 for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) {
210 si = ff_tc_index[tc_index];
211 TextureStage *stage = _filtered_texture->get_on_ff_stage(si);
212 InternalName *name = stage->get_texcoord_name();
213
214 const GeomVertexColumn *texcoord_type = orig->get_column(name);
215
216 if (texcoord_type != nullptr) {
217 new_array_format->add_column
218 (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
219 } else {
220 // We have to add something as a placeholder, even if the texture
221 // coordinates aren't defined.
222 new_array_format->add_column(name, 2, NT_float32, C_texcoord);
223 }
224 new_format->remove_column(name);
225 }
226 }
227
228 // Now go through the remaining arrays and make sure they are tightly
229 // packed. If not, repack them.
230 for (size_t i = 0; i < new_format->get_num_arrays(); ++i) {
231 CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
232 if (orig_a->count_unused_space() != 0) {
233 PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
234 for (int j = 0; j < orig_a->get_num_columns(); ++j) {
235 const GeomVertexColumn *column = orig_a->get_column(j);
236 new_a->add_column(column->get_name(), column->get_num_components(),
237 column->get_numeric_type(), column->get_contents());
238 }
239 new_format->set_array(i, new_a);
240 }
241 }
242
243 // Make sure the FVF-style array we just built up is first in the list.
244 new_format->insert_array(0, new_array_format);
245
246 return GeomVertexFormat::register_format(new_format);
247 }
248
249 /**
250 * Given a source GeomVertexFormat, converts it if necessary to the
251 * appropriate format for rendering.
252 */
253 CPT(GeomVertexFormat) DXGeomMunger9::
254 premunge_format_impl(const GeomVertexFormat *orig) {
255 // We have to build a completely new format that includes only the
256 // appropriate components, in the appropriate order, in just one array.
257 PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
258 PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
259
260 const GeomVertexColumn *vertex_type = orig->get_vertex_column();
261 const GeomVertexColumn *normal_type = orig->get_normal_column();
262 const GeomVertexColumn *color_type = orig->get_color_column();
263
264 if (vertex_type != nullptr) {
265 new_array_format->add_column
266 (InternalName::get_vertex(), 3, NT_float32,
267 vertex_type->get_contents());
268 new_format->remove_column(vertex_type->get_name());
269
270 } else {
271 // If we don't have a vertex type, not much we can do.
272 return orig;
273 }
274
275 if (normal_type != nullptr) {
276 new_array_format->add_column
277 (InternalName::get_normal(), 3, NT_float32, C_normal);
278 new_format->remove_column(normal_type->get_name());
279 }
280
281 if (color_type != nullptr) {
282 new_array_format->add_column
283 (InternalName::get_color(), 1, NT_packed_dabc, C_color);
284 new_format->remove_column(color_type->get_name());
285 }
286
287 // To support multitexture, we will need to add all of the relevant texcoord
288 // types, and in the order specified by the TextureAttrib.
289
290 // Now set up each of the active texture coordinate stages--or at least
291 // those for which we're not generating texture coordinates automatically.
292
293 if (_filtered_texture != nullptr) {
294 int num_stages = _filtered_texture->get_num_on_ff_stages();
295 vector_int ff_tc_index(num_stages, 0);
296
297 // Be sure we add the texture coordinates in the right order, as specified
298 // by the attrib. To ensure this, we first walk through the stages of the
299 // attrib and get the index numbers in the appropriate order.
300 int si, tc_index;
301 int max_tc_index = -1;
302 for (si = 0; si < num_stages; ++si) {
303 int tc_index = _filtered_texture->get_ff_tc_index(si);
304 nassertr(tc_index < num_stages, orig);
305 ff_tc_index[tc_index] = si;
306 max_tc_index = std::max(tc_index, max_tc_index);
307 }
308
309 // Now walk through the texture coordinates in the order they will appear
310 // on the final geometry. For each one, get the texture coordinate name
311 // from the associated stage.
312 for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) {
313 si = ff_tc_index[tc_index];
314 TextureStage *stage = _filtered_texture->get_on_ff_stage(si);
315 InternalName *name = stage->get_texcoord_name();
316
317 const GeomVertexColumn *texcoord_type = orig->get_column(name);
318
319 if (texcoord_type != nullptr) {
320 new_array_format->add_column
321 (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
322 } else {
323 // We have to add something as a placeholder, even if the texture
324 // coordinates aren't defined.
325 new_array_format->add_column(name, 2, NT_float32, C_texcoord);
326 }
327 new_format->remove_column(name);
328 }
329 }
330
331 // Now go through the remaining arrays and make sure they are tightly
332 // packed. If not, repack them.
333 for (size_t i = 0; i < new_format->get_num_arrays(); ++i) {
334 CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
335 if (orig_a->count_unused_space() != 0) {
336 PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
337 for (int j = 0; j < orig_a->get_num_columns(); ++j) {
338 const GeomVertexColumn *column = orig_a->get_column(j);
339 new_a->add_column(column->get_name(), column->get_num_components(),
340 column->get_numeric_type(), column->get_contents());
341 }
342 new_format->set_array(i, new_a);
343 }
344 }
345
346 // Make sure the FVF-style array we just built up is first in the list.
347 new_format->insert_array(0, new_array_format);
348
349 return GeomVertexFormat::register_format(new_format);
350 }
351
352 /**
353 * Called to compare two GeomMungers who are known to be of the same type, for
354 * an apples-to-apples comparison. This will never be called on two pointers
355 * of a different type.
356 */
357 int DXGeomMunger9::
358 compare_to_impl(const GeomMunger *other) const {
359 const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
360 if (_filtered_texture != om->_filtered_texture) {
361 return _filtered_texture < om->_filtered_texture ? -1 : 1;
362 }
363 if (_tex_gen.owner_before(om->_tex_gen)) {
364 return -1;
365 }
366 if (om->_tex_gen.owner_before(_tex_gen)) {
367 return 1;
368 }
369
370 return StandardMunger::compare_to_impl(other);
371 }
372
373 /**
374 * Called to compare two GeomMungers who are known to be of the same type, for
375 * an apples-to-apples comparison. This will never be called on two pointers
376 * of a different type.
377 */
378 int DXGeomMunger9::
379 geom_compare_to_impl(const GeomMunger *other) const {
380 // Unlike GLGeomMunger, we do consider _filtered_texture and _tex_gen
381 // important for this purpose, since they control the number and order of
382 // texture coordinates we might put into the FVF.
383 const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
384 if (_filtered_texture != om->_filtered_texture) {
385 return _filtered_texture < om->_filtered_texture ? -1 : 1;
386 }
387 if (_tex_gen.owner_before(om->_tex_gen)) {
388 return -1;
389 }
390 if (om->_tex_gen.owner_before(_tex_gen)) {
391 return 1;
392 }
393
394 return StandardMunger::geom_compare_to_impl(other);
395 }
ColorAttrib
Indicates what color should be applied to renderable geometry.
Definition: colorAttrib.h:27
ColorAttrib::get_color
get_color
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
Definition: colorAttrib.h:47
ColorAttrib::get_color_type
get_color_type
Returns the type of color specified by this ColorAttrib.
Definition: colorAttrib.h:46
ColorScaleAttrib
Applies a scale to colors in the scene graph and on vertices.
Definition: colorScaleAttrib.h:27
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
ColorScaleAttrib::get_scale
get_scale
Returns the scale to be applied to colors.
Definition: colorScaleAttrib.h:47
DXGeomMunger9
This specialization on GeomMunger finesses vertices for DirectX rendering.
Definition: dxGeomMunger9.h:29
DXGeomMunger9::wp_callback
virtual void wp_callback(void *)
This callback is set to be made whenever the associated _texture or _tex_gen attributes are destructe...
Definition: dxGeomMunger9.cxx:102
GeomMunger
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50
GeomVertexAnimationSpec
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
Definition: geomVertexAnimationSpec.h:38
GeomVertexAnimationSpec::get_animation_type
get_animation_type
Returns the type of animation represented by this spec.
Definition: geomVertexAnimationSpec.h:45
GeomVertexAnimationSpec::get_indexed_transforms
get_indexed_transforms
This is only meaningful for animation_type AT_hardware.
Definition: geomVertexAnimationSpec.h:50
GeomVertexAnimationSpec::get_num_transforms
get_num_transforms
This is only meaningful for animation_type AT_hardware.
Definition: geomVertexAnimationSpec.h:49
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
GeomVertexColumn
This defines how a single column is interleaved within a vertex array stored within a Geom.
Definition: geomVertexColumn.h:37
GeomVertexColumn::get_num_values
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
Definition: geomVertexColumn.I:99
GeomVertexColumn::get_numeric_type
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Definition: geomVertexColumn.I:116
GeomVertexColumn::get_name
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
Definition: geomVertexColumn.I:77
GeomVertexColumn::get_contents
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
Definition: geomVertexColumn.I:124
GeomVertexColumn::get_num_components
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
Definition: geomVertexColumn.I:87
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
GeomVertexFormat::get_normal_column
const GeomVertexColumn * get_normal_column() const
Returns the column definition of the "normal" column, or NULL if there is no such column.
Definition: geomVertexFormat.I:399
GeomVertexFormat::get_vertex_column
const GeomVertexColumn * get_vertex_column() const
Returns the column definition of the "vertex" column, or NULL if there is no such column.
Definition: geomVertexFormat.I:375
GeomVertexFormat::get_color_column
const GeomVertexColumn * get_color_column() const
Returns the column definition of the "color" column, or NULL if there is no such column.
Definition: geomVertexFormat.I:423
GeomVertexFormat::get_column
get_column
Returns the ith column of the specification, across all arrays.
Definition: geomVertexFormat.h:97
GeomVertexFormat::remove_column
void remove_column(const InternalName *name, bool keep_empty_array=false)
Removes the named column from the format, from whichever array it exists in.
Definition: geomVertexFormat.cxx:485
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
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
GraphicsStateGuardian::get_max_texture_stages
get_max_texture_stages
Returns the maximum number of simultaneous textures that may be applied to geometry with multitexturi...
Definition: graphicsStateGuardian.h:181
InternalName
Encodes a string name in a hash table, mapping it to a pointer.
Definition: internalName.h:38
ReferenceCount::ref
void ref() const
Explicitly increments the reference count.
Definition: referenceCount.I:151
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
ShaderAttrib
Definition: shaderAttrib.h:39
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
StandardMunger
Performs some generic munging that is appropriate for all GSG types; for instance,...
Definition: standardMunger.h:31
TexGenAttrib
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Definition: texGenAttrib.h:32
TextureAttrib
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:31
TextureAttrib::get_num_on_ff_stages
get_num_on_ff_stages
Returns the number of on-stages that are relevant to the classic fixed function pipeline.
Definition: textureAttrib.h:58
TextureAttrib::get_on_ff_stage
get_on_ff_stage
Returns the nth stage turned on by the attribute, sorted in render order, including only those releva...
Definition: textureAttrib.h:58
TextureAttrib::get_ff_tc_index
int get_ff_tc_index(int n) const
For each TextureStage listed in get_on_ff_stage(), this returns a unique index number for the texture...
Definition: textureAttrib.I:115
TextureStage
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
TextureStage::get_texcoord_name
get_texcoord_name
See set_texcoord_name.
Definition: textureStage.h:194
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
config_dxgsg9.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CPT
CPT(GeomVertexFormat) DXGeomMunger9
Given a source GeomVertexFormat, converts it if necessary to the appropriate format for rendering.
Definition: dxGeomMunger9.cxx:115
dxGeomMunger9.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
unref_delete
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
Definition: referenceCount.I:344