Panda3D
 All Classes Functions Variables Enumerations
dxGeomMunger9.cxx
00001 // Filename: dxGeomMunger9.cxx
00002 // Created by:  drose (11Mar05)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "dxGeomMunger9.h"
00016 #include "geomVertexReader.h"
00017 #include "geomVertexWriter.h"
00018 #include "config_dxgsg9.h"
00019 
00020 GeomMunger *DXGeomMunger9::_deleted_chain = NULL;
00021 TypeHandle DXGeomMunger9::_type_handle;
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: DXGeomMunger9::Destructor
00025 //       Access: Public, Virtual
00026 //  Description: 
00027 ////////////////////////////////////////////////////////////////////
00028 DXGeomMunger9::
00029 ~DXGeomMunger9() {
00030   if (_reffed_filtered_texture) {
00031     unref_delete(_filtered_texture);
00032     _reffed_filtered_texture = false;
00033   }
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: DXGeomMunger9::wp_callback
00038 //       Access: Public, Virtual
00039 //  Description: This callback is set to be made whenever the
00040 //               associated _texture or _tex_gen attributes are
00041 //               destructed, in which case the GeomMunger is invalid
00042 //               and should no longer be used.
00043 ////////////////////////////////////////////////////////////////////
00044 void DXGeomMunger9::
00045 wp_callback(void *) {
00046   unregister_myself();
00047 
00048   if (_reffed_filtered_texture) {
00049     unref_delete(_filtered_texture);
00050     _reffed_filtered_texture = false;
00051   }
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: DXGeomMunger9::munge_format_impl
00056 //       Access: Protected, Virtual
00057 //  Description: Given a source GeomVertexFormat, converts it if
00058 //               necessary to the appropriate format for rendering.
00059 ////////////////////////////////////////////////////////////////////
00060 CPT(GeomVertexFormat) DXGeomMunger9::
00061 munge_format_impl(const GeomVertexFormat *orig,
00062                   const GeomVertexAnimationSpec &animation) {
00063   if (dxgsg9_cat.is_debug()) {
00064     if (animation.get_animation_type() != AT_none) {
00065       dxgsg9_cat.debug()
00066         << "preparing animation type " << animation << " for " << *orig
00067         << "\n";
00068     }
00069   }
00070   // We have to build a completely new format that includes only the
00071   // appropriate components, in the appropriate order, in just one
00072   // array.
00073   PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
00074   new_format->set_animation(animation);
00075   PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
00076 
00077   const GeomVertexColumn *vertex_type = orig->get_vertex_column();
00078   const GeomVertexColumn *normal_type = orig->get_normal_column();
00079   const GeomVertexColumn *color_type = orig->get_color_column();
00080 
00081   if (vertex_type != (const GeomVertexColumn *)NULL) {
00082     new_array_format->add_column
00083       (InternalName::get_vertex(), 3, NT_float32,
00084        vertex_type->get_contents());
00085     new_format->remove_column(vertex_type->get_name());
00086 
00087   } else {
00088     // If we don't have a vertex type, not much we can do.
00089     return orig;
00090   }
00091 
00092   if (animation.get_animation_type() == AT_hardware &&
00093       animation.get_num_transforms() > 0) {
00094     if (animation.get_num_transforms() > 1) {
00095       // If we want hardware animation, we need to reserve space for the
00096       // blend weights.
00097       new_array_format->add_column
00098         (InternalName::get_transform_weight(), animation.get_num_transforms() - 1,
00099          NT_float32, C_other);
00100     }
00101 
00102     if (animation.get_indexed_transforms()) {
00103       // Also, if we'll be indexing into the transform table, reserve
00104       // space for the index.
00105       new_array_format->add_column
00106         (InternalName::get_transform_index(), 1,
00107          NT_packed_dcba, C_index);
00108     }
00109 
00110     // Make sure the old weights and indices are removed, just in
00111     // case.
00112     new_format->remove_column(InternalName::get_transform_weight());
00113     new_format->remove_column(InternalName::get_transform_index());
00114 
00115     // And we don't need the transform_blend table any more.
00116     new_format->remove_column(InternalName::get_transform_blend());
00117   }
00118 
00119   if (normal_type != (const GeomVertexColumn *)NULL) {
00120     new_array_format->add_column
00121       (InternalName::get_normal(), 3, NT_float32, C_vector);
00122     new_format->remove_column(normal_type->get_name());
00123   }
00124 
00125   if (color_type != (const GeomVertexColumn *)NULL) {
00126     new_array_format->add_column
00127       (InternalName::get_color(), 1, NT_packed_dabc, C_color);
00128     new_format->remove_column(color_type->get_name());
00129   }
00130 
00131   // To support multitexture, we will need to add all of the relevant
00132   // texcoord types, and in the order specified by the TextureAttrib.
00133 
00134   // Now set up each of the active texture coordinate stages--or at
00135   // least those for which we're not generating texture coordinates
00136   // automatically.
00137 
00138   if (_filtered_texture != (TextureAttrib *)NULL) {
00139     int num_stages = _filtered_texture->get_num_on_ff_stages();
00140     vector_int ff_tc_index(num_stages, 0);
00141 
00142     // Be sure we add the texture coordinates in the right order, as
00143     // specified by the attrib.  To ensure this, we first walk through
00144     // the stages of the attrib and get the index numbers in the
00145     // appropriate order.
00146     int si, tc_index;
00147     int max_tc_index = -1;
00148     for (si = 0; si < num_stages; ++si) {
00149       int tc_index = _filtered_texture->get_ff_tc_index(si);
00150       nassertr(tc_index < num_stages, orig);
00151       ff_tc_index[tc_index] = si;
00152       max_tc_index = max(tc_index, max_tc_index);
00153     }
00154 
00155     // Now walk through the texture coordinates in the order they will
00156     // appear on the final geometry.  For each one, get the texture
00157     // coordinate name from the associated stage.
00158     for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) {
00159       si = ff_tc_index[tc_index];
00160       TextureStage *stage = _filtered_texture->get_on_ff_stage(si);
00161       InternalName *name = stage->get_texcoord_name();
00162 
00163       const GeomVertexColumn *texcoord_type = orig->get_column(name);
00164 
00165       if (texcoord_type != (const GeomVertexColumn *)NULL) {
00166         new_array_format->add_column
00167           (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
00168       } else {
00169         // We have to add something as a placeholder, even if the
00170         // texture coordinates aren't defined.
00171         new_array_format->add_column(name, 2, NT_float32, C_texcoord);
00172       }
00173       new_format->remove_column(name);
00174     }
00175   }
00176 
00177   // Now go through the remaining arrays and make sure they are
00178   // tightly packed.  If not, repack them.
00179   for (int i = 0; i < new_format->get_num_arrays(); ++i) {
00180     CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
00181     if (orig_a->count_unused_space() != 0) {
00182       PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
00183       for (int j = 0; j < orig_a->get_num_columns(); ++j) {
00184         const GeomVertexColumn *column = orig_a->get_column(j);
00185         new_a->add_column(column->get_name(), column->get_num_components(),
00186                           column->get_numeric_type(), column->get_contents());
00187       }
00188       new_format->set_array(i, new_a);
00189     }
00190   }
00191 
00192   // Make sure the FVF-style array we just built up is first in the
00193   // list.
00194   new_format->insert_array(0, new_array_format);
00195 
00196   return GeomVertexFormat::register_format(new_format);
00197 }
00198 
00199 ////////////////////////////////////////////////////////////////////
00200 //     Function: DXGeomMunger9::premunge_format_impl
00201 //       Access: Protected, Virtual
00202 //  Description: Given a source GeomVertexFormat, converts it if
00203 //               necessary to the appropriate format for rendering.
00204 ////////////////////////////////////////////////////////////////////
00205 CPT(GeomVertexFormat) DXGeomMunger9::
00206 premunge_format_impl(const GeomVertexFormat *orig) {
00207   // We have to build a completely new format that includes only the
00208   // appropriate components, in the appropriate order, in just one
00209   // array.
00210   PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
00211   PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
00212 
00213   const GeomVertexColumn *vertex_type = orig->get_vertex_column();
00214   const GeomVertexColumn *normal_type = orig->get_normal_column();
00215   const GeomVertexColumn *color_type = orig->get_color_column();
00216 
00217   if (vertex_type != (const GeomVertexColumn *)NULL) {
00218     new_array_format->add_column
00219       (InternalName::get_vertex(), 3, NT_float32,
00220        vertex_type->get_contents());
00221     new_format->remove_column(vertex_type->get_name());
00222 
00223   } else {
00224     // If we don't have a vertex type, not much we can do.
00225     return orig;
00226   }
00227 
00228   if (normal_type != (const GeomVertexColumn *)NULL) {
00229     new_array_format->add_column
00230       (InternalName::get_normal(), 3, NT_float32, C_vector);
00231     new_format->remove_column(normal_type->get_name());
00232   }
00233 
00234   if (color_type != (const GeomVertexColumn *)NULL) {
00235     new_array_format->add_column
00236       (InternalName::get_color(), 1, NT_packed_dabc, C_color);
00237     new_format->remove_column(color_type->get_name());
00238   }
00239 
00240   // To support multitexture, we will need to add all of the relevant
00241   // texcoord types, and in the order specified by the TextureAttrib.
00242 
00243   // Now set up each of the active texture coordinate stages--or at
00244   // least those for which we're not generating texture coordinates
00245   // automatically.
00246 
00247   if (_filtered_texture != (TextureAttrib *)NULL) {
00248     int num_stages = _filtered_texture->get_num_on_ff_stages();
00249     vector_int ff_tc_index(num_stages, 0);
00250 
00251     // Be sure we add the texture coordinates in the right order, as
00252     // specified by the attrib.  To ensure this, we first walk through
00253     // the stages of the attrib and get the index numbers in the
00254     // appropriate order.
00255     int si, tc_index;
00256     int max_tc_index = -1;
00257     for (si = 0; si < num_stages; ++si) {
00258       int tc_index = _filtered_texture->get_ff_tc_index(si);
00259       nassertr(tc_index < num_stages, orig);
00260       ff_tc_index[tc_index] = si;
00261       max_tc_index = max(tc_index, max_tc_index);
00262     }
00263 
00264     // Now walk through the texture coordinates in the order they will
00265     // appear on the final geometry.  For each one, get the texture
00266     // coordinate name from the associated stage.
00267     for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) {
00268       si = ff_tc_index[tc_index];
00269       TextureStage *stage = _filtered_texture->get_on_ff_stage(si);
00270       InternalName *name = stage->get_texcoord_name();
00271 
00272       const GeomVertexColumn *texcoord_type = orig->get_column(name);
00273 
00274       if (texcoord_type != (const GeomVertexColumn *)NULL) {
00275         new_array_format->add_column
00276           (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
00277       } else {
00278         // We have to add something as a placeholder, even if the
00279         // texture coordinates aren't defined.
00280         new_array_format->add_column(name, 2, NT_float32, C_texcoord);
00281       }
00282       new_format->remove_column(name);
00283     }
00284   }
00285 
00286   // Now go through the remaining arrays and make sure they are
00287   // tightly packed.  If not, repack them.
00288   for (int i = 0; i < new_format->get_num_arrays(); ++i) {
00289     CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
00290     if (orig_a->count_unused_space() != 0) {
00291       PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
00292       for (int j = 0; j < orig_a->get_num_columns(); ++j) {
00293         const GeomVertexColumn *column = orig_a->get_column(j);
00294         new_a->add_column(column->get_name(), column->get_num_components(),
00295                           column->get_numeric_type(), column->get_contents());
00296       }
00297       new_format->set_array(i, new_a);
00298     }
00299   }
00300 
00301   // Make sure the FVF-style array we just built up is first in the
00302   // list.
00303   new_format->insert_array(0, new_array_format);
00304 
00305   return GeomVertexFormat::register_format(new_format);
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: DXGeomMunger9::compare_to_impl
00310 //       Access: Protected, Virtual
00311 //  Description: Called to compare two GeomMungers who are known to be
00312 //               of the same type, for an apples-to-apples comparison.
00313 //               This will never be called on two pointers of a
00314 //               different type.
00315 ////////////////////////////////////////////////////////////////////
00316 int DXGeomMunger9::
00317 compare_to_impl(const GeomMunger *other) const {
00318   const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
00319   if (_filtered_texture != om->_filtered_texture) {
00320     return _filtered_texture < om->_filtered_texture ? -1 : 1;
00321   }
00322   if (_tex_gen != om->_tex_gen) {
00323     return _tex_gen < om->_tex_gen ? -1 : 1;
00324   }
00325 
00326   return StandardMunger::compare_to_impl(other);
00327 }
00328 
00329 ////////////////////////////////////////////////////////////////////
00330 //     Function: DXGeomMunger9::geom_compare_to_impl
00331 //       Access: Protected, Virtual
00332 //  Description: Called to compare two GeomMungers who are known to be
00333 //               of the same type, for an apples-to-apples comparison.
00334 //               This will never be called on two pointers of a
00335 //               different type.
00336 ////////////////////////////////////////////////////////////////////
00337 int DXGeomMunger9::
00338 geom_compare_to_impl(const GeomMunger *other) const {
00339   // Unlike GLGeomMunger, we do consider _filtered_texture and
00340   // _tex_gen important for this purpose, since they control the
00341   // number and order of texture coordinates we might put into the
00342   // FVF.
00343   const DXGeomMunger9 *om = DCAST(DXGeomMunger9, other);
00344   if (_filtered_texture != om->_filtered_texture) {
00345     return _filtered_texture < om->_filtered_texture ? -1 : 1;
00346   }
00347   if (_tex_gen != om->_tex_gen) {
00348     return _tex_gen < om->_tex_gen ? -1 : 1;
00349   }
00350 
00351   return StandardMunger::geom_compare_to_impl(other);
00352 }
 All Classes Functions Variables Enumerations