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
19 GeomMunger *DXGeomMunger9::_deleted_chain = nullptr;
20 TypeHandle 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 */
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 */
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) {
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 */
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) {
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::
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 */
378 int 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}
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
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
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
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
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::filter_to_max
ConstPointerTo< TextureAttrib > filter_to_max(int max_texture_stages) const
Returns a new TextureAttrib, very much like this one, but with the number of on_stages reduced to be ...
Definition textureAttrib.cxx:295
TextureStage::get_texcoord_name
get_texcoord_name
See set_texcoord_name.
Definition textureStage.h:198
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.
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