Panda3D
 All Classes Functions Variables Enumerations
dxGeomMunger9.cxx
1 // Filename: dxGeomMunger9.cxx
2 // Created by: drose (11Mar05)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "dxGeomMunger9.h"
16 #include "geomVertexReader.h"
17 #include "geomVertexWriter.h"
18 #include "config_dxgsg9.h"
19 
20 GeomMunger *DXGeomMunger9::_deleted_chain = NULL;
21 TypeHandle DXGeomMunger9::_type_handle;
22 
23 ////////////////////////////////////////////////////////////////////
24 // Function: DXGeomMunger9::Destructor
25 // Access: Public, Virtual
26 // Description:
27 ////////////////////////////////////////////////////////////////////
28 DXGeomMunger9::
29 ~DXGeomMunger9() {
30  if (_reffed_filtered_texture) {
31  unref_delete(_filtered_texture);
32  _reffed_filtered_texture = false;
33  }
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: DXGeomMunger9::wp_callback
38 // Access: Public, Virtual
39 // Description: This callback is set to be made whenever the
40 // associated _texture or _tex_gen attributes are
41 // destructed, in which case the GeomMunger is invalid
42 // and should no longer be used.
43 ////////////////////////////////////////////////////////////////////
44 void DXGeomMunger9::
45 wp_callback(void *) {
46  unregister_myself();
47 
48  if (_reffed_filtered_texture) {
49  unref_delete(_filtered_texture);
50  _reffed_filtered_texture = false;
51  }
52 }
53 
54 ////////////////////////////////////////////////////////////////////
55 // Function: DXGeomMunger9::munge_format_impl
56 // Access: Protected, Virtual
57 // Description: Given a source GeomVertexFormat, converts it if
58 // necessary to the appropriate format for rendering.
59 ////////////////////////////////////////////////////////////////////
60 CPT(GeomVertexFormat) DXGeomMunger9::
61 munge_format_impl(const GeomVertexFormat *orig,
62  const GeomVertexAnimationSpec &animation) {
63  if (dxgsg9_cat.is_debug()) {
64  if (animation.get_animation_type() != AT_none) {
65  dxgsg9_cat.debug()
66  << "preparing animation type " << animation << " for " << *orig
67  << "\n";
68  }
69  }
70  // We have to build a completely new format that includes only the
71  // appropriate components, in the appropriate order, in just one
72  // array.
73  PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
74  new_format->set_animation(animation);
75  PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
76 
77  const GeomVertexColumn *vertex_type = orig->get_vertex_column();
78  const GeomVertexColumn *normal_type = orig->get_normal_column();
79  const GeomVertexColumn *color_type = orig->get_color_column();
80 
81  if (vertex_type != (const GeomVertexColumn *)NULL) {
82  new_array_format->add_column
83  (InternalName::get_vertex(), 3, NT_float32,
84  vertex_type->get_contents());
85  new_format->remove_column(vertex_type->get_name());
86 
87  } else {
88  // If we don't have a vertex type, not much we can do.
89  return orig;
90  }
91 
92  if (animation.get_animation_type() == AT_hardware &&
93  animation.get_num_transforms() > 0) {
94  if (animation.get_num_transforms() > 1) {
95  // If we want hardware animation, we need to reserve space for the
96  // blend weights.
97  new_array_format->add_column
98  (InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
99  NT_float32, C_other);
100  }
101 
102  if (animation.get_indexed_transforms()) {
103  // Also, if we'll be indexing into the transform table, reserve
104  // space for the index.
105  new_array_format->add_column
106  (InternalName::get_transform_index(), 1,
107  NT_packed_dcba, C_index);
108  }
109 
110  // Make sure the old weights and indices are removed, just in
111  // case.
112  new_format->remove_column(InternalName::get_transform_weight());
113  new_format->remove_column(InternalName::get_transform_index());
114 
115  // And we don't need the transform_blend table any more.
116  new_format->remove_column(InternalName::get_transform_blend());
117  }
118 
119  if (normal_type != (const GeomVertexColumn *)NULL) {
120  new_array_format->add_column
121  (InternalName::get_normal(), 3, NT_float32, C_normal);
122  new_format->remove_column(normal_type->get_name());
123  }
124 
125  if (color_type != (const GeomVertexColumn *)NULL) {
126  new_array_format->add_column
127  (InternalName::get_color(), 1, NT_packed_dabc, C_color);
128  new_format->remove_column(color_type->get_name());
129  }
130 
131  // To support multitexture, we will need to add all of the relevant
132  // texcoord types, and in the order specified by the TextureAttrib.
133 
134  // Now set up each of the active texture coordinate stages--or at
135  // least those for which we're not generating texture coordinates
136  // automatically.
137 
138  if (_filtered_texture != (TextureAttrib *)NULL) {
139  int num_stages = _filtered_texture->get_num_on_ff_stages();
140  vector_int ff_tc_index(num_stages, 0);
141 
142  // Be sure we add the texture coordinates in the right order, as
143  // specified by the attrib. To ensure this, we first walk through
144  // the stages of the attrib and get the index numbers in the
145  // appropriate order.
146  int si, tc_index;
147  int max_tc_index = -1;
148  for (si = 0; si < num_stages; ++si) {
149  int tc_index = _filtered_texture->get_ff_tc_index(si);
150  nassertr(tc_index < num_stages, orig);
151  ff_tc_index[tc_index] = si;
152  max_tc_index = max(tc_index, max_tc_index);
153  }
154 
155  // Now walk through the texture coordinates in the order they will
156  // appear on the final geometry. For each one, get the texture
157  // coordinate name from the associated stage.
158  for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) {
159  si = ff_tc_index[tc_index];
160  TextureStage *stage = _filtered_texture->get_on_ff_stage(si);
161  InternalName *name = stage->get_texcoord_name();
162 
163  const GeomVertexColumn *texcoord_type = orig->get_column(name);
164 
165  if (texcoord_type != (const GeomVertexColumn *)NULL) {
166  new_array_format->add_column
167  (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
168  } else {
169  // We have to add something as a placeholder, even if the
170  // texture coordinates aren't defined.
171  new_array_format->add_column(name, 2, NT_float32, C_texcoord);
172  }
173  new_format->remove_column(name);
174  }
175  }
176 
177  // Now go through the remaining arrays and make sure they are
178  // tightly packed. If not, repack them.
179  for (int i = 0; i < new_format->get_num_arrays(); ++i) {
180  CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
181  if (orig_a->count_unused_space() != 0) {
182  PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
183  for (int j = 0; j < orig_a->get_num_columns(); ++j) {
184  const GeomVertexColumn *column = orig_a->get_column(j);
185  new_a->add_column(column->get_name(), column->get_num_components(),
186  column->get_numeric_type(), column->get_contents());
187  }
188  new_format->set_array(i, new_a);
189  }
190  }
191 
192  // Make sure the FVF-style array we just built up is first in the
193  // list.
194  new_format->insert_array(0, new_array_format);
195 
196  return GeomVertexFormat::register_format(new_format);
197 }
198 
199 ////////////////////////////////////////////////////////////////////
200 // Function: DXGeomMunger9::premunge_format_impl
201 // Access: Protected, Virtual
202 // Description: Given a source GeomVertexFormat, converts it if
203 // necessary to the appropriate format for rendering.
204 ////////////////////////////////////////////////////////////////////
205 CPT(GeomVertexFormat) DXGeomMunger9::
206 premunge_format_impl(const GeomVertexFormat *orig) {
207  // We have to build a completely new format that includes only the
208  // appropriate components, in the appropriate order, in just one
209  // array.
210  PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
211  PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
212 
213  const GeomVertexColumn *vertex_type = orig->get_vertex_column();
214  const GeomVertexColumn *normal_type = orig->get_normal_column();
215  const GeomVertexColumn *color_type = orig->get_color_column();
216 
217  if (vertex_type != (const GeomVertexColumn *)NULL) {
218  new_array_format->add_column
219  (InternalName::get_vertex(), 3, NT_float32,
220  vertex_type->get_contents());
221  new_format->remove_column(vertex_type->get_name());
222 
223  } else {
224  // If we don't have a vertex type, not much we can do.
225  return orig;
226  }
227 
228  if (normal_type != (const GeomVertexColumn *)NULL) {
229  new_array_format->add_column
230  (InternalName::get_normal(), 3, NT_float32, C_normal);
231  new_format->remove_column(normal_type->get_name());
232  }
233 
234  if (color_type != (const GeomVertexColumn *)NULL) {
235  new_array_format->add_column
236  (InternalName::get_color(), 1, NT_packed_dabc, C_color);
237  new_format->remove_column(color_type->get_name());
238  }
239 
240  // To support multitexture, we will need to add all of the relevant
241  // texcoord types, and in the order specified by the TextureAttrib.
242 
243  // Now set up each of the active texture coordinate stages--or at
244  // least those for which we're not generating texture coordinates
245  // automatically.
246 
247  if (_filtered_texture != (TextureAttrib *)NULL) {
248  int num_stages = _filtered_texture->get_num_on_ff_stages();
249  vector_int ff_tc_index(num_stages, 0);
250 
251  // Be sure we add the texture coordinates in the right order, as
252  // specified by the attrib. To ensure this, we first walk through
253  // the stages of the attrib and get the index numbers in the
254  // appropriate order.
255  int si, tc_index;
256  int max_tc_index = -1;
257  for (si = 0; si < num_stages; ++si) {
258  int tc_index = _filtered_texture->get_ff_tc_index(si);
259  nassertr(tc_index < num_stages, orig);
260  ff_tc_index[tc_index] = si;
261  max_tc_index = max(tc_index, max_tc_index);
262  }
263 
264  // Now walk through the texture coordinates in the order they will
265  // appear on the final geometry. For each one, get the texture
266  // coordinate name from the associated stage.
267  for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) {
268  si = ff_tc_index[tc_index];
269  TextureStage *stage = _filtered_texture->get_on_ff_stage(si);
270  InternalName *name = stage->get_texcoord_name();
271 
272  const GeomVertexColumn *texcoord_type = orig->get_column(name);
273 
274  if (texcoord_type != (const GeomVertexColumn *)NULL) {
275  new_array_format->add_column
276  (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
277  } else {
278  // We have to add something as a placeholder, even if the
279  // texture coordinates aren't defined.
280  new_array_format->add_column(name, 2, NT_float32, C_texcoord);
281  }
282  new_format->remove_column(name);
283  }
284  }
285 
286  // Now go through the remaining arrays and make sure they are
287  // tightly packed. If not, repack them.
288  for (int i = 0; i < new_format->get_num_arrays(); ++i) {
289  CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
290  if (orig_a->count_unused_space() != 0) {
291  PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
292  for (int j = 0; j < orig_a->get_num_columns(); ++j) {
293  const GeomVertexColumn *column = orig_a->get_column(j);
294  new_a->add_column(column->get_name(), column->get_num_components(),
295  column->get_numeric_type(), column->get_contents());
296  }
297  new_format->set_array(i, new_a);
298  }
299  }
300 
301  // Make sure the FVF-style array we just built up is first in the
302  // list.
303  new_format->insert_array(0, new_array_format);
304 
305  return GeomVertexFormat::register_format(new_format);
306 }
307 
308 ////////////////////////////////////////////////////////////////////
309 // Function: DXGeomMunger9::compare_to_impl
310 // Access: Protected, Virtual
311 // Description: Called to compare two GeomMungers who are known to be
312 // of the same type, for an apples-to-apples comparison.
313 // This will never be called on two pointers of a
314 // different type.
315 ////////////////////////////////////////////////////////////////////
316 int DXGeomMunger9::
317 compare_to_impl(const GeomMunger *other) const {
318  const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
319  if (_filtered_texture != om->_filtered_texture) {
320  return _filtered_texture < om->_filtered_texture ? -1 : 1;
321  }
322  if (_tex_gen != om->_tex_gen) {
323  return _tex_gen < om->_tex_gen ? -1 : 1;
324  }
325 
326  return StandardMunger::compare_to_impl(other);
327 }
328 
329 ////////////////////////////////////////////////////////////////////
330 // Function: DXGeomMunger9::geom_compare_to_impl
331 // Access: Protected, Virtual
332 // Description: Called to compare two GeomMungers who are known to be
333 // of the same type, for an apples-to-apples comparison.
334 // This will never be called on two pointers of a
335 // different type.
336 ////////////////////////////////////////////////////////////////////
337 int DXGeomMunger9::
338 geom_compare_to_impl(const GeomMunger *other) const {
339  // Unlike GLGeomMunger, we do consider _filtered_texture and
340  // _tex_gen important for this purpose, since they control the
341  // number and order of texture coordinates we might put into the
342  // FVF.
343  const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
344  if (_filtered_texture != om->_filtered_texture) {
345  return _filtered_texture < om->_filtered_texture ? -1 : 1;
346  }
347  if (_tex_gen != om->_tex_gen) {
348  return _tex_gen < om->_tex_gen ? -1 : 1;
349  }
350 
351  return StandardMunger::geom_compare_to_impl(other);
352 }
virtual void wp_callback(void *)
This callback is set to be made whenever the associated _texture or _tex_gen attributes are destructe...
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded...
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:57
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
This defines how a single column is interleaved within a vertex array stored within a Geom...
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
Definition: textureAttrib.h:34
InternalName * get_texcoord_name() const
See set_texcoord_name.
Definition: textureStage.I:148
This specialization on GeomMunger finesses vertices for DirectX rendering.
Definition: dxGeomMunger9.h:32
int get_num_values() const
Returns the number of numeric values of the column: the number of distinct numeric values that go int...
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:38