mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
robustify xfile some more
This commit is contained in:
parent
679f9cdc13
commit
99d7222df4
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user