Panda3D
|
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 }