diff --git a/pandatool/src/xfile/xFileMesh.cxx b/pandatool/src/xfile/xFileMesh.cxx index 46ec6ff7e4..42c489ab2a 100644 --- a/pandatool/src/xfile/xFileMesh.cxx +++ b/pandatool/src/xfile/xFileMesh.cxx @@ -33,7 +33,7 @@ // Description: //////////////////////////////////////////////////////////////////// XFileMesh:: -XFileMesh() { +XFileMesh(CoordinateSystem cs) : _cs(cs) { _has_normals = false; _has_colors = false; _has_uvs = false; @@ -260,6 +260,13 @@ add_material(XFileMaterial *material) { //////////////////////////////////////////////////////////////////// bool XFileMesh:: create_polygons(EggGroupNode *egg_parent, XFileToEggConverter *converter) { + if (has_name()) { + // Put a named mesh within its own group. + EggGroup *egg_group = new EggGroup(get_name()); + egg_parent->add_child(egg_group); + egg_parent = egg_group; + } + EggVertexPool *vpool = new EggVertexPool(get_name()); egg_parent->add_child(vpool); Faces::const_iterator fi; @@ -302,6 +309,10 @@ create_polygons(EggGroupNode *egg_parent, XFileToEggConverter *converter) { temp_vtx.set_normal(LCAST(double, normal->_normal)); } + // Transform the vertex into the appropriate (global) coordinate + // space. + temp_vtx.transform(egg_parent->get_node_to_vertex()); + // Now get a real EggVertex matching our template. EggVertex *egg_vtx = vpool->create_unique_vertex(temp_vtx); egg_poly->add_vertex(egg_vtx); @@ -315,6 +326,13 @@ create_polygons(EggGroupNode *egg_parent, XFileToEggConverter *converter) { } } + if (!has_normals()) { + // If we don't have explicit normals, make some up, per the DX + // spec. Since the DX spec doesn't mention anything about a + // crease angle, we should be as generous as possible. + egg_parent->recompute_vertex_normals(180.0, _cs); + } + return true; } diff --git a/pandatool/src/xfile/xFileMesh.h b/pandatool/src/xfile/xFileMesh.h index cc6e5dfd61..46b3487156 100644 --- a/pandatool/src/xfile/xFileMesh.h +++ b/pandatool/src/xfile/xFileMesh.h @@ -24,6 +24,7 @@ #include "pmap.h" #include "indirectCompareTo.h" #include "namable.h" +#include "coordinateSystem.h" class XFileMesh; class XFileVertex; @@ -43,7 +44,7 @@ class Datagram; //////////////////////////////////////////////////////////////////// class XFileMesh : public Namable { public: - XFileMesh(); + XFileMesh(CoordinateSystem cs = CS_yup_left); ~XFileMesh(); void clear(); @@ -86,6 +87,8 @@ private: typedef pvector Materials; typedef pvector Faces; + CoordinateSystem _cs; + Vertices _vertices; Normals _normals; Materials _materials; diff --git a/pandatool/src/xfile/xFileToEggConverter.cxx b/pandatool/src/xfile/xFileToEggConverter.cxx index 8aea646ac3..d72bf1f10a 100644 --- a/pandatool/src/xfile/xFileToEggConverter.cxx +++ b/pandatool/src/xfile/xFileToEggConverter.cxx @@ -195,9 +195,13 @@ get_toplevel() { HRESULT hr; LPDIRECTXFILEDATA obj; + PT(EggGroup) egg_toplevel = new EggGroup; + bool any_frames = false; + hr = _dx_file_enum->GetNextDataObject(&obj); while (hr == DXFILE_OK) { - if (!convert_data_object(obj, _egg_data)) { + if (!convert_toplevel_object(obj, _egg_data, + egg_toplevel, any_frames)) { return false; } hr = _dx_file_enum->GetNextDataObject(&obj); @@ -209,6 +213,71 @@ get_toplevel() { return false; } + if (!any_frames) { + // If the file contained no frames at all, then all of the meshes + // that appeared at the toplevel were meant to be directly + // included. + _egg_data->steal_children(*egg_toplevel); + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileToEggConverter::convert_toplevel_object +// Access: Private +// Description: Converts the indicated object, encountered outside of +// any Frames, to the appropriate egg structures. +//////////////////////////////////////////////////////////////////// +bool XFileToEggConverter:: +convert_toplevel_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent, + EggGroupNode *egg_toplevel, bool &any_frames) { + HRESULT hr; + + // Determine what type of data object we have. + const GUID *type; + hr = obj->GetType(&type); + if (hr != DXFILE_OK) { + xfile_cat.error() + << "Unable to get type of template\n"; + return false; + } + + if (*type == mydef_TID_D3DRMHeader) { + // Quietly ignore headers. + + } else if (*type == TID_D3DRMMaterial) { + // Quietly ignore toplevel materials. These will presumably be + // referenced below. + + } else if (*type == TID_D3DRMFrame) { + any_frames = true; + 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) { + // Assume a Mesh at the toplevel is just present to define a + // reference that will be included below. Convert it into the + // egg_toplevel group, where it will be ignored unless there are + // no frames at all in the file. + if (!convert_mesh(obj, egg_toplevel)) { + return false; + } + + } else { + if (xfile_cat.is_debug()) { + xfile_cat.debug() + << "Ignoring toplevel object of unknown type: " + << get_object_name(obj) << "\n"; + } + } + return true; } @@ -222,6 +291,7 @@ bool XFileToEggConverter:: convert_object(LPDIRECTXFILEOBJECT obj, EggGroupNode *egg_parent) { HRESULT hr; LPDIRECTXFILEDATA data_obj; + LPDIRECTXFILEDATAREFERENCE ref_obj; // See if the object is a data object. hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj); @@ -230,6 +300,15 @@ convert_object(LPDIRECTXFILEOBJECT obj, EggGroupNode *egg_parent) { return convert_data_object(data_obj, egg_parent); } + // Or maybe it's a reference to a previous object. + hr = obj->QueryInterface(IID_IDirectXFileDataReference, (void **)&ref_obj); + if (hr == DD_OK) { + // It is. + if (ref_obj->Resolve(&data_obj) == DXFILE_OK) { + return convert_data_object(data_obj, egg_parent); + } + } + // It isn't. if (xfile_cat.is_debug()) { xfile_cat.debug() @@ -345,7 +424,7 @@ convert_transform(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { 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) @@ -370,7 +449,7 @@ convert_mesh(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) { return false; } - XFileMesh mesh; + XFileMesh mesh(_egg_data->get_coordinate_system()); mesh.set_name(get_object_name(obj)); if (!mesh.read_mesh_data(raw_data)) { return false; @@ -411,6 +490,7 @@ bool XFileToEggConverter:: convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) { HRESULT hr; LPDIRECTXFILEDATA data_obj; + LPDIRECTXFILEDATAREFERENCE ref_obj; // See if the object is a data object. hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj); @@ -419,6 +499,15 @@ convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) { return convert_mesh_data_object(data_obj, mesh); } + // Or maybe it's a reference to a previous object. + hr = obj->QueryInterface(IID_IDirectXFileDataReference, (void **)&ref_obj); + if (hr == DD_OK) { + // It is. + if (ref_obj->Resolve(&data_obj) == DXFILE_OK) { + return convert_mesh_data_object(data_obj, mesh); + } + } + // It isn't. if (xfile_cat.is_debug()) { xfile_cat.debug() @@ -705,6 +794,7 @@ bool XFileToEggConverter:: convert_material_object(LPDIRECTXFILEOBJECT obj, XFileMaterial &material) { HRESULT hr; LPDIRECTXFILEDATA data_obj; + LPDIRECTXFILEDATAREFERENCE ref_obj; // See if the object is a data object. hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj); @@ -713,6 +803,15 @@ convert_material_object(LPDIRECTXFILEOBJECT obj, XFileMaterial &material) { return convert_material_data_object(data_obj, material); } + // Or maybe it's a reference to a previous object. + hr = obj->QueryInterface(IID_IDirectXFileDataReference, (void **)&ref_obj); + if (hr == DD_OK) { + // It is. + if (ref_obj->Resolve(&data_obj) == DXFILE_OK) { + return convert_material_data_object(data_obj, material); + } + } + // It isn't. if (xfile_cat.is_debug()) { xfile_cat.debug() diff --git a/pandatool/src/xfile/xFileToEggConverter.h b/pandatool/src/xfile/xFileToEggConverter.h index 26214f25cd..689e895447 100644 --- a/pandatool/src/xfile/xFileToEggConverter.h +++ b/pandatool/src/xfile/xFileToEggConverter.h @@ -61,6 +61,8 @@ public: private: bool get_toplevel(); + bool convert_toplevel_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent, + EggGroupNode *egg_toplevel, bool &any_frames); 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);