diff --git a/pandatool/src/eggbase/eggFilter.cxx b/pandatool/src/eggbase/eggFilter.cxx index a8f8597b02..7b597f06a0 100644 --- a/pandatool/src/eggbase/eggFilter.cxx +++ b/pandatool/src/eggbase/eggFilter.cxx @@ -55,7 +55,7 @@ EggFilter(bool allow_last_param, bool allow_stdout) : //////////////////////////////////////////////////////////////////// bool EggFilter:: handle_args(ProgramBase::Args &args) { - if (!check_last_arg(args, 0)) { + if (!check_last_arg(args, 1)) { return false; } diff --git a/pandatool/src/eggbase/eggReader.cxx b/pandatool/src/eggbase/eggReader.cxx index 5ed5d66b51..da4636d88c 100644 --- a/pandatool/src/eggbase/eggReader.cxx +++ b/pandatool/src/eggbase/eggReader.cxx @@ -54,6 +54,11 @@ EggReader() { // program. If the user specifies one of the options on // the command line, the textures will be copied and // converted as each egg file is read. +// +// Note that if you call this function to add these +// options, you must call copy_textures() at the +// appropriate point before or during processing to +// execute the options if the user specified them. //////////////////////////////////////////////////////////////////// void EggReader:: add_texture_options() { @@ -153,10 +158,6 @@ handle_args(ProgramBase::Args &args) { //////////////////////////////////////////////////////////////////// bool EggReader:: post_command_line() { - if (!copy_textures()) { - exit(1); - } - return EggBase::post_command_line(); } diff --git a/pandatool/src/eggbase/eggReader.h b/pandatool/src/eggbase/eggReader.h index aadd639367..5f89f45a4f 100644 --- a/pandatool/src/eggbase/eggReader.h +++ b/pandatool/src/eggbase/eggReader.h @@ -43,10 +43,12 @@ protected: virtual bool handle_args(Args &args); virtual bool post_command_line(); -private: bool copy_textures(); +protected: bool _force_complete; + +private: Filename _tex_dirname; bool _got_tex_dirname; string _tex_extension; diff --git a/pandatool/src/eggprogs/eggTrans.cxx b/pandatool/src/eggprogs/eggTrans.cxx index 0581a51e7d..0e4722c28d 100644 --- a/pandatool/src/eggprogs/eggTrans.cxx +++ b/pandatool/src/eggprogs/eggTrans.cxx @@ -112,6 +112,10 @@ run() { uniquifier.uniquify(&_data); } + if (!copy_textures()) { + exit(1); + } + write_egg_file(); } diff --git a/pandatool/src/ptloader/config_ptloader.cxx b/pandatool/src/ptloader/config_ptloader.cxx index ed512a109f..9b101aeed4 100644 --- a/pandatool/src/ptloader/config_ptloader.cxx +++ b/pandatool/src/ptloader/config_ptloader.cxx @@ -25,6 +25,7 @@ #include "lwoToEggConverter.h" #ifdef HAVE_DX +#include "config_xfile.h" #include "xFileToEggConverter.h" #endif @@ -67,6 +68,7 @@ init_libptloader() { reg->register_type(new LoaderFileTypePandatool(lwo)); #ifdef HAVE_DX + init_libxfile(); XFileToEggConverter *xfile = new XFileToEggConverter; reg->register_type(new LoaderFileTypePandatool(xfile)); #endif diff --git a/pandatool/src/xfile/Sources.pp b/pandatool/src/xfile/Sources.pp index 9fa953c7ec..989a1d99f6 100644 --- a/pandatool/src/xfile/Sources.pp +++ b/pandatool/src/xfile/Sources.pp @@ -14,6 +14,7 @@ d3dxof.lib #define SOURCES \ + config_xfile.cxx config_xfile.h \ xFileFace.cxx xFileFace.h \ xFileMaker.cxx xFileMaker.h \ xFileMaterial.cxx xFileMaterial.h \ diff --git a/pandatool/src/xfile/config_xfile.cxx b/pandatool/src/xfile/config_xfile.cxx new file mode 100644 index 0000000000..e2c54f59d7 --- /dev/null +++ b/pandatool/src/xfile/config_xfile.cxx @@ -0,0 +1,52 @@ +// Filename: config_xfile.cxx +// Created by: drose (24Aug00) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "config_xfile.h" + +#include + +Configure(config_xfile); +NotifyCategoryDef(xfile, ""); + +// This is set true, typically by the user's command-line options, to +// indicate that when a X file is generated it should include all +// geometry in one big mesh, instead of preserving the hierarchy +// from the source egg file. +bool xfile_one_mesh = false; + +ConfigureFn(config_xfile) { + init_libxfile(); +} + +//////////////////////////////////////////////////////////////////// +// Function: init_libxfile +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libxfile() { + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; +} + diff --git a/pandatool/src/xfile/config_xfile.h b/pandatool/src/xfile/config_xfile.h new file mode 100644 index 0000000000..8bb019bd7d --- /dev/null +++ b/pandatool/src/xfile/config_xfile.h @@ -0,0 +1,32 @@ +// Filename: config_xfile.h +// Created by: drose (22Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef CONFIG_XFILE_H +#define CONFIG_XFILE_H + +#include "pandatoolbase.h" + +#include "notifyCategoryProxy.h" + +NotifyCategoryDeclNoExport(xfile); + +extern bool xfile_one_mesh; + +extern void init_libxfile(); + +#endif diff --git a/pandatool/src/xfile/xFileMaker.cxx b/pandatool/src/xfile/xFileMaker.cxx index 00f23b298e..11d7cd0bc1 100644 --- a/pandatool/src/xfile/xFileMaker.cxx +++ b/pandatool/src/xfile/xFileMaker.cxx @@ -20,6 +20,7 @@ #include "xFileMesh.h" #include "xFileMaterial.h" #include "xFileTemplates.h" +#include "config_xfile.h" #include "notify.h" #include "eggGroupNode.h" @@ -99,12 +100,14 @@ open(const Filename &filename) { &TID_D3DRMColorRGB, &TID_D3DRMIndexedColor, &TID_D3DRMTextureFilename, + &TID_D3DRMMatrix4x4, &TID_D3DRMMaterial, &TID_D3DRMMeshFace, &TID_D3DRMMesh, &TID_D3DRMMeshNormals, &TID_D3DRMMeshTextureCoords, &TID_D3DRMMeshMaterialList, + &TID_D3DRMFrameTransformMatrix, &TID_D3DRMFrame, }; static const int num_temps = sizeof(temps) / sizeof(temps[0]); @@ -145,12 +148,24 @@ close() { //////////////////////////////////////////////////////////////////// bool XFileMaker:: add_tree(EggData &egg_data) { + _meshes.clear(); + // Now collect all the polygons together into polysets. EggPolysetMaker pmaker; int num_bins = pmaker.make_bins(&egg_data); // And now we're ready to traverse the egg hierarchy. - return recurse_nodes(&egg_data, NULL); + if (!recurse_nodes(&egg_data, NULL)) { + return false; + } + + // Make sure we finalize any meshes in the root. + if (!finalize_mesh(NULL)) { + return false; + } + + nassertr(_meshes.empty(), false); + return true; } //////////////////////////////////////////////////////////////////// @@ -171,17 +186,28 @@ add_node(EggNode *egg_node, LPDIRECTXFILEDATA dx_parent) { // A grouping node of some kind. EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node); LPDIRECTXFILEDATA obj; - if (!create_frame(obj, egg_group->get_name())) { - return false; - } + + if (xfile_one_mesh) { + // Don't create any additional frames representing the egg + // hierarchy. + if (!recurse_nodes(egg_group, dx_parent)) { + return false; + } + + } else { + // Create a frame for each EggGroup. + if (!create_frame(obj, egg_group->get_name())) { + return false; + } - if (!recurse_nodes(egg_group, obj)) { - obj->Release(); - return false; - } - - if (!attach_and_release(obj, dx_parent)) { - return false; + if (!recurse_nodes(egg_group, obj)) { + obj->Release(); + return false; + } + + if (!attach_and_release(obj, dx_parent)) { + return false; + } } return true; @@ -198,18 +224,33 @@ add_node(EggNode *egg_node, LPDIRECTXFILEDATA dx_parent) { //////////////////////////////////////////////////////////////////// bool XFileMaker:: add_group(EggGroup *egg_group, LPDIRECTXFILEDATA dx_parent) { - LPDIRECTXFILEDATA obj; - if (!create_frame(obj, egg_group->get_name())) { - return false; - } + if (xfile_one_mesh) { + // Don't create any additional frames representing the egg + // hierarchy. + if (!recurse_nodes(egg_group, dx_parent)) { + return false; + } - if (!recurse_nodes(egg_group, obj)) { - obj->Release(); - return false; - } + } else { + // Create a frame for each EggGroup. + LPDIRECTXFILEDATA obj; + if (!create_frame(obj, egg_group->get_name())) { + return false; + } - if (!attach_and_release(obj, dx_parent)) { - return false; + // Set the transform on the frame, if we have one. + if (egg_group->has_transform()) { + add_frame_transform(obj, LCAST(float, egg_group->get_transform())); + } + + if (!recurse_nodes(egg_group, obj)) { + obj->Release(); + return false; + } + + if (!attach_and_release(obj, dx_parent)) { + return false; + } } return true; @@ -228,7 +269,8 @@ add_bin(EggBin *egg_bin, LPDIRECTXFILEDATA dx_parent) { return add_polyset(egg_bin, dx_parent); } - cerr << "Unexpected bin type " << egg_bin->get_bin_number() << "\n"; + xfile_cat.error() + << "Unexpected bin type " << egg_bin->get_bin_number() << "\n"; return false; } @@ -243,121 +285,19 @@ add_polyset(EggBin *egg_bin, LPDIRECTXFILEDATA dx_parent) { // Make sure that all our polygons are reasonable. egg_bin->remove_invalid_primitives(); - XFileMesh mesh; + XFileMesh *mesh = get_mesh(dx_parent); EggGroupNode::iterator ci; for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) { EggPolygon *poly; DCAST_INTO_R(poly, *ci, false); - mesh.add_polygon(poly); + mesh->add_polygon(poly); } - // Get a unique number for each mesh. - _mesh_index++; - string mesh_index = format_string(_mesh_index); - - // Finally, create the Mesh object. - Datagram raw_data; - mesh.make_mesh_data(raw_data); - - LPDIRECTXFILEDATA xobj; - if (!create_object(xobj, TID_D3DRMMesh, "mesh" + mesh_index, raw_data)) { - return false; - } - - if (mesh.has_normals()) { - // Tack on normals. - LPDIRECTXFILEDATA xnormals; - mesh.make_normal_data(raw_data); - if (!create_object(xnormals, TID_D3DRMMeshNormals, "norms" + mesh_index, - raw_data)) { - return false; - } - if (!attach_and_release(xnormals, xobj)) { - return false; - } - } - - if (mesh.has_colors()) { - // Tack on colors. - LPDIRECTXFILEDATA xcolors; - mesh.make_color_data(raw_data); - if (!create_object(xcolors, TID_D3DRMMeshVertexColors, - "colors" + mesh_index, raw_data)) { - return false; - } - if (!attach_and_release(xcolors, xobj)) { - return false; - } - } - - if (mesh.has_uvs()) { - // Tack on texture coordinates. - LPDIRECTXFILEDATA xuvs; - mesh.make_uv_data(raw_data); - if (!create_object(xuvs, TID_D3DRMMeshTextureCoords, - "uvs" + mesh_index, raw_data)) { - return false; - } - if (!attach_and_release(xuvs, xobj)) { - return false; - } - } - - if (mesh.has_materials()) { - // Tack on material definitions. - LPDIRECTXFILEDATA xmaterial_list; - mesh.make_material_list_data(raw_data); - if (!create_object(xmaterial_list, TID_D3DRMMeshMaterialList, - "materials" + mesh_index, raw_data)) { - return false; - } - - // Now we need to iterate through the list of Materials - // themselves, and add *these* as children of the material list. - int num_materials = mesh.get_num_materials(); - for (int i = 0; i < num_materials; i++) { - XFileMaterial *material = mesh.get_material(i); - LPDIRECTXFILEDATA xmaterial; - material->make_material_data(raw_data); - if (!create_object(xmaterial, TID_D3DRMMaterial, - "material" + mesh_index + "_" + format_string(i), - raw_data)) { - return false; - } - - // Also, if the Material has a texture map, we must add *this* - // as a child of the material. What a weird system. - if (material->has_texture()) { - LPDIRECTXFILEDATA xtexture; - material->make_texture_data(raw_data); - if (!create_object(xtexture, TID_D3DRMTextureFilename, - "texture" + mesh_index + "_" + format_string(i), - raw_data)) { - return false; - } - - if (!attach_and_release(xtexture, xmaterial)) { - return false; - } - } - - if (!attach_and_release(xmaterial, xmaterial_list)) { - return false; - } - } - - if (!attach_and_release(xmaterial_list, xobj)) { - return false; - } - } - - if (!attach_and_release(xobj, dx_parent)) { - return false; - } return true; } + //////////////////////////////////////////////////////////////////// // Function: XFileMaker::recurse_nodes @@ -418,6 +358,28 @@ create_frame(LPDIRECTXFILEDATA &obj, const string &name) { return create_object(obj, TID_D3DRMFrame, name, Datagram()); } +//////////////////////////////////////////////////////////////////// +// Function: XFileMaker::add_frame_transform +// Access: Private +// Description: Adds a transformation matrix to the indicated frame. +//////////////////////////////////////////////////////////////////// +bool XFileMaker:: +add_frame_transform(LPDIRECTXFILEDATA obj, const LMatrix4f &mat) { + Datagram raw_data; + mat.write_datagram(raw_data); + + LPDIRECTXFILEDATA xtransform; + if (!create_object(xtransform, TID_D3DRMFrameTransformMatrix, + "transform", raw_data)) { + return false; + } + if (!attach_and_release(xtransform, obj)) { + return false; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: XFileMaker::attach_and_release // Access: Private @@ -428,6 +390,12 @@ bool XFileMaker:: attach_and_release(LPDIRECTXFILEDATA obj, LPDIRECTXFILEDATA dx_parent) { HRESULT hr; + // First, make sure we don't have an outstanding mesh for this + // object. + if (!finalize_mesh(obj)) { + return false; + } + if (dx_parent == NULL) { // No parent; it's a toplevel object. hr = _dx_file_save->SaveData(obj); @@ -471,3 +439,148 @@ make_nice_name(const string &str) { return result; } + +//////////////////////////////////////////////////////////////////// +// Function: XFileMaker::get_mesh +// Access: Private +// Description: Returns a suitable XFileMesh object for creating +// meshes within the indicated dx_parent object. +//////////////////////////////////////////////////////////////////// +XFileMesh *XFileMaker:: +get_mesh(LPDIRECTXFILEDATA dx_parent) { + Meshes::iterator mi = _meshes.find(dx_parent); + if (mi != _meshes.end()) { + // We've already started working on this dx_parent before; use the + // same mesh object. + return (*mi).second; + } + + // We haven't seen this dx_parent before; create a new mesh object. + XFileMesh *mesh = new XFileMesh; + _meshes.insert(Meshes::value_type(dx_parent, mesh)); + return mesh; +} + + +//////////////////////////////////////////////////////////////////// +// Function: XFileMaker::finalize_mesh +// Access: Private +// Description: Creates the actual DX mesh object corresponding to +// the indicated dx_parent object. +//////////////////////////////////////////////////////////////////// +bool XFileMaker:: +finalize_mesh(LPDIRECTXFILEDATA dx_parent) { + Meshes::iterator mi = _meshes.find(dx_parent); + if (mi == _meshes.end()) { + // We haven't got a mesh for this object; do nothing. + return true; + } + + XFileMesh *mesh = (*mi).second; + _meshes.erase(mi); + + // Get a unique number for each mesh. + _mesh_index++; + string mesh_index = format_string(_mesh_index); + + // Finally, create the Mesh object. + Datagram raw_data; + mesh->make_mesh_data(raw_data); + + LPDIRECTXFILEDATA xobj; + if (!create_object(xobj, TID_D3DRMMesh, "mesh" + mesh_index, raw_data)) { + return false; + } + + if (mesh->has_normals()) { + // Tack on normals. + LPDIRECTXFILEDATA xnormals; + mesh->make_normal_data(raw_data); + if (!create_object(xnormals, TID_D3DRMMeshNormals, "norms" + mesh_index, + raw_data)) { + return false; + } + if (!attach_and_release(xnormals, xobj)) { + return false; + } + } + + if (mesh->has_colors()) { + // Tack on colors. + LPDIRECTXFILEDATA xcolors; + mesh->make_color_data(raw_data); + if (!create_object(xcolors, TID_D3DRMMeshVertexColors, + "colors" + mesh_index, raw_data)) { + return false; + } + if (!attach_and_release(xcolors, xobj)) { + return false; + } + } + + if (mesh->has_uvs()) { + // Tack on texture coordinates. + LPDIRECTXFILEDATA xuvs; + mesh->make_uv_data(raw_data); + if (!create_object(xuvs, TID_D3DRMMeshTextureCoords, + "uvs" + mesh_index, raw_data)) { + return false; + } + if (!attach_and_release(xuvs, xobj)) { + return false; + } + } + + if (mesh->has_materials()) { + // Tack on material definitions. + LPDIRECTXFILEDATA xmaterial_list; + mesh->make_material_list_data(raw_data); + if (!create_object(xmaterial_list, TID_D3DRMMeshMaterialList, + "materials" + mesh_index, raw_data)) { + return false; + } + + // Now we need to iterate through the list of Materials + // themselves, and add *these* as children of the material list. + int num_materials = mesh->get_num_materials(); + for (int i = 0; i < num_materials; i++) { + XFileMaterial *material = mesh->get_material(i); + LPDIRECTXFILEDATA xmaterial; + material->make_material_data(raw_data); + if (!create_object(xmaterial, TID_D3DRMMaterial, + "material" + mesh_index + "_" + format_string(i), + raw_data)) { + return false; + } + + // Also, if the Material has a texture map, we must add *this* + // as a child of the material. What a weird system. + if (material->has_texture()) { + LPDIRECTXFILEDATA xtexture; + material->make_texture_data(raw_data); + if (!create_object(xtexture, TID_D3DRMTextureFilename, + "texture" + mesh_index + "_" + format_string(i), + raw_data)) { + return false; + } + + if (!attach_and_release(xtexture, xmaterial)) { + return false; + } + } + + if (!attach_and_release(xmaterial, xmaterial_list)) { + return false; + } + } + + if (!attach_and_release(xmaterial_list, xobj)) { + return false; + } + } + + if (!attach_and_release(xobj, dx_parent)) { + return false; + } + return true; +} diff --git a/pandatool/src/xfile/xFileMaker.h b/pandatool/src/xfile/xFileMaker.h index edbb465aeb..9c6216f4cd 100644 --- a/pandatool/src/xfile/xFileMaker.h +++ b/pandatool/src/xfile/xFileMaker.h @@ -19,9 +19,11 @@ #ifndef XFILEMAKER_H #define XFILEMAKER_H -#include +#include "pandatoolbase.h" -#include +#include "filename.h" +#include "pmap.h" +#include "luse.h" #define WIN32_LEAN_AND_MEAN #include @@ -37,6 +39,7 @@ class EggBin; class EggData; class EggVertexPool; class Datagram; +class XFileMesh; //////////////////////////////////////////////////////////////////// // Class : XFileMaker @@ -64,14 +67,22 @@ private: bool create_object(LPDIRECTXFILEDATA &obj, REFGUID template_id, const string &name, const Datagram &dg); bool create_frame(LPDIRECTXFILEDATA &obj, const string &name); + bool add_frame_transform(LPDIRECTXFILEDATA obj, const LMatrix4f &mat); + bool attach_and_release(LPDIRECTXFILEDATA obj, LPDIRECTXFILEDATA dx_parent); static string make_nice_name(const string &str); + XFileMesh *get_mesh(LPDIRECTXFILEDATA dx_parent); + bool finalize_mesh(LPDIRECTXFILEDATA dx_parent); + LPDIRECTXFILE _dx_file; LPDIRECTXFILESAVEOBJECT _dx_file_save; int _mesh_index; + + typedef pmap Meshes; + Meshes _meshes; }; #endif diff --git a/pandatool/src/xfile/xFileMesh.cxx b/pandatool/src/xfile/xFileMesh.cxx index 61da1246d0..64046c7c9f 100644 --- a/pandatool/src/xfile/xFileMesh.cxx +++ b/pandatool/src/xfile/xFileMesh.cxx @@ -86,6 +86,11 @@ clear() { _unique_vertices.clear(); _unique_normals.clear(); _unique_materials.clear(); + + _has_normals = false; + _has_colors = false; + _has_uvs = false; + _has_materials = false; } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/xfile/xFileMesh.h b/pandatool/src/xfile/xFileMesh.h index 2d760f3888..9621ab7030 100644 --- a/pandatool/src/xfile/xFileMesh.h +++ b/pandatool/src/xfile/xFileMesh.h @@ -91,7 +91,6 @@ private: Materials _materials; Faces _faces; -private: typedef pmap > UniqueVertices; typedef pmap > UniqueNormals; typedef pmap > UniqueMaterials; diff --git a/pandatool/src/xfile/xFileNormal.cxx b/pandatool/src/xfile/xFileNormal.cxx index 5719630d4f..a3f7a8b1d2 100644 --- a/pandatool/src/xfile/xFileNormal.cxx +++ b/pandatool/src/xfile/xFileNormal.cxx @@ -19,6 +19,7 @@ #include "xFileNormal.h" #include "eggVertex.h" #include "eggPrimitive.h" +#include "config_xfile.h" //////////////////////////////////////////////////////////////////// // Function: XFileNormal::Constructor @@ -38,11 +39,24 @@ XFileNormal() { //////////////////////////////////////////////////////////////////// void XFileNormal:: set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim) { - if (egg_vertex->has_normal()) { - _normal = LCAST(float, egg_vertex->get_normal()); - _has_normal = true; - } else if (egg_prim->has_normal()) { - _normal = LCAST(float, egg_prim->get_normal()); + if (egg_vertex->has_normal() || egg_prim->has_normal()) { + Normald norm; + if (egg_vertex->has_normal()) { + norm = egg_vertex->get_normal(); + } else { + norm = egg_prim->get_normal(); + } + + if (xfile_one_mesh) { + // If this is going into one big mesh, we must ensure every + // vertex is in world coordinates. + norm = norm * egg_prim->get_vertex_frame(); + } else { + // Otherwise, we ensure the vertex is in local coordinates. + norm = norm * egg_prim->get_vertex_to_node(); + } + + _normal = LCAST(float, norm); _has_normal = true; } } diff --git a/pandatool/src/xfile/xFileToEggConverter.cxx b/pandatool/src/xfile/xFileToEggConverter.cxx index 8420a19d0a..39cb2a66a1 100644 --- a/pandatool/src/xfile/xFileToEggConverter.cxx +++ b/pandatool/src/xfile/xFileToEggConverter.cxx @@ -20,6 +20,7 @@ #include "xFileMesh.h" #include "xFileMaterial.h" #include "xFileTemplates.h" +#include "config_xfile.h" #include "eggData.h" #include "eggGroup.h" @@ -202,7 +203,8 @@ get_toplevel() { } if (hr != DXFILEERR_NOMOREOBJECTS) { - cerr << "Error extracting top-level objects.\n"; + xfile_cat.error() + << "Error extracting top-level objects.\n"; return false; } @@ -228,8 +230,9 @@ convert_object(LPDIRECTXFILEOBJECT obj, EggGroupNode *egg_parent) { } // It isn't. - cerr << "Ignoring object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring object of unknown type: " << get_object_name(obj) + << "\n"; return true; } @@ -248,7 +251,8 @@ convert_data_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { const GUID *type; hr = obj->GetType(&type); if (hr != DXFILE_OK) { - cerr << "Unable to get type of template\n"; + xfile_cat.error() + << "Unable to get type of template\n"; return false; } @@ -259,13 +263,21 @@ convert_data_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { if (!convert_frame(obj, egg_parent)) { return false; } + + } else if (*type == TID_D3DRMFrameTransformMatrix) { + if (!convert_transform(obj, egg_parent)) { + return false; + } + } else if (*type == TID_D3DRMMesh) { if (!convert_mesh(obj, egg_parent)) { return false; } + } else { - cerr << "Ignoring data object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring data object of unknown type: " << get_object_name(obj) + << "\n"; } return true; @@ -297,13 +309,47 @@ convert_frame(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { } if (hr != DXFILEERR_NOMOREOBJECTS) { - cerr << "Error extracting children of frame " << name << ".\n"; + xfile_cat.error() + << "Error extracting children of frame " << name << ".\n"; return false; } return true; } +//////////////////////////////////////////////////////////////////// +// Function: XFileToEggConverter::convert_transform +// Access: Private +// Description: Reads a transform matrix, a child of a given frame, +// and applies it to the node. Normally this can only +// be done if the node in question is an EggGroup, which +// should be the case if the transform was a child of a +// frame. +//////////////////////////////////////////////////////////////////// +bool XFileToEggConverter:: +convert_transform(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { + Datagram raw_data; + if (!get_data(obj, raw_data)) { + return false; + } + + DatagramIterator di(raw_data); + LMatrix4f mat; + mat.read_datagram(di); + + if (egg_parent->is_of_type(EggGroup::get_class_type())) { + EggGroup *egg_group = DCAST(EggGroup, egg_parent); + egg_group->set_transform(LCAST(double, mat)); + egg_group->set_group_type(EggGroup::GT_instance); + } else { + xfile_cat.error() + << "Transform " << get_object_name(obj) + << " encountered without frame!\n"; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: XFileToEggConverter::convert_mesh // Access: Private @@ -337,8 +383,9 @@ convert_mesh(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { } if (hr != DXFILEERR_NOMOREOBJECTS) { - cerr << "Error extracting children of mesh " << get_object_name(obj) - << ".\n"; + xfile_cat.error() + << "Error extracting children of mesh " << get_object_name(obj) + << ".\n"; return false; } @@ -368,8 +415,9 @@ convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) { } // It isn't. - cerr << "Ignoring object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring object of unknown type: " << get_object_name(obj) + << "\n"; return true; } @@ -387,7 +435,8 @@ convert_mesh_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) { const GUID *type; hr = obj->GetType(&type); if (hr != DXFILE_OK) { - cerr << "Unable to get type of template\n"; + xfile_cat.error() + << "Unable to get type of template\n"; return false; } @@ -412,8 +461,9 @@ convert_mesh_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) { } } else { - cerr << "Ignoring data object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring data object of unknown type: " << get_object_name(obj) + << "\n"; } return true; @@ -511,8 +561,9 @@ convert_mesh_material_list(LPDIRECTXFILEDATA obj, XFileMesh &mesh) { } if (hr != DXFILEERR_NOMOREOBJECTS) { - cerr << "Error extracting children of MeshMaterialList " - << get_object_name(obj) << ".\n"; + xfile_cat.error() + << "Error extracting children of MeshMaterialList " + << get_object_name(obj) << ".\n"; return false; } @@ -538,8 +589,9 @@ convert_material_list_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) { } // It isn't. - cerr << "Ignoring object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring object of unknown type: " << get_object_name(obj) + << "\n"; return true; } @@ -557,7 +609,8 @@ convert_material_list_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) { const GUID *type; hr = obj->GetType(&type); if (hr != DXFILE_OK) { - cerr << "Unable to get type of template\n"; + xfile_cat.error() + << "Unable to get type of template\n"; return false; } @@ -566,8 +619,9 @@ convert_material_list_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) { return false; } } else { - cerr << "Ignoring data object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring data object of unknown type: " << get_object_name(obj) + << "\n"; } return true; @@ -609,8 +663,9 @@ convert_material(LPDIRECTXFILEDATA obj, XFileMesh &mesh) { } if (hr != DXFILEERR_NOMOREOBJECTS) { - cerr << "Error extracting children of Material " - << get_object_name(obj) << ".\n"; + xfile_cat.error() + << "Error extracting children of Material " + << get_object_name(obj) << ".\n"; return false; } @@ -636,8 +691,9 @@ convert_material_object(LPDIRECTXFILEOBJECT obj, XFileMaterial &material) { } // It isn't. - cerr << "Ignoring object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring object of unknown type: " << get_object_name(obj) + << "\n"; return true; } @@ -655,7 +711,8 @@ convert_material_data_object(LPDIRECTXFILEDATA obj, XFileMaterial &material) { const GUID *type; hr = obj->GetType(&type); if (hr != DXFILE_OK) { - cerr << "Unable to get type of template\n"; + xfile_cat.error() + << "Unable to get type of template\n"; return false; } @@ -664,8 +721,9 @@ convert_material_data_object(LPDIRECTXFILEDATA obj, XFileMaterial &material) { return false; } } else { - cerr << "Ignoring data object of unknown type: " << get_object_name(obj) - << "\n"; + xfile_cat.error() + << "Ignoring data object of unknown type: " << get_object_name(obj) + << "\n"; } return true; @@ -711,7 +769,8 @@ get_object_name(LPDIRECTXFILEOBJECT obj) { string result; if (hr != DXFILE_OK) { - cerr << "Unable to get object name.\n"; + xfile_cat.error() + << "Unable to get object name.\n"; } else { result = buffer; } @@ -732,7 +791,8 @@ get_data(LPDIRECTXFILEDATA obj, Datagram &raw_data) { void *data; hr = obj->GetData(NULL, &length, &data); if (hr != DXFILE_OK) { - cerr << "Unable to get data for " << get_object_name(obj) << "\n"; + xfile_cat.error() + << "Unable to get data for " << get_object_name(obj) << "\n"; return false; } diff --git a/pandatool/src/xfile/xFileToEggConverter.h b/pandatool/src/xfile/xFileToEggConverter.h index c7b613dc09..3c9554f699 100644 --- a/pandatool/src/xfile/xFileToEggConverter.h +++ b/pandatool/src/xfile/xFileToEggConverter.h @@ -64,6 +64,7 @@ private: bool convert_object(LPDIRECTXFILEOBJECT obj, EggGroupNode *egg_parent); bool convert_data_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent); bool convert_frame(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent); + bool convert_transform(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent); bool convert_mesh(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent); bool convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh); diff --git a/pandatool/src/xfile/xFileVertex.cxx b/pandatool/src/xfile/xFileVertex.cxx index c14696293f..e2201de1c9 100644 --- a/pandatool/src/xfile/xFileVertex.cxx +++ b/pandatool/src/xfile/xFileVertex.cxx @@ -19,6 +19,7 @@ #include "xFileVertex.h" #include "eggVertex.h" #include "eggPrimitive.h" +#include "config_xfile.h" //////////////////////////////////////////////////////////////////// // Function: XFileVertex::Constructor @@ -41,7 +42,18 @@ XFileVertex() { //////////////////////////////////////////////////////////////////// void XFileVertex:: set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim) { - _point = LCAST(float, egg_vertex->get_pos3()); + Vertexd pos = egg_vertex->get_pos3(); + + if (xfile_one_mesh) { + // If this is going into one big mesh, we must ensure every + // vertex is in world coordinates. + pos = pos * egg_prim->get_vertex_frame(); + } else { + // Otherwise, we ensure the vertex is in local coordinates. + pos = pos * egg_prim->get_vertex_to_node(); + } + + _point = LCAST(float, pos); if (egg_vertex->has_uv()) { TexCoordd uv = egg_vertex->get_uv(); diff --git a/pandatool/src/xfileprogs/eggToX.cxx b/pandatool/src/xfileprogs/eggToX.cxx index 89717d6eb9..e014f4f435 100644 --- a/pandatool/src/xfileprogs/eggToX.cxx +++ b/pandatool/src/xfileprogs/eggToX.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "eggToX.h" +#include "config_xfile.h" //////////////////////////////////////////////////////////////////// // Function: EggToX::Constructor @@ -24,17 +25,30 @@ // Description: //////////////////////////////////////////////////////////////////// EggToX:: -EggToX() : EggToSomething("DirectX", ".x") { +EggToX() : EggToSomething("DirectX", ".x", true, false) { + add_texture_options(); + set_program_description ("This program reads an Egg file and outputs an equivalent, " "or nearly equivalent, DirectX-style .x file. Only simple " "hierarchy and polygon meshes are supported; advanced features " "like LOD's, decals, and characters cannot be supported."); + add_option + ("m", "", 0, + "Convert all the objects in the egg file as one big mesh, instead of " + "preserving the normal egg hierarchy.", + &EggToX::dispatch_none, &xfile_one_mesh); + // X files are always y-up-left. remove_option("cs"); _got_coordinate_system = true; _coordinate_system = CS_yup_left; + + // We always have -f on: force complete load. X files don't support + // external references. + remove_option("f"); + _force_complete = true; } @@ -50,6 +64,10 @@ run() { exit(1); } + if (!copy_textures()) { + exit(1); + } + if (!_x.add_tree(_data)) { nout << "Unable to define egg structure.\n"; exit(1); @@ -60,6 +78,7 @@ run() { int main(int argc, char *argv[]) { + init_libxfile(); EggToX prog; prog.parse_command_line(argc, argv); prog.run(); diff --git a/pandatool/src/xfileprogs/xFileToEgg.cxx b/pandatool/src/xfileprogs/xFileToEgg.cxx index 027a4e2de4..af0164bb3f 100644 --- a/pandatool/src/xfileprogs/xFileToEgg.cxx +++ b/pandatool/src/xfileprogs/xFileToEgg.cxx @@ -18,6 +18,7 @@ #include "xFileToEgg.h" #include "xFileToEggConverter.h" +#include "config_xfile.h" //////////////////////////////////////////////////////////////////// // Function: XFileToEgg::Constructor @@ -71,6 +72,7 @@ run() { int main(int argc, char *argv[]) { + init_libxfile(); XFileToEgg prog; prog.parse_command_line(argc, argv); prog.run();