*** empty log message ***

This commit is contained in:
David Rose 2001-06-22 01:54:52 +00:00
parent a98fd52495
commit 3bd11c3cda
16 changed files with 1899 additions and 24 deletions

View File

@ -15,13 +15,46 @@
#define SOURCES \
xFileFace.cxx xFileFace.h \
xFileMaker.cxx xFileMaker.h \
xFileMaterial.cxx xFileMaterial.h \
xFileMesh.cxx xFileMesh.h \
xFileNormal.cxx xFileNormal.h \
xFileVertex.cxx xFileVertex.h
#define SOURCES \
$[SOURCES] \
xFileMaker.cxx xFileMaker.h
#define SOURCES \
$[SOURCES] \
eggToX.cxx eggToX.h
#end bin_target
#begin bin_target
#define TARGET x2egg
#define LOCAL_LIBS converter eggbase progbase pandatoolbase
#define OTHER_LIBS \
egg:c pandaegg:m \
mathutil:c linmath:c putil:c panda:m \
express:c pandaexpress:m \
dtoolconfig dtool pystub \
#define WIN_SYS_LIBS \
d3dxof.lib
#define SOURCES \
xFileFace.cxx xFileFace.h \
xFileMaterial.cxx xFileMaterial.h \
xFileMesh.cxx xFileMesh.h \
xFileNormal.cxx xFileNormal.h \
xFileVertex.cxx xFileVertex.h
#define SOURCES \
$[SOURCES] \
xFileToEggConverter.cxx xFileToEggConverter.h
#define SOURCES \
$[SOURCES] \
xFileToEgg.cxx xFileToEgg.h
#end bin_target

View File

@ -26,7 +26,17 @@
// Description:
////////////////////////////////////////////////////////////////////
XFileFace::
XFileFace(XFileMesh *mesh, EggPolygon *egg_poly) {
XFileFace() {
_material_index = -1;
}
////////////////////////////////////////////////////////////////////
// Function: XFileFace::set_from_egg
// Access: Public
// Description: Sets the structure up from the indicated egg data.
////////////////////////////////////////////////////////////////////
void XFileFace::
set_from_egg(XFileMesh *mesh, EggPolygon *egg_poly) {
// Walk through the polygon's vertices in reverse order, to change
// from Egg's counter-clockwise convention to DX's clockwise.
EggPolygon::reverse_iterator vi;
@ -37,4 +47,6 @@ XFileFace(XFileMesh *mesh, EggPolygon *egg_poly) {
v._normal_index = mesh->add_normal(egg_vertex, egg_poly);
_vertices.push_back(v);
}
_material_index = mesh->add_material(egg_poly);
}

View File

@ -31,7 +31,8 @@ class EggPolygon;
////////////////////////////////////////////////////////////////////
class XFileFace {
public:
XFileFace(XFileMesh *mesh, EggPolygon *egg_poly);
XFileFace();
void set_from_egg(XFileMesh *mesh, EggPolygon *egg_poly);
class Vertex {
public:
@ -40,6 +41,8 @@ public:
};
typedef pvector<Vertex> Vertices;
Vertices _vertices;
int _material_index;
};
#endif

View File

@ -18,6 +18,8 @@
#include "xFileMaker.h"
#include "xFileMesh.h"
#include "xFileMaterial.h"
#include "notify.h"
#include "eggGroupNode.h"
#include "eggGroup.h"
@ -305,6 +307,54 @@ add_polyset(EggBin *egg_bin, LPDIRECTXFILEDATA dx_parent) {
}
}
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;
}

View File

