Panda3D
Loading...
Searching...
No Matches
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
19GeomMunger *DXGeomMunger9::_deleted_chain = nullptr;
20TypeHandle DXGeomMunger9::_type_handle;
21
22/**
23 *
24 */
25DXGeomMunger9::
26DXGeomMunger9(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 */
85DXGeomMunger9::
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 */
102wp_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 */
115CPT(GeomVertexFormat) DXGeomMunger9::
116munge_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) {
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 */
253CPT(GeomVertexFormat) DXGeomMunger9::
254premunge_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) {
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 */
357int DXGeomMunger9::
358compare_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 */
378int DXGeomMunger9::
379geom_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}
Indicates what color should be applied to renderable geometry.
Definition colorAttrib.h:27
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
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.
has_scale
Returns true if the ColorScaleAttrib has a non-identity scale, false otherwise (in which case it migh...
get_scale
Returns the scale to be applied to colors.
This specialization on GeomMunger finesses vertices for DirectX rendering.
virtual void wp_callback(void *)
This callback is set to be made whenever the associated _texture or _tex_gen attributes are destructe...
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.
get_indexed_transforms
This is only meaningful for animation_type AT_hardware.
get_num_transforms
This is only meaningful for animation_type AT_hardware.
This describes the structure of a single array within a Geom data.
This defines how a single column is interleaved within a vertex array stored within a Geom.
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
This class defines the physical layout of the vertex data stored within a Geom.
const GeomVertexColumn * get_normal_column() const
Returns the column definition of the "normal" column, or NULL if there is no such column.
const GeomVertexColumn * get_vertex_column() const
Returns the column definition of the "vertex" column, or NULL if there is no such column.
const GeomVertexColumn * get_color_column() const
Returns the column definition of the "color" column, or NULL if there is no such column.
get_column
Returns the ith column of the specification, across all arrays.
void remove_column(const InternalName *name, bool keep_empty_array=false)
Removes the named column from the format, from whichever array it exists in.
Encapsulates all the communication with a particular instance of a given rendering backend.
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...
get_max_texture_stages
Returns the maximum number of simultaneous textures that may be applied to geometry with multitexturi...
Encodes a string name in a hash table, mapping it to a pointer.
void ref() const
Explicitly increments the reference count.
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,...
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
get_num_on_ff_stages
Returns the number of on-stages that are relevant to the classic fixed function pipeline.
get_on_ff_stage
Returns the nth stage turned on by the attribute, sorted in render order, including only those releva...
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...
Defines the properties of a named stage of the multitexture pipeline.
get_texcoord_name
See set_texcoord_name.
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.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...