robustify xfile some more

This commit is contained in:
David Rose 2004-10-02 17:52:42 +00:00
parent 679f9cdc13
commit 99d7222df4
4 changed files with 127 additions and 5 deletions

View File

@ -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;
}

View File

@ -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<XFileMaterial *> Materials;
typedef pvector<XFileFace *> Faces;
CoordinateSystem _cs;
Vertices _vertices;
Normals _normals;
Materials _materials;

View File

@ -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()

View File

@ -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);