Panda3D
|
00001 // Filename: xFileMaker.cxx 00002 // Created by: drose (19Jun01) 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 "xFileMaker.h" 00016 #include "xFileMesh.h" 00017 #include "xFileMaterial.h" 00018 #include "config_xfile.h" 00019 00020 #include "pnotify.h" 00021 #include "eggGroupNode.h" 00022 #include "eggGroup.h" 00023 #include "eggBin.h" 00024 #include "eggPolysetMaker.h" 00025 #include "eggVertexPool.h" 00026 #include "eggVertex.h" 00027 #include "eggPolygon.h" 00028 #include "eggData.h" 00029 #include "pvector.h" 00030 #include "vector_int.h" 00031 #include "string_utils.h" 00032 #include "datagram.h" 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Function: XFileMaker::Constructor 00036 // Access: Public 00037 // Description: 00038 //////////////////////////////////////////////////////////////////// 00039 XFileMaker:: 00040 XFileMaker() { 00041 _mesh_index = 0; 00042 _x_file = new XFile; 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: XFileMaker::Destructor 00047 // Access: Public 00048 // Description: 00049 //////////////////////////////////////////////////////////////////// 00050 XFileMaker:: 00051 ~XFileMaker() { 00052 } 00053 00054 //////////////////////////////////////////////////////////////////// 00055 // Function: XFileMaker::write 00056 // Access: Public 00057 // Description: Writes the .x file data to the indicated filename; 00058 // returns true on success, false otherwise. 00059 //////////////////////////////////////////////////////////////////// 00060 bool XFileMaker:: 00061 write(const Filename &filename) { 00062 return _x_file->write(filename); 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: XFileMaker::add_tree 00067 // Access: Public 00068 // Description: Adds the egg tree rooted at the indicated node to the 00069 // X structure. This may be somewhat destructive of 00070 // the egg tree. Returns true on success, false on 00071 // failure. 00072 //////////////////////////////////////////////////////////////////// 00073 bool XFileMaker:: 00074 add_tree(EggData *egg_data) { 00075 _meshes.clear(); 00076 00077 // Now collect all the polygons together into polysets. 00078 EggPolysetMaker pmaker; 00079 pmaker.make_bins(egg_data); 00080 00081 // And now we're ready to traverse the egg hierarchy. 00082 if (!recurse_nodes(egg_data, _x_file)) { 00083 return false; 00084 } 00085 00086 // Create X structures for all of the meshes we built up. 00087 Meshes::iterator mi; 00088 for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) { 00089 if (!finalize_mesh((*mi).first, (*mi).second)) { 00090 return false; 00091 } 00092 } 00093 _meshes.clear(); 00094 00095 return true; 00096 } 00097 00098 //////////////////////////////////////////////////////////////////// 00099 // Function: XFileMaker::add_node 00100 // Access: Private 00101 // Description: Adds the node to the DX structure, in whatever form 00102 // it is supported. 00103 //////////////////////////////////////////////////////////////////// 00104 bool XFileMaker:: 00105 add_node(EggNode *egg_node, XFileNode *x_parent) { 00106 if (egg_node->is_of_type(EggBin::get_class_type())) { 00107 return add_bin(DCAST(EggBin, egg_node), x_parent); 00108 00109 } else if (egg_node->is_of_type(EggGroup::get_class_type())) { 00110 return add_group(DCAST(EggGroup, egg_node), x_parent); 00111 00112 } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) { 00113 // A grouping node of some kind. 00114 EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); 00115 00116 if (xfile_one_mesh) { 00117 // Don't create any additional frames representing the egg 00118 // hierarchy. 00119 if (!recurse_nodes(egg_group, x_parent)) { 00120 return false; 00121 } 00122 00123 } else { 00124 // Create a Frame for each EggGroup. 00125 XFileDataNode *x_frame = x_parent->add_Frame(egg_group->get_name()); 00126 00127 if (!recurse_nodes(egg_group, x_frame)) { 00128 return false; 00129 } 00130 } 00131 00132 return true; 00133 } 00134 00135 // Some unsupported node type. Ignore it. 00136 return true; 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: XFileMaker::add_group 00141 // Access: Private 00142 // Description: Adds a frame for the indicated group node. 00143 //////////////////////////////////////////////////////////////////// 00144 bool XFileMaker:: 00145 add_group(EggGroup *egg_group, XFileNode *x_parent) { 00146 if (xfile_one_mesh) { 00147 // Don't create any additional frames representing the egg 00148 // hierarchy. 00149 if (!recurse_nodes(egg_group, x_parent)) { 00150 return false; 00151 } 00152 00153 } else { 00154 // Create a frame for each EggGroup. 00155 XFileDataNode *x_frame = x_parent->add_Frame(egg_group->get_name()); 00156 00157 // Set the transform on the frame, if we have one. 00158 if (egg_group->has_transform()) { 00159 x_frame->add_FrameTransformMatrix(egg_group->get_transform3d()); 00160 } 00161 00162 if (!recurse_nodes(egg_group, x_frame)) { 00163 return false; 00164 } 00165 } 00166 00167 return true; 00168 } 00169 00170 //////////////////////////////////////////////////////////////////// 00171 // Function: XFileMaker::add_bin 00172 // Access: Private 00173 // Description: Determines what kind of object needs to be added for 00174 // the indicated bin node. 00175 //////////////////////////////////////////////////////////////////// 00176 bool XFileMaker:: 00177 add_bin(EggBin *egg_bin, XFileNode *x_parent) { 00178 switch (egg_bin->get_bin_number()) { 00179 case EggPolysetMaker::BN_polyset: 00180 return add_polyset(egg_bin, x_parent); 00181 } 00182 00183 xfile_cat.error() 00184 << "Unexpected bin type " << egg_bin->get_bin_number() << "\n"; 00185 return false; 00186 } 00187 00188 //////////////////////////////////////////////////////////////////// 00189 // Function: XFileMaker::add_polyset 00190 // Access: Private 00191 // Description: Adds a mesh object corresponding to the collection of 00192 // polygons within the indicated bin. 00193 //////////////////////////////////////////////////////////////////// 00194 bool XFileMaker:: 00195 add_polyset(EggBin *egg_bin, XFileNode *x_parent) { 00196 // Make sure that all our polygons are reasonable. 00197 egg_bin->remove_invalid_primitives(true); 00198 00199 XFileMesh *mesh = get_mesh(x_parent); 00200 00201 EggGroupNode::iterator ci; 00202 for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) { 00203 EggPolygon *poly; 00204 DCAST_INTO_R(poly, *ci, false); 00205 00206 mesh->add_polygon(poly); 00207 } 00208 00209 return true; 00210 } 00211 00212 00213 //////////////////////////////////////////////////////////////////// 00214 // Function: XFileMaker::recurse_nodes 00215 // Access: Private 00216 // Description: Adds each child of the indicated Node as a child of 00217 // the indicated DX object. 00218 //////////////////////////////////////////////////////////////////// 00219 bool XFileMaker:: 00220 recurse_nodes(EggGroupNode *egg_node, XFileNode *x_parent) { 00221 EggGroupNode::iterator ci; 00222 for (ci = egg_node->begin(); ci != egg_node->end(); ++ci) { 00223 EggNode *child = (*ci); 00224 if (!add_node(child, x_parent)) { 00225 return false; 00226 } 00227 } 00228 00229 return true; 00230 } 00231 00232 //////////////////////////////////////////////////////////////////// 00233 // Function: XFileMaker::get_mesh 00234 // Access: Private 00235 // Description: Returns a suitable XFileMesh object for creating 00236 // meshes within the indicated x_parent object. 00237 //////////////////////////////////////////////////////////////////// 00238 XFileMesh *XFileMaker:: 00239 get_mesh(XFileNode *x_parent) { 00240 Meshes::iterator mi = _meshes.find(x_parent); 00241 if (mi != _meshes.end()) { 00242 // We've already started working on this x_parent before; use the 00243 // same mesh object. 00244 return (*mi).second; 00245 } 00246 00247 // We haven't seen this x_parent before; create a new mesh object. 00248 XFileMesh *mesh = new XFileMesh; 00249 _meshes.insert(Meshes::value_type(x_parent, mesh)); 00250 return mesh; 00251 } 00252 00253 00254 //////////////////////////////////////////////////////////////////// 00255 // Function: XFileMaker::finalize_mesh 00256 // Access: Private 00257 // Description: Creates the actual X structures corresponding to 00258 // the indicated XFileMesh object. 00259 //////////////////////////////////////////////////////////////////// 00260 bool XFileMaker:: 00261 finalize_mesh(XFileNode *x_parent, XFileMesh *mesh) { 00262 // Get a unique number for each mesh. 00263 _mesh_index++; 00264 string mesh_index = format_string(_mesh_index); 00265 00266 // Finally, create the Mesh object. 00267 mesh->make_x_mesh(x_parent, mesh_index); 00268 00269 return true; 00270 }