@ -0,0 +1,284 @@
// Filename: xFileMaterial.cxx
// Created by: drose (19Jun01)
//
////////////////////////////////////////////////////////////////////
//
// 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 "xFileMaterial.h"
#include "eggMaterial.h"
#include "eggTexture.h"
#include "eggMaterialCollection.h"
#include "eggTextureCollection.h"
#include "eggPrimitive.h"
#include "datagram.h"
#include <string.h> // for strcmp, strdup
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileMaterial::
XFileMaterial() {
_face_color.set(1.0, 1.0, 1.0, 1.0);
_specular_color.set(0.0, 0.0, 0.0);
_emissive_color.set(0.0, 0.0, 0.0);
_power = 64.0;
_has_material = false;
_has_texture = false;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileMaterial::
~XFileMaterial() {
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::set_from_egg
// Access: Public
// Description: Sets the structure up from the indicated egg data.
////////////////////////////////////////////////////////////////////
void XFileMaterial::
set_from_egg(EggPrimitive *egg_prim) {
// First, determine the face color.
if (egg_prim->has_color()) {
_face_color = egg_prim->get_color();
_has_material = true;
}
// Do we have an actual EggMaterial, to control lighting effects?
if (egg_prim->has_material()) {
_has_material = true;
EggMaterial *egg_mat = egg_prim->get_material();
if (egg_mat->has_diff()) {
_face_color = egg_mat->get_diff();
}
if (egg_mat->has_spec()) {
const Colorf &spec = egg_mat->get_spec();
_specular_color.set(spec[0], spec[1], spec[2]);
}
if (egg_mat->has_emit()) {
const Colorf &emit = egg_mat->get_emit();
_emissive_color.set(emit[0], emit[1], emit[2]);
}
if (egg_mat->has_shininess()) {
_power = egg_mat->get_shininess();
}
}
// Finally, if we also have a texture, record that.
if (egg_prim->has_texture()) {
_has_material = true;
_has_texture = true;
EggTexture *egg_tex = egg_prim->get_texture();
_texture = egg_tex->get_filename();
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::apply_to_egg
// Access: Public
// Description: Applies the properties in the material to the
// indicated egg primitive.
////////////////////////////////////////////////////////////////////
void XFileMaterial::
apply_to_egg(EggPrimitive *egg_prim,
EggTextureCollection &textures,
EggMaterialCollection &materials) {
// Is there a texture?
if (_has_texture) {
EggTexture temp("", _texture);
EggTexture *egg_tex =
textures.create_unique_texture(temp, ~EggTexture::E_tref_name);
egg_prim->set_texture(egg_tex);
}
// Are there any fancy lighting effects?
bool got_spec = (_specular_color != RGBColorf::zero());
bool got_emit = (_emissive_color != RGBColorf::zero());
if (got_spec || got_emit) {
EggMaterial temp("");
temp.set_diff(_face_color);
if (got_spec) {
temp.set_shininess(_power);
temp.set_spec(Colorf(_specular_color[0], _specular_color[1],
_specular_color[2], 1.0));
}
if (got_emit) {
temp.set_emit(Colorf(_emissive_color[0], _emissive_color[1],
_emissive_color[2], 1.0));
}
EggMaterial *egg_mat =
materials.create_unique_material(temp, ~EggMaterial::E_mref_name);
egg_prim->set_material(egg_mat);
}
// Also apply the face color.
egg_prim->set_color(_face_color);
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::compare_to
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
int XFileMaterial::
compare_to(const XFileMaterial &other) const {
int ct;
ct = _face_color.compare_to(other._face_color);
if (ct == 0) {
ct = (_power == other._power) ? 0 : ((_power < other._power) ? -1 : 1);
}
if (ct == 0) {
ct = _specular_color.compare_to(other._specular_color);
}
if (ct == 0) {
ct = _emissive_color.compare_to(other._emissive_color);
}
if (ct == 0) {
ct = strcmp(_texture.c_str(), other._texture.c_str());
}
return ct;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::has_material
// Access: Public
// Description: Returns true if this material represents something
// meaningful, or false if the default material is
// sufficient.
////////////////////////////////////////////////////////////////////
bool XFileMaterial::
has_material() const {
return _has_material;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::has_texture
// Access: Public
// Description: Returns true if this material includes a texture map,
// false otherwise.
////////////////////////////////////////////////////////////////////
bool XFileMaterial::
has_texture() const {
return _has_texture;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::make_material_data
// Access: Public
// Description: Fills the datagram with the raw data for the DX
// Material template.
////////////////////////////////////////////////////////////////////
void XFileMaterial::
make_material_data(Datagram &raw_data) {
raw_data.clear();
raw_data.add_float32(_face_color[0]);
raw_data.add_float32(_face_color[1]);
raw_data.add_float32(_face_color[2]);
raw_data.add_float32(_face_color[3]);
raw_data.add_float32(_power);
raw_data.add_float32(_specular_color[0]);
raw_data.add_float32(_specular_color[1]);
raw_data.add_float32(_specular_color[2]);
raw_data.add_float32(_emissive_color[0]);
raw_data.add_float32(_emissive_color[1]);
raw_data.add_float32(_emissive_color[2]);
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::make_texture_data
// Access: Public
// Description: Fills the datagram with the raw data for the DX
// TextureFilename template.
////////////////////////////////////////////////////////////////////
void XFileMaterial::
make_texture_data(Datagram &raw_data) {
raw_data.clear();
// Get a char * pointer to the texture filename, to pass into the
// Microsoft DX file interface. Unfortunately, we can't delete this
// again, since it needs to live longer than the life of the
// XFileMaterial object itself, so this becomes a memory leak
// (unless the DX file interface frees it, but the documentation is
// far from clear). Too bad.
string filename = _texture.to_os_specific();
char *filename_str = strdup(filename.c_str());
// The Microsoft convention is to stuff a pointer into a four-byte
// field. Not terribly portable, but that's the interface.
raw_data.add_int32((int)filename_str);
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::read_material_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// Material template.
////////////////////////////////////////////////////////////////////
bool XFileMaterial::
read_material_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
_face_color[0] = di.get_float32();
_face_color[1] = di.get_float32();
_face_color[2] = di.get_float32();
_face_color[3] = di.get_float32();
_power = di.get_float32();
_specular_color[0] = di.get_float32();
_specular_color[1] = di.get_float32();
_specular_color[2] = di.get_float32();
_emissive_color[0] = di.get_float32();
_emissive_color[1] = di.get_float32();
_emissive_color[2] = di.get_float32();
_has_material = true;
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size()
<< " trailing MeshMaterial.\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMaterial::read_texture_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// TextureFilename template.
////////////////////////////////////////////////////////////////////
bool XFileMaterial::
read_texture_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
// The Microsoft convention is to stuff a pointer into a four-byte
// field. Not terribly portable, but that's the interface.
const char *ptr = (const char *)di.get_int32();
_texture = ptr;
_has_texture = true;
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size()
<< " trailing MeshMaterial.\n";
}
return true;
}

View File

@ -0,0 +1,69 @@
// Filename: xFileMaterial.h
// Created by: drose (19Jun01)
//
////////////////////////////////////////////////////////////////////
//
// 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 XFILEMATERIAL_H
#define XFILEMATERIAL_H
#include "pandatoolbase.h"
#include "luse.h"
#include "filename.h"
class EggPrimitive;
class EggTextureCollection;
class EggMaterialCollection;
class Datagram;
////////////////////////////////////////////////////////////////////
// Class : XFileMaterial
// Description : This represents an X file "material", which consists
// of a color, lighting, and/or texture specification.
////////////////////////////////////////////////////////////////////
class XFileMaterial {
public:
XFileMaterial();
~XFileMaterial();
void set_from_egg(EggPrimitive *egg_prim);
void apply_to_egg(EggPrimitive *egg_prim,
EggTextureCollection &textures,
EggMaterialCollection &materials);
int compare_to(const XFileMaterial &other) const;
bool has_material() const;
bool has_texture() const;
void make_material_data(Datagram &raw_data);
void make_texture_data(Datagram &raw_data);
bool read_material_data(const Datagram &raw_data);
bool read_texture_data(const Datagram &raw_data);
private:
Colorf _face_color;
float _power;
RGBColorf _specular_color;
RGBColorf _emissive_color;
Filename _texture;
bool _has_material;
bool _has_texture;
};
#endif

View File

@ -20,6 +20,12 @@
#include "xFileFace.h"
#include "xFileVertex.h"
#include "xFileNormal.h"
#include "xFileMaterial.h"
#include "eggVertexPool.h"
#include "eggVertex.h"
#include "eggPolygon.h"
#include "eggGroupNode.h"
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::Constructor
@ -31,6 +37,7 @@ XFileMesh() {
_has_normals = false;
_has_colors = false;
_has_uvs = false;
_has_materials = false;
}
////////////////////////////////////////////////////////////////////
@ -40,6 +47,16 @@ XFileMesh() {
////////////////////////////////////////////////////////////////////
XFileMesh::
~XFileMesh() {
clear();
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::clear
// Access: Public
// Description: Empties all data from the mesh.
////////////////////////////////////////////////////////////////////
void XFileMesh::
clear() {
Vertices::iterator vi;
for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
XFileVertex *vertex = (*vi);
@ -50,6 +67,25 @@ XFileMesh::
XFileNormal *normal = (*ni);
delete normal;
}
Materials::iterator mi;
for (mi = _materials.begin(); mi != _materials.end(); ++mi) {
XFileMaterial *material = (*mi);
delete material;
}
Faces::iterator fi;
for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
XFileFace *face = (*fi);
delete face;
}
_vertices.clear();
_normals.clear();
_materials.clear();
_faces.clear();
_unique_vertices.clear();
_unique_normals.clear();
_unique_materials.clear();
}
////////////////////////////////////////////////////////////////////
@ -59,7 +95,8 @@ XFileMesh::
////////////////////////////////////////////////////////////////////
void XFileMesh::
add_polygon(EggPolygon *egg_poly) {
XFileFace *face = new XFileFace(this, egg_poly);
XFileFace *face = new XFileFace;
face->set_from_egg(this, egg_poly);
_faces.push_back(face);
}
@ -73,7 +110,8 @@ add_polygon(EggPolygon *egg_poly) {
int XFileMesh::
add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
int next_index = _vertices.size();
XFileVertex *vertex = new XFileVertex(egg_vertex, egg_prim);
XFileVertex *vertex = new XFileVertex;
vertex->set_from_egg(egg_vertex, egg_prim);
if (vertex->_has_color) {
_has_colors = true;
}
@ -107,7 +145,8 @@ add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
int XFileMesh::
add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
int next_index = _normals.size();
XFileNormal *normal = new XFileNormal(egg_vertex, egg_prim);
XFileNormal *normal = new XFileNormal;
normal->set_from_egg(egg_vertex, egg_prim);
if (normal->_has_normal) {
_has_normals = true;
}
@ -127,6 +166,156 @@ add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::add_material
// Access: Public
// Description: Creates a new XFileMaterial, if one does not already
// exist for the indicated material, and returns its
// index.
////////////////////////////////////////////////////////////////////
int XFileMesh::
add_material(EggPrimitive *egg_prim) {
int next_index = _materials.size();
XFileMaterial *material = new XFileMaterial;
material->set_from_egg(egg_prim);
if (material->has_material()) {
_has_materials = true;
}
pair<UniqueMaterials::iterator, bool> result =
_unique_materials.insert(UniqueMaterials::value_type(material, next_index));
if (result.second) {
// Successfully added; this is a new material.
_materials.push_back(material);
return next_index;
} else {
// Not successfully added; there is already a material with these
// properties. Return that one instead.
delete material;
return (*result.first).second;
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::add_vertex
// Access: Public
// Description: Adds the newly-created XFileVertex unequivocally to
// the mesh, returning its index number. The XFileMesh
// object becomes the owner of the XFileVertex
// pointer, and will delete it when it destructs.
////////////////////////////////////////////////////////////////////
int XFileMesh::
add_vertex(XFileVertex *vertex) {
int next_index = _vertices.size();
_unique_vertices.insert(UniqueVertices::value_type(vertex, next_index));
_vertices.push_back(vertex);
return next_index;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::add_normal
// Access: Public
// Description: Adds the newly-created XFileNormal unequivocally to
// the mesh, returning its index number. The XFileMesh
// object becomes the owner of the XFileNormal
// pointer, and will delete it when it destructs.
////////////////////////////////////////////////////////////////////
int XFileMesh::
add_normal(XFileNormal *normal) {
int next_index = _normals.size();
_unique_normals.insert(UniqueNormals::value_type(normal, next_index));
_normals.push_back(normal);
return next_index;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::add_material
// Access: Public
// Description: Adds the newly-created XFileMaterial unequivocally to
// the mesh, returning its index number. The XFileMesh
// object becomes the owner of the XFileMaterial
// pointer, and will delete it when it destructs.
////////////////////////////////////////////////////////////////////
int XFileMesh::
add_material(XFileMaterial *material) {
int next_index = _materials.size();
_unique_materials.insert(UniqueMaterials::value_type(material, next_index));
_materials.push_back(material);
return next_index;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::create_polygons
// Access: Public
// Description: Creates a slew of EggPolygons according to the faces
// in the mesh, and adds them to the indicated parent
// node.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
create_polygons(EggGroupNode *egg_parent,
EggTextureCollection &textures,
EggMaterialCollection &materials) {
EggVertexPool *vpool = new EggVertexPool(get_name());
egg_parent->add_child(vpool);
Faces::const_iterator fi;
for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
XFileFace *face = (*fi);
EggPolygon *egg_poly = new EggPolygon;
egg_parent->add_child(egg_poly);
// Set up the vertices for the polygon.
XFileFace::Vertices::reverse_iterator vi;
for (vi = face->_vertices.rbegin(); vi != face->_vertices.rend(); ++vi) {
int vertex_index = (*vi)._vertex_index;
int normal_index = (*vi)._normal_index;
if (vertex_index < 0 || vertex_index >= (int)_vertices.size()) {
cerr << "Vertex index out of range in Mesh.\n";
return false;
}
XFileVertex *vertex = _vertices[vertex_index];
XFileNormal *normal = (XFileNormal *)NULL;
if (normal_index >= 0 && normal_index < (int)_normals.size()) {
normal = _normals[normal_index];
}
// Create a temporary EggVertex before adding it to the pool.
EggVertex temp_vtx;
temp_vtx.set_pos(LCAST(double, vertex->_point));
if (vertex->_has_color) {
temp_vtx.set_color(vertex->_color);
}
if (vertex->_has_uv) {
TexCoordd uv = LCAST(double, vertex->_uv);
// Windows draws the UV's upside-down.
uv[1] = 1.0 - uv[1];
temp_vtx.set_uv(uv);
}
if (normal != (XFileNormal *)NULL && normal->_has_normal) {
temp_vtx.set_normal(LCAST(double, normal->_normal));
}
// Now get a real EggVertex matching our template.
EggVertex *egg_vtx = vpool->create_unique_vertex(temp_vtx);
egg_poly->add_vertex(egg_vtx);
}
// And apply the material for the polygon.
int material_index = face->_material_index;
if (material_index >= 0 && material_index < (int)_materials.size()) {
XFileMaterial *material = _materials[material_index];
material->apply_to_egg(egg_poly, textures, materials);
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::has_normals
// Access: Public
@ -160,6 +349,40 @@ has_uvs() const {
return _has_uvs;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::has_materials
// Access: Public
// Description: Returns true if any of the faces added to this mesh
// used a real material, false otherwise.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
has_materials() const {
return _has_materials;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::get_num_materials
// Access: Public
// Description: Returns the number of distinct materials associated
// with the mesh.
////////////////////////////////////////////////////////////////////
int XFileMesh::
get_num_materials() const {
return _materials.size();
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::get_material
// Access: Public
// Description: Returns a pointer to the nth materials associated
// with the mesh.
////////////////////////////////////////////////////////////////////
XFileMaterial *XFileMesh::
get_material(int n) const {
nassertr(n >= 0 && n < (int)_materials.size(), (XFileMaterial *)NULL);
return _materials[n];
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::make_mesh_data
// Access: Public
@ -274,3 +497,222 @@ make_uv_data(Datagram &raw_data) {
raw_data.add_float32(uv[1]);
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::make_material_list_data
// Access: Public
// Description: Fills the datagram with the raw data for the DX
// MeshMaterialList template.
////////////////////////////////////////////////////////////////////
void XFileMesh::
make_material_list_data(Datagram &raw_data) {
raw_data.clear();
raw_data.add_int32(_materials.size());
raw_data.add_int32(_faces.size());
Faces::const_iterator fi;
for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
XFileFace *face = (*fi);
raw_data.add_int32(face->_material_index);
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::read_mesh_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// Mesh template.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
read_mesh_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
clear();
int i, j;
int num_vertices = di.get_int32();
for (i = 0; i < num_vertices; i++) {
XFileVertex *vertex = new XFileVertex;
vertex->_point[0] = di.get_float32();
vertex->_point[1] = di.get_float32();
vertex->_point[2] = di.get_float32();
add_vertex(vertex);
}
int num_faces = di.get_int32();
for (i = 0; i < num_faces; i++) {
XFileFace *face = new XFileFace;
num_vertices = di.get_int32();
for (j = 0; j < num_vertices; j++) {
XFileFace::Vertex vertex;
vertex._vertex_index = di.get_int32();
vertex._normal_index = -1;
face->_vertices.push_back(vertex);
}
_faces.push_back(face);
}
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size() << " trailing Mesh.\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::read_normal_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// MeshNormals template.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
read_normal_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
int num_normals = di.get_int32();
int i;
for (i = 0; i < num_normals; i++) {
XFileNormal *normal = new XFileNormal;
normal->_normal[0] = di.get_float32();
normal->_normal[1] = di.get_float32();
normal->_normal[2] = di.get_float32();
normal->_has_normal = true;
add_normal(normal);
}
int num_faces = di.get_int32();
if (num_faces != _faces.size()) {
cerr << "Incorrect number of faces in MeshNormals.\n";
return false;
}
for (i = 0; i < num_faces; i++) {
XFileFace *face = _faces[i];
int num_vertices = di.get_int32();
if (num_vertices != face->_vertices.size()) {
cerr << "Incorrect number of vertices for face in MeshNormals.\n";
return false;
}
for (int j = 0; j < num_vertices; j++) {
face->_vertices[j]._normal_index = di.get_int32();
}
}
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size()
<< " trailing MeshNormals.\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::read_color_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// MeshVertexColors template.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
read_color_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
int num_colors = di.get_int32();
int i;
for (i = 0; i < num_colors; i++) {
int vertex_index = di.get_int32();
if (vertex_index < 0 || vertex_index >= _vertices.size()) {
cerr << "Vertex index out of range in MeshVertexColors.\n";
return false;
}
XFileVertex *vertex = _vertices[vertex_index];
vertex->_color[0] = di.get_float32();
vertex->_color[1] = di.get_float32();
vertex->_color[2] = di.get_float32();
vertex->_color[3] = di.get_float32();
vertex->_has_color = true;
}
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size()
<< " trailing MeshVertexColors.\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::read_uv_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// MeshTextureCoords template.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
read_uv_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
int num_vertices = di.get_int32();
if (num_vertices != _vertices.size()) {
cerr << "Wrong number of vertices in MeshTextureCoords.\n";
return false;
}
int i;
for (i = 0; i < num_vertices; i++) {
XFileVertex *vertex = _vertices[i];
vertex->_uv[0] = di.get_float32();
vertex->_uv[1] = di.get_float32();
vertex->_has_uv = true;
}
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size()
<< " trailing MeshTextureCoords.\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileMesh::read_material_list_data
// Access: Public
// Description: Fills the structure based on the raw data from the
// MaterialList template.
////////////////////////////////////////////////////////////////////
bool XFileMesh::
read_material_list_data(const Datagram &raw_data) {
DatagramIterator di(raw_data);
di.get_int32(); /* num_materials */
int num_faces = di.get_int32();
if (num_faces > _faces.size()) {
cerr << "Too many faces in MaterialList.\n";
return false;
}
int material_index = -1;
int i = 0;
while (i < num_faces) {
XFileFace *face = _faces[i];
material_index = di.get_int32();
face->_material_index = material_index;
i++;
}
// The rest of the faces get the same material index as the last
// one in the list.
while (i < (int)_faces.size()) {
XFileFace *face = _faces[i];
face->_material_index = material_index;
i++;
}
if (di.get_remaining_size() != 0) {
cerr << "Ignoring " << di.get_remaining_size()
<< " trailing MeshMaterialList.\n";
}
return true;
}

View File

@ -23,56 +23,88 @@
#include "pvector.h"
#include "pmap.h"
#include "indirectCompareTo.h"
#include "namable.h"
class XFileMesh;
class XFileVertex;
class XFileNormal;
class XFileMaterial;
class XFileFace;
class EggGroupNode;
class EggVertex;
class EggPolygon;
class EggPrimitive;
class EggTextureCollection;
class EggMaterialCollection;
class Datagram;
////////////////////////////////////////////////////////////////////
// Class : XFileMesh
// Description : This is a collection of polygons; i.e. a polyset.
////////////////////////////////////////////////////////////////////
class XFileMesh {
class XFileMesh : public Namable {
public:
XFileMesh();
~XFileMesh();
void clear();
void add_polygon(EggPolygon *egg_poly);
int add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim);
int add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim);
int add_material(EggPrimitive *egg_prim);
int add_vertex(XFileVertex *vertex);
int add_normal(XFileNormal *normal);
int add_material(XFileMaterial *material);
bool create_polygons(EggGroupNode *egg_parent,
EggTextureCollection &textures,
EggMaterialCollection &materials);
bool has_normals() const;
bool has_colors() const;
bool has_uvs() const;
bool has_materials() const;
int get_num_materials() const;
XFileMaterial *get_material(int n) const;
void make_mesh_data(Datagram &raw_data);
void make_normal_data(Datagram &raw_data);
void make_color_data(Datagram &raw_data);
void make_uv_data(Datagram &raw_data);
void make_material_list_data(Datagram &raw_data);
bool read_mesh_data(const Datagram &raw_data);
bool read_normal_data(const Datagram &raw_data);
bool read_color_data(const Datagram &raw_data);
bool read_uv_data(const Datagram &raw_data);
bool read_material_list_data(const Datagram &raw_data);
private:
typedef pvector<XFileVertex *> Vertices;
typedef pvector<XFileNormal *> Normals;
typedef pvector<XFileMaterial *> Materials;
typedef pvector<XFileFace *> Faces;
Vertices _vertices;
Normals _normals;
Materials _materials;
Faces _faces;
private:
typedef pmap<XFileVertex *, int, IndirectCompareTo<XFileVertex> > UniqueVertices;
typedef pmap<XFileNormal *, int, IndirectCompareTo<XFileNormal> > UniqueNormals;
typedef pmap<XFileMaterial *, int, IndirectCompareTo<XFileMaterial> > UniqueMaterials;
UniqueVertices _unique_vertices;
UniqueNormals _unique_normals;
UniqueMaterials _unique_materials;
bool _has_normals;
bool _has_colors;
bool _has_uvs;
bool _has_materials;
};
#endif

View File

@ -26,15 +26,24 @@
// Description:
////////////////////////////////////////////////////////////////////
XFileNormal::
XFileNormal(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
_has_normal = true;
XFileNormal() {
_normal.set(0.0, 0.0, 0.0);
_has_normal = false;
}
////////////////////////////////////////////////////////////////////
// Function: XFileNormal::set_from_egg
// Access: Public
// Description: Sets the structure up from the indicated egg data.
////////////////////////////////////////////////////////////////////
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());
} else {
_normal.set(0.0, 0.0, 0.0);
_has_normal = false;
_has_normal = true;
}
}

View File

@ -34,7 +34,8 @@ class EggPrimitive;
////////////////////////////////////////////////////////////////////
class XFileNormal {
public:
XFileNormal(EggVertex *egg_vertex, EggPrimitive *egg_prim);
XFileNormal();
void set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim);
int compare_to(const XFileNormal &other) const;
Normalf _normal;

View File

@ -0,0 +1,78 @@
// Filename: xFileToEgg.cxx
// Created by: drose (21Jun01)
//
////////////////////////////////////////////////////////////////////
//
// 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 "xFileToEgg.h"
#include "xFileToEggConverter.h"
////////////////////////////////////////////////////////////////////
// Function: XFileToEgg::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileToEgg::
XFileToEgg() :
SomethingToEgg("DirectX", ".x")
{
add_normals_options();
add_transform_options();
add_texture_path_options();
add_rel_dir_options();
add_search_path_options(false);
set_program_description
("This program converts DirectX retained-mode (.x) files to egg. This "
"is a simple file format that only supports basic polygons, materials, "
"and textures, in a hierarchy.");
redescribe_option
("cs",
"Specify the coordinate system of the input " + _format_name +
" file. Normally, this is y-up-left.");
_coordinate_system = CS_yup_left;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEgg::run
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void XFileToEgg::
run() {
_data.set_coordinate_system(_coordinate_system);
XFileToEggConverter converter;
converter.set_egg_data(&_data, false);
converter.set_texture_path_convert(_texture_path_convert, _make_rel_dir);
if (!converter.convert_file(_input_filename)) {
nout << "Unable to read " << _input_filename << "\n";
exit(1);
}
write_egg_file();
nout << "\n";
}
int main(int argc, char *argv[]) {
XFileToEgg prog;
prog.parse_command_line(argc, argv);
prog.run();
return 0;
}

View File

@ -0,0 +1,41 @@
// Filename: xFileToEgg.h
// Created by: drose (21Jun01)
//
////////////////////////////////////////////////////////////////////
//
// 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 XFILETOEGG_H
#define XFILETOEGG_H
#include "pandatoolbase.h"
#include "somethingToEgg.h"
#include "xFileToEggConverter.h"
#include "dSearchPath.h"
////////////////////////////////////////////////////////////////////
// Class : XFileToEgg
// Description : A program to read a DirectX "x" file and generate an
// egg file.
////////////////////////////////////////////////////////////////////
class XFileToEgg : public SomethingToEgg {
public:
XFileToEgg();
void run();
};
#endif

View File

@ -0,0 +1,713 @@
// Filename: xFileToEggConverter.cxx
// Created by: drose (21Jun01)
//
////////////////////////////////////////////////////////////////////
//
// 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 "xFileToEggConverter.h"
#include "xFileMesh.h"
#include "xFileMaterial.h"
#include "eggData.h"
#include "eggGroup.h"
#include "datagram.h"
// This must be included only in exactly one .cxx file, since
// including defines the structure!
#include <rmxftmpl.h>
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileToEggConverter::
XFileToEggConverter() {
_dx_file = NULL;
_dx_file_enum = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileToEggConverter::
XFileToEggConverter(const XFileToEggConverter &copy) :
SomethingToEggConverter(copy)
{
_dx_file = NULL;
_dx_file_enum = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
XFileToEggConverter::
~XFileToEggConverter() {
close();
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::make_copy
// Access: Public, Virtual
// Description: Allocates and returns a new copy of the converter.
////////////////////////////////////////////////////////////////////
SomethingToEggConverter *XFileToEggConverter::
make_copy() {
return new XFileToEggConverter(*this);
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::get_name
// Access: Public, Virtual
// Description: Returns the English name of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string XFileToEggConverter::
get_name() const {
return "DirectX";
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::get_extension
// Access: Public, Virtual
// Description: Returns the common extension of the file type this
// converter supports.
////////////////////////////////////////////////////////////////////
string XFileToEggConverter::
get_extension() const {
return "x";
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_file
// Access: Public, Virtual
// Description: Handles the reading of the input file and converting
// it to egg. Returns true if successful, false
// otherwise.
//
// This is designed to be as generic as possible,
// generally in support of run-time loading.
// Command-line converters may choose to use
// convert_flt() instead, as it provides more control.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_file(const Filename &filename) {
HRESULT hr;
close();
hr = DirectXFileCreate(&_dx_file);
if (hr != DXFILE_OK) {
nout << "Unable to create X interface.\n";
return false;
}
// Register our templates.
hr = _dx_file->RegisterTemplates(D3DRM_XTEMPLATES, D3DRM_XTEMPLATE_BYTES);
if (hr != DXFILE_OK) {
nout << "Unable to register templates.\n";
return false;
}
string os_file = filename.to_os_specific();
hr = _dx_file->CreateEnumObject
((void *)os_file.c_str(), DXFILELOAD_FROMFILE, &_dx_file_enum);
if (hr != DXFILE_OK) {
nout << "Unable to open X file: " << os_file << "\n";
return false;
}
return get_toplevel();
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::close
// Access: Public
// Description: Finalizes and closes the file previously opened via
// convert_file().
////////////////////////////////////////////////////////////////////
void XFileToEggConverter::
close() {
if (_dx_file != NULL) {
if (_dx_file_enum != NULL) {
_dx_file_enum->Release();
_dx_file_enum = NULL;
}
_dx_file->Release();
_dx_file = NULL;
}
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::get_toplevel
// Access: Private
// Description: Pulls off all of the top-level objects in the .x file
// and converts them, and their descendents, to the
// appropriate egg structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
get_toplevel() {
HRESULT hr;
LPDIRECTXFILEDATA obj;
hr = _dx_file_enum->GetNextDataObject(&obj);
while (hr == DXFILE_OK) {
if (!convert_data_object(obj, _egg_data)) {
return false;
}
hr = _dx_file_enum->GetNextDataObject(&obj);
}
if (hr != DXFILEERR_NOMOREOBJECTS) {
cerr << "Error extracting top-level objects.\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_object
// Access: Private
// Description: Converts the indicated object to the appropriate egg
// structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_object(LPDIRECTXFILEOBJECT obj, EggGroupNode *egg_parent) {
HRESULT hr;
LPDIRECTXFILEDATA data_obj;
// See if the object is a data object.
hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
if (hr == DD_OK) {
// It is.
return convert_data_object(data_obj, egg_parent);
}
// It isn't.
cerr << "Ignoring object of unknown type: " << get_object_name(obj)
<< "\n";
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_data_object
// Access: Private
// Description: Converts the indicated object to the appropriate egg
// structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_data_object(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
HRESULT hr;
// Determine what type of data object we have.
const GUID *type;
hr = obj->GetType(&type);
if (hr != DXFILE_OK) {
cerr << "Unable to get type of template\n";
return false;
}
if (*type == TID_D3DRMFrame) {
if (!convert_frame(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";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_frame
// Access: Private
// Description: Converts the indicated frame to the appropriate egg
// structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_frame(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
HRESULT hr;
string name = get_object_name(obj);
EggGroup *group = new EggGroup(name);
egg_parent->add_child(group);
// Now walk through the children of the frame.
LPDIRECTXFILEOBJECT child_obj;
hr = obj->GetNextObject(&child_obj);
while (hr == DXFILE_OK) {
if (!convert_object(child_obj, group)) {
return false;
}
hr = obj->GetNextObject(&child_obj);
}
if (hr != DXFILEERR_NOMOREOBJECTS) {
cerr << "Error extracting children of frame " << name << ".\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh
// Access: Private
// Description: Converts the indicated mesh to the appropriate egg
// structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent) {
HRESULT hr;
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
XFileMesh mesh;
mesh.set_name(get_object_name(obj));
if (!mesh.read_mesh_data(raw_data)) {
return false;
}
// Now process all the child objects of the mesh.
LPDIRECTXFILEOBJECT child_obj;
hr = obj->GetNextObject(&child_obj);
while (hr == DXFILE_OK) {
if (!convert_mesh_object(child_obj, mesh)) {
return false;
}
hr = obj->GetNextObject(&child_obj);
}
if (hr != DXFILEERR_NOMOREOBJECTS) {
cerr << "Error extracting children of mesh " << get_object_name(obj)
<< ".\n";
return false;
}
if (!mesh.create_polygons(egg_parent, _textures, _materials)) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh_object
// Access: Private
// Description: Converts the indicated object, a child of a Mesh, to
// the appropriate egg structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) {
HRESULT hr;
LPDIRECTXFILEDATA data_obj;
// See if the object is a data object.
hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
if (hr == DD_OK) {
// It is.
return convert_mesh_data_object(data_obj, mesh);
}
// It isn't.
cerr << "Ignoring object of unknown type: " << get_object_name(obj)
<< "\n";
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh_data_object
// Access: Private
// Description: Converts the indicated data object, a child of a
// Mesh, to the appropriate egg structures.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
HRESULT hr;
// Determine what type of data object we have.
const GUID *type;
hr = obj->GetType(&type);
if (hr != DXFILE_OK) {
cerr << "Unable to get type of template\n";
return false;
}
if (*type == TID_D3DRMMeshNormals) {
if (!convert_mesh_normals(obj, mesh)) {
return false;
}
} else if (*type == TID_D3DRMMeshVertexColors) {
if (!convert_mesh_colors(obj, mesh)) {
return false;
}
} else if (*type == TID_D3DRMMeshTextureCoords) {
if (!convert_mesh_uvs(obj, mesh)) {
return false;
}
} else if (*type == TID_D3DRMMeshMaterialList) {
if (!convert_mesh_material_list(obj, mesh)) {
return false;
}
} else {
cerr << "Ignoring data object of unknown type: " << get_object_name(obj)
<< "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh_normals
// Access: Private
// Description: Converts the indicated MeshNormals template
// object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh_normals(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
if (!mesh.read_normal_data(raw_data)) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh_colors
// Access: Private
// Description: Converts the indicated MeshVertexColors template
// object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh_colors(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
if (!mesh.read_color_data(raw_data)) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh_uvs
// Access: Private
// Description: Converts the indicated MeshTextureCoords template
// object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh_uvs(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
if (!mesh.read_uv_data(raw_data)) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_mesh_material_list
// Access: Private
// Description: Converts the indicated MeshMaterialList template
// object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_mesh_material_list(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
HRESULT hr;
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
if (!mesh.read_material_list_data(raw_data)) {
return false;
}
// Now we need to process the children of the material list. These
// will be the materials.
LPDIRECTXFILEOBJECT child_obj;
hr = obj->GetNextObject(&child_obj);
while (hr == DXFILE_OK) {
if (!convert_material_list_object(child_obj, mesh)) {
return false;
}
hr = obj->GetNextObject(&child_obj);
}
if (hr != DXFILEERR_NOMOREOBJECTS) {
cerr << "Error extracting children of MeshMaterialList "
<< get_object_name(obj) << ".\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_material_list_object
// Access: Private
// Description: Converts the indicated object, a child of a
// MeshMaterialList.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_material_list_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh) {
HRESULT hr;
LPDIRECTXFILEDATA data_obj;
// See if the object is a data object.
hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
if (hr == DD_OK) {
// It is.
return convert_material_list_data_object(data_obj, mesh);
}
// It isn't.
cerr << "Ignoring object of unknown type: " << get_object_name(obj)
<< "\n";
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_material_list_data_object
// Access: Private
// Description: Converts the indicated data object, a child of a
// MeshMaterialList.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_material_list_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
HRESULT hr;
// Determine what type of data object we have.
const GUID *type;
hr = obj->GetType(&type);
if (hr != DXFILE_OK) {
cerr << "Unable to get type of template\n";
return false;
}
if (*type == TID_D3DRMMaterial) {
if (!convert_material(obj, mesh)) {
return false;
}
} else {
cerr << "Ignoring data object of unknown type: " << get_object_name(obj)
<< "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_material
// Access: Private
// Description: Converts the indicated Material template object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_material(LPDIRECTXFILEDATA obj, XFileMesh &mesh) {
HRESULT hr;
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
XFileMaterial *material = new XFileMaterial;
if (!material->read_material_data(raw_data)) {
delete material;
return false;
}
mesh.add_material(material);
// Now we need to process the children of the material. There
// should only be one, and it will be a texture.
LPDIRECTXFILEOBJECT child_obj;
hr = obj->GetNextObject(&child_obj);
while (hr == DXFILE_OK) {
if (!convert_material_object(child_obj, *material)) {
return false;
}
hr = obj->GetNextObject(&child_obj);
}
if (hr != DXFILEERR_NOMOREOBJECTS) {
cerr << "Error extracting children of Material "
<< get_object_name(obj) << ".\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_material_object
// Access: Private
// Description: Converts the indicated object, a child of a
// Material.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_material_object(LPDIRECTXFILEOBJECT obj, XFileMaterial &material) {
HRESULT hr;
LPDIRECTXFILEDATA data_obj;
// See if the object is a data object.
hr = obj->QueryInterface(IID_IDirectXFileData, (void **)&data_obj);
if (hr == DD_OK) {
// It is.
return convert_material_data_object(data_obj, material);
}
// It isn't.
cerr << "Ignoring object of unknown type: " << get_object_name(obj)
<< "\n";
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_material_data_object
// Access: Private
// Description: Converts the indicated data object, a child of a
// Material.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_material_data_object(LPDIRECTXFILEDATA obj, XFileMaterial &material) {
HRESULT hr;
// Determine what type of data object we have.
const GUID *type;
hr = obj->GetType(&type);
if (hr != DXFILE_OK) {
cerr << "Unable to get type of template\n";
return false;
}
if (*type == TID_D3DRMTextureFilename) {
if (!convert_texture(obj, material)) {
return false;
}
} else {
cerr << "Ignoring data object of unknown type: " << get_object_name(obj)
<< "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::convert_texture
// Access: Private
// Description: Converts the indicated TextureFilename template object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
convert_texture(LPDIRECTXFILEDATA obj, XFileMaterial &material) {
Datagram raw_data;
if (!get_data(obj, raw_data)) {
return false;
}
if (!material.read_texture_data(raw_data)) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::get_object_name
// Access: Private
// Description: Returns the name of the indicated object.
////////////////////////////////////////////////////////////////////
string XFileToEggConverter::
get_object_name(LPDIRECTXFILEOBJECT obj) {
HRESULT hr;
DWORD length = 0;
obj->GetName(NULL, &length);
if (length == 0) {
return string();
}
char *buffer = new char[length];
hr = obj->GetName(buffer, &length);
string result;
if (hr != DXFILE_OK) {
cerr << "Unable to get object name.\n";
} else {
result = buffer;
}
delete[] buffer;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: XFileToEggConverter::get_data
// Access: Private
// Description: Extracts out the raw data for the indicated object.
////////////////////////////////////////////////////////////////////
bool XFileToEggConverter::
get_data(LPDIRECTXFILEDATA obj, Datagram &raw_data) {
HRESULT hr;
DWORD length;
void *data;
hr = obj->GetData(NULL, &length, &data);
if (hr != DXFILE_OK) {
cerr << "Unable to get data for " << get_object_name(obj) << "\n";
return false;
}
raw_data.clear();
raw_data.append_data(data, length);
return true;
}

View File

@ -0,0 +1,87 @@
// Filename: xFileToEggConverter.h
// Created by: drose (21Jun01)
//
////////////////////////////////////////////////////////////////////
//
// 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 XFILETOEGGCONVERTER_H
#define XFILETOEGGCONVERTER_H
#include "pandatoolbase.h"
#include "somethingToEggConverter.h"
#include "eggTextureCollection.h"
#include "eggMaterialCollection.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d.h>
#include <dxfile.h>
#include <rmxfguid.h>
#undef WIN32_LEAN_AND_MEAN
class EggGroupNode;
class Datagram;
class XFileMesh;
class XFileMaterial;
////////////////////////////////////////////////////////////////////
// Class : XFileToEggConverter
// Description :
////////////////////////////////////////////////////////////////////
class XFileToEggConverter : public SomethingToEggConverter {
public:
XFileToEggConverter();
XFileToEggConverter(const XFileToEggConverter &copy);
~XFileToEggConverter();
virtual SomethingToEggConverter *make_copy();
virtual string get_name() const;
virtual string get_extension() const;
virtual bool convert_file(const Filename &filename);
void close();
private:
bool get_toplevel();
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_mesh(LPDIRECTXFILEDATA obj, EggGroupNode *egg_parent);
bool convert_mesh_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh);
bool convert_mesh_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_mesh_normals(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_mesh_colors(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_mesh_uvs(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_mesh_material_list(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_material_list_object(LPDIRECTXFILEOBJECT obj, XFileMesh &mesh);
bool convert_material_list_data_object(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_material(LPDIRECTXFILEDATA obj, XFileMesh &mesh);
bool convert_material_object(LPDIRECTXFILEOBJECT obj, XFileMaterial &material);
bool convert_material_data_object(LPDIRECTXFILEDATA obj, XFileMaterial &material);
bool convert_texture(LPDIRECTXFILEDATA obj, XFileMaterial &material);
string get_object_name(LPDIRECTXFILEOBJECT obj);
bool get_data(LPDIRECTXFILEDATA obj, Datagram &raw_data);
LPDIRECTXFILE _dx_file;
LPDIRECTXFILEENUMOBJECT _dx_file_enum;
EggTextureCollection _textures;
EggMaterialCollection _materials;
};
#endif

View File

@ -26,25 +26,45 @@
// Description:
////////////////////////////////////////////////////////////////////
XFileVertex::
XFileVertex(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
_has_color = true;
_has_uv = true;
XFileVertex() {
_has_color = false;
_has_uv = false;
_point.set(0.0, 0.0, 0.0);
_uv.set(0.0, 0.0);
_color.set(1.0, 1.0, 1.0, 1.0);
}
////////////////////////////////////////////////////////////////////
// Function: XFileVertex::set_from_egg
// Access: Public
// Description: Sets the structure up from the indicated egg data.
////////////////////////////////////////////////////////////////////
void XFileVertex::
set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
_point = LCAST(float, egg_vertex->get_pos3());
if (egg_vertex->has_uv()) {
_uv = LCAST(float, egg_vertex->get_uv());
} else {
_uv.set(0.0, 0.0);
_has_uv = false;
TexCoordd uv = egg_vertex->get_uv();
if (egg_prim->has_texture()) {
// Check if there's a texture matrix on the texture.
EggTexture *egg_tex = egg_prim->get_texture();
if (egg_tex->has_transform()) {
uv = uv * egg_tex->get_transform();
}
}
_uv[0] = uv[0];
// Windows draws the UV's upside-down.
_uv[1] = 1.0 - uv[1];
_has_uv = true;
}
if (egg_vertex->has_color()) {
_color = egg_vertex->get_color();
_has_color = true;
} else if (egg_prim->has_color()) {
_color = egg_prim->get_color();
} else {
_color.set(1.0, 1.0, 1.0, 1.0);
_has_color = false;
_has_color = true;
}
}

View File

@ -32,7 +32,8 @@ class EggPrimitive;
////////////////////////////////////////////////////////////////////
class XFileVertex {
public:
XFileVertex(EggVertex *egg_vertex, EggPrimitive *egg_poly);
XFileVertex();
void set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_poly);
int compare_to(const XFileVertex &other) const;
Vertexf _point;