Panda3D
|
00001 // Filename: dxGeomMunger8.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 "dxGeomMunger8.h" 00016 #include "geomVertexReader.h" 00017 #include "geomVertexWriter.h" 00018 #include "config_dxgsg8.h" 00019 00020 GeomMunger *DXGeomMunger8::_deleted_chain = NULL; 00021 TypeHandle DXGeomMunger8::_type_handle; 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: DXGeomMunger8::Destructor 00025 // Access: Public, Virtual 00026 // Description: 00027 //////////////////////////////////////////////////////////////////// 00028 DXGeomMunger8:: 00029 ~DXGeomMunger8() { 00030 if (_reffed_filtered_texture) { 00031 unref_delete(_filtered_texture); 00032 _reffed_filtered_texture = false; 00033 } 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: DXGeomMunger8::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 DXGeomMunger8:: 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: DXGeomMunger8::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) DXGeomMunger8:: 00061 munge_format_impl(const GeomVertexFormat *orig, 00062 const GeomVertexAnimationSpec &animation) { 00063 if (dxgsg8_cat.is_debug()) { 00064 if (animation.get_animation_type() != AT_none) { 00065 dxgsg8_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 // Make sure the FVF-style array we just built up is first in the 00178 // list. 00179 new_format->insert_array(0, new_array_format); 00180 00181 return GeomVertexFormat::register_format(new_format); 00182 } 00183 00184 //////////////////////////////////////////////////////////////////// 00185 // Function: DXGeomMunger8::premunge_format_impl 00186 // Access: Protected, Virtual 00187 // Description: Given a source GeomVertexFormat, converts it if 00188 // necessary to the appropriate format for rendering. 00189 //////////////////////////////////////////////////////////////////// 00190 CPT(GeomVertexFormat) DXGeomMunger8:: 00191 premunge_format_impl(const GeomVertexFormat *orig) { 00192 // We have to build a completely new format that includes only the 00193 // appropriate components, in the appropriate order, in just one 00194 // array. 00195 PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig); 00196 PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat; 00197 00198 const GeomVertexColumn *vertex_type = orig->get_vertex_column(); 00199 const GeomVertexColumn *normal_type = orig->get_normal_column(); 00200 const GeomVertexColumn *color_type = orig->get_color_column(); 00201 00202 if (vertex_type != (const GeomVertexColumn *)NULL) { 00203 new_array_format->add_column 00204 (InternalName::get_vertex(), 3, NT_float32, 00205 vertex_type->get_contents()); 00206 new_format->remove_column(vertex_type->get_name()); 00207 00208 } else { 00209 // If we don't have a vertex type, not much we can do. 00210 return orig; 00211 } 00212 00213 if (normal_type != (const GeomVertexColumn *)NULL) { 00214 new_array_format->add_column 00215 (InternalName::get_normal(), 3, NT_float32, C_vector); 00216 new_format->remove_column(normal_type->get_name()); 00217 } 00218 00219 if (color_type != (const GeomVertexColumn *)NULL) { 00220 new_array_format->add_column 00221 (InternalName::get_color(), 1, NT_packed_dabc, C_color); 00222 new_format->remove_column(color_type->get_name()); 00223 } 00224 00225 // To support multitexture, we will need to add all of the relevant 00226 // texcoord types, and in the order specified by the TextureAttrib. 00227 00228 // Now set up each of the active texture coordinate stages--or at 00229 // least those for which we're not generating texture coordinates 00230 // automatically. 00231 00232 if (_filtered_texture != (TextureAttrib *)NULL) { 00233 int num_stages = _filtered_texture->get_num_on_ff_stages(); 00234 vector_int ff_tc_index(num_stages, 0); 00235 00236 // Be sure we add the texture coordinates in the right order, as 00237 // specified by the attrib. To ensure this, we first walk through 00238 // the stages of the attrib and get the index numbers in the 00239 // appropriate order. 00240 int si, tc_index; 00241 int max_tc_index = -1; 00242 for (si = 0; si < num_stages; ++si) { 00243 int tc_index = _filtered_texture->get_ff_tc_index(si); 00244 nassertr(tc_index < num_stages, orig); 00245 ff_tc_index[tc_index] = si; 00246 max_tc_index = max(tc_index, max_tc_index); 00247 } 00248 00249 // Now walk through the texture coordinates in the order they will 00250 // appear on the final geometry. For each one, get the texture 00251 // coordinate name from the associated stage. 00252 for (tc_index = 0; tc_index <= max_tc_index; ++tc_index) { 00253 si = ff_tc_index[tc_index]; 00254 TextureStage *stage = _filtered_texture->get_on_ff_stage(si); 00255 InternalName *name = stage->get_texcoord_name(); 00256 00257 const GeomVertexColumn *texcoord_type = orig->get_column(name); 00258 00259 if (texcoord_type != (const GeomVertexColumn *)NULL) { 00260 new_array_format->add_column 00261 (name, texcoord_type->get_num_values(), NT_float32, C_texcoord); 00262 } else { 00263 // We have to add something as a placeholder, even if the 00264 // texture coordinates aren't defined. 00265 new_array_format->add_column(name, 2, NT_float32, C_texcoord); 00266 } 00267 new_format->remove_column(name); 00268 } 00269 } 00270 00271 // Make sure the FVF-style array we just built up is first in the 00272 // list. 00273 new_format->insert_array(0, new_array_format); 00274 00275 return GeomVertexFormat::register_format(new_format); 00276 } 00277 00278 //////////////////////////////////////////////////////////////////// 00279 // Function: DXGeomMunger8::compare_to_impl 00280 // Access: Protected, Virtual 00281 // Description: Called to compare two GeomMungers who are known to be 00282 // of the same type, for an apples-to-apples comparison. 00283 // This will never be called on two pointers of a 00284 // different type. 00285 //////////////////////////////////////////////////////////////////// 00286 int DXGeomMunger8:: 00287 compare_to_impl(const GeomMunger *other) const { 00288 const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); 00289 if (_filtered_texture != om->_filtered_texture) { 00290 return _filtered_texture < om->_filtered_texture ? -1 : 1; 00291 } 00292 if (_tex_gen != om->_tex_gen) { 00293 return _tex_gen < om->_tex_gen ? -1 : 1; 00294 } 00295 00296 return StandardMunger::compare_to_impl(other); 00297 } 00298 00299 //////////////////////////////////////////////////////////////////// 00300 // Function: DXGeomMunger8::geom_compare_to_impl 00301 // Access: Protected, Virtual 00302 // Description: Called to compare two GeomMungers who are known to be 00303 // of the same type, for an apples-to-apples comparison. 00304 // This will never be called on two pointers of a 00305 // different type. 00306 //////////////////////////////////////////////////////////////////// 00307 int DXGeomMunger8:: 00308 geom_compare_to_impl(const GeomMunger *other) const { 00309 // Unlike GLGeomMunger, we do consider _filtered_texture and 00310 // _tex_gen important for this purpose, since they control the 00311 // number and order of texture coordinates we might put into the 00312 // FVF. 00313 const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); 00314 if (_filtered_texture != om->_filtered_texture) { 00315 return _filtered_texture < om->_filtered_texture ? -1 : 1; 00316 } 00317 if (_tex_gen != om->_tex_gen) { 00318 return _tex_gen < om->_tex_gen ? -1 : 1; 00319 } 00320 00321 return StandardMunger::geom_compare_to_impl(other); 00322 }