| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718 |
- // Filename: xFileMesh.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
- // [email protected] .
- //
- ////////////////////////////////////////////////////////////////////
- #include "xFileMesh.h"
- #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
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- XFileMesh::
- XFileMesh() {
- _has_normals = false;
- _has_colors = false;
- _has_uvs = false;
- _has_materials = false;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::Destructor
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- 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);
- delete vertex;
- }
- Normals::iterator ni;
- for (ni = _normals.begin(); ni != _normals.end(); ++ni) {
- 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();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::add_polygon
- // Access: Public
- // Description: Adds the indicated polygon to the mesh.
- ////////////////////////////////////////////////////////////////////
- void XFileMesh::
- add_polygon(EggPolygon *egg_poly) {
- XFileFace *face = new XFileFace;
- face->set_from_egg(this, egg_poly);
- _faces.push_back(face);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::add_vertex
- // Access: Public
- // Description: Creates a new XFileVertex, if one does not already
- // exist for the indicated vertex, and returns its
- // index.
- ////////////////////////////////////////////////////////////////////
- int XFileMesh::
- add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
- int next_index = _vertices.size();
- XFileVertex *vertex = new XFileVertex;
- vertex->set_from_egg(egg_vertex, egg_prim);
- if (vertex->_has_color) {
- _has_colors = true;
- }
- if (vertex->_has_uv) {
- _has_uvs = true;
- }
- pair<UniqueVertices::iterator, bool> result =
- _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index));
- if (result.second) {
- // Successfully added; this is a new vertex.
- _vertices.push_back(vertex);
- return next_index;
- } else {
- // Not successfully added; there is already a vertex with these
- // properties. Return that one instead.
- delete vertex;
- return (*result.first).second;
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::add_normal
- // Access: Public
- // Description: Creates a new XFileNormal, if one does not already
- // exist for the indicated normal, and returns its
- // index.
- ////////////////////////////////////////////////////////////////////
- int XFileMesh::
- add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
- int next_index = _normals.size();
- XFileNormal *normal = new XFileNormal;
- normal->set_from_egg(egg_vertex, egg_prim);
- if (normal->_has_normal) {
- _has_normals = true;
- }
- pair<UniqueNormals::iterator, bool> result =
- _unique_normals.insert(UniqueNormals::value_type(normal, next_index));
- if (result.second) {
- // Successfully added; this is a new normal.
- _normals.push_back(normal);
- return next_index;
- } else {
- // Not successfully added; there is already a normal with these
- // properties. Return that one instead.
- delete normal;
- return (*result.first).second;
- }
- }
- ////////////////////////////////////////////////////////////////////
- // 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
- // Description: Returns true if any of the vertices or faces added to
- // this mesh used a normal, false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool XFileMesh::
- has_normals() const {
- return _has_normals;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::has_colors
- // Access: Public
- // Description: Returns true if any of the vertices or faces added to
- // this mesh used a color, false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool XFileMesh::
- has_colors() const {
- return _has_colors;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::has_uvs
- // Access: Public
- // Description: Returns true if any of the vertices added to this
- // mesh used a texture coordinate, false otherwise.
- ////////////////////////////////////////////////////////////////////
- bool XFileMesh::
- 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
- // Description: Fills the datagram with the raw data for the DX
- // Mesh template.
- ////////////////////////////////////////////////////////////////////
- void XFileMesh::
- make_mesh_data(Datagram &raw_data) {
- raw_data.clear();
- raw_data.add_int32(_vertices.size());
-
- Vertices::const_iterator vi;
- for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
- XFileVertex *vertex = (*vi);
- const Vertexf &point = vertex->_point;
- raw_data.add_float32(point[0]);
- raw_data.add_float32(point[1]);
- raw_data.add_float32(point[2]);
- }
- 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->_vertices.size());
- XFileFace::Vertices::const_iterator fvi;
- for (fvi = face->_vertices.begin();
- fvi != face->_vertices.end();
- ++fvi) {
- raw_data.add_int32((*fvi)._vertex_index);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::make_normal_data
- // Access: Public
- // Description: Fills the datagram with the raw data for the DX
- // MeshNormals template.
- ////////////////////////////////////////////////////////////////////
- void XFileMesh::
- make_normal_data(Datagram &raw_data) {
- raw_data.clear();
- raw_data.add_int32(_normals.size());
-
- Normals::const_iterator ni;
- for (ni = _normals.begin(); ni != _normals.end(); ++ni) {
- XFileNormal *normal = (*ni);
- const Normalf &norm = normal->_normal;
- raw_data.add_float32(norm[0]);
- raw_data.add_float32(norm[1]);
- raw_data.add_float32(norm[2]);
- }
- 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->_vertices.size());
- XFileFace::Vertices::const_iterator fvi;
- for (fvi = face->_vertices.begin();
- fvi != face->_vertices.end();
- ++fvi) {
- raw_data.add_int32((*fvi)._normal_index);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::make_color_data
- // Access: Public
- // Description: Fills the datagram with the raw data for the DX
- // MeshVertexColors template.
- ////////////////////////////////////////////////////////////////////
- void XFileMesh::
- make_color_data(Datagram &raw_data) {
- raw_data.clear();
- raw_data.add_int32(_vertices.size());
-
- Vertices::const_iterator vi;
- int i = 0;
- for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
- XFileVertex *vertex = (*vi);
- const Colorf &color = vertex->_color;
- raw_data.add_int32(i);
- raw_data.add_float32(color[0]);
- raw_data.add_float32(color[1]);
- raw_data.add_float32(color[2]);
- raw_data.add_float32(color[3]);
- i++;
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: XFileMesh::make_uv_data
- // Access: Public
- // Description: Fills the datagram with the raw data for the DX
- // MeshTextureCoords template.
- ////////////////////////////////////////////////////////////////////
- void XFileMesh::
- make_uv_data(Datagram &raw_data) {
- raw_data.clear();
- raw_data.add_int32(_vertices.size());
-
- Vertices::const_iterator vi;
- for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
- XFileVertex *vertex = (*vi);
- const TexCoordf &uv = vertex->_uv;
- raw_data.add_float32(uv[0]);
- 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;
- }
|