36 XFileMesh(CoordinateSystem cs) : _cs(cs) {
40 _has_materials =
false;
41 _egg_parent =
nullptr;
57 Vertices::iterator vi;
58 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
63 for (ni = _normals.begin(); ni != _normals.end(); ++ni) {
67 Materials::iterator mi;
68 for (mi = _materials.begin(); mi != _materials.end(); ++mi) {
73 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
83 _unique_vertices.clear();
84 _unique_normals.clear();
85 _unique_materials.clear();
90 _has_materials =
false;
100 _faces.push_back(face);
109 int next_index = _vertices.size();
112 if (vertex->_has_color) {
115 if (vertex->_has_uv) {
119 std::pair<UniqueVertices::iterator, bool> result =
120 _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index));
124 _vertices.push_back(vertex);
130 return (*result.first).second;
141 int next_index = _normals.size();
144 if (normal->_has_normal) {
148 std::pair<UniqueNormals::iterator, bool> result =
149 _unique_normals.insert(UniqueNormals::value_type(normal, next_index));
153 _normals.push_back(normal);
159 return (*result.first).second;
169 int next_index = _materials.size();
173 _has_materials =
true;
176 std::pair<UniqueMaterials::iterator, bool> result =
177 _unique_materials.insert(UniqueMaterials::value_type(material, next_index));
181 _materials.push_back(material);
187 return (*result.first).second;
199 if (vertex->_has_color) {
202 if (vertex->_has_uv) {
206 int next_index = _vertices.size();
207 _unique_vertices.insert(UniqueVertices::value_type(vertex, next_index));
208 _vertices.push_back(vertex);
219 if (normal->_has_normal) {
223 int next_index = _normals.size();
224 _unique_normals.insert(UniqueNormals::value_type(normal, next_index));
225 _normals.push_back(normal);
237 _has_materials =
true;
240 int next_index = _materials.size();
241 _unique_materials.insert(UniqueMaterials::value_type(material, next_index));
242 _materials.push_back(material);
256 _egg_parent = egg_group;
265 nassertr(_egg_parent !=
nullptr,
false);
269 Faces::const_iterator fi;
270 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
277 XFileFace::Vertices::reverse_iterator vi;
278 for (vi = face->_vertices.rbegin(); vi != face->_vertices.rend(); ++vi) {
279 int vertex_index = (*vi)._vertex_index;
280 int normal_index = (*vi)._normal_index;
281 if (vertex_index < 0 || vertex_index >= (
int)_vertices.size()) {
283 <<
"Vertex index out of range in Mesh " << get_name() <<
"\n";
289 if (normal_index >= 0 && normal_index < (
int)_normals.size()) {
290 normal = _normals[normal_index];
296 temp_vtx.
set_pos(vertex->_point);
297 if (vertex->_has_color) {
298 temp_vtx.set_color(vertex->_color);
300 if (vertex->_has_uv) {
301 LTexCoordd uv = vertex->_uv;
307 if (normal !=
nullptr && normal->_has_normal) {
308 temp_vtx.set_normal(normal->_normal);
315 double net_weight = 0.0;
316 LMatrix4d weighted_transform(0.0, 0.0, 0.0, 0.0,
320 SkinWeights::const_iterator swi;
321 for (swi = _skin_weights.begin(); swi != _skin_weights.end(); ++swi) {
322 const SkinWeightsData &data = (*swi);
323 WeightMap::const_iterator wmi = data._weight_map.find(vertex_index);
324 if (wmi != data._weight_map.end()) {
326 if (joint !=
nullptr) {
327 double weight = (*wmi).second;
328 LMatrix4d mat = data._matrix_offset;
330 weighted_transform += mat * weight;
331 net_weight += weight;
336 if (net_weight == 0.0) {
345 weighted_transform /= net_weight;
355 int material_index = face->_material_index;
356 if (material_index >= 0 && material_index < (
int)_materials.size()) {
364 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
368 SkinWeights::const_iterator swi;
369 for (swi = _skin_weights.begin(); swi != _skin_weights.end(); ++swi) {
370 const SkinWeightsData &data = (*swi);
371 WeightMap::const_iterator wmi = data._weight_map.find(vertex_index);
372 if (wmi != data._weight_map.end()) {
374 if (joint !=
nullptr) {
375 double weight = (*wmi).second;
425 return _has_materials;
433 return _materials.size();
441 nassertr(n >= 0 && n < (
int)_materials.size(),
nullptr);
442 return _materials[n];
455 Vertices::const_iterator vi;
456 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
458 x_vertices.
add_Vector(x_mesh->get_x_file(), vertex->_point);
460 (*x_mesh)[
"nVertices"] = x_vertices.
size();
464 Faces::const_iterator fi;
465 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
469 XFileDataObject &x_faceVertexIndices = x_mesh_face[
"faceVertexIndices"];
470 XFileFace::Vertices::const_iterator fvi;
471 for (fvi = face->_vertices.begin();
472 fvi != face->_vertices.end();
474 x_faceVertexIndices.
add_int((*fvi)._vertex_index);
476 x_mesh_face[
"nFaceVertexIndices"] = x_faceVertexIndices.
size();
478 (*x_mesh)[
"nFaces"] = x_faces.
size();
511 Normals::const_iterator ni;
512 for (ni = _normals.begin(); ni != _normals.end(); ++ni) {
514 x_normals.
add_Vector(x_mesh->get_x_file(), normal->_normal);
516 (*x_meshNormals)[
"nNormals"] = x_normals.
size();
520 Faces::const_iterator fi;
521 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
525 XFileDataObject &x_faceVertexIndices = x_normals_face[
"faceVertexIndices"];
526 XFileFace::Vertices::const_iterator fvi;
527 for (fvi = face->_vertices.begin();
528 fvi != face->_vertices.end();
530 x_faceVertexIndices.
add_int((*fvi)._normal_index);
532 x_normals_face[
"nFaceVertexIndices"] = x_faceVertexIndices.
size();
534 (*x_meshNormals)[
"nFaceNormals"] = x_faces.
size();
536 return x_meshNormals;
548 Vertices::const_iterator vi;
550 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
552 const LColor &color = vertex->_color;
557 (*x_meshColors)[
"nVertexColors"] = x_colors.
size();
571 Vertices::const_iterator vi;
572 for (vi = _vertices.begin(); vi != _vertices.end(); ++vi) {
577 (*x_meshUvs)[
"nTextureCoords"] = x_uvs.
size();
593 Faces::const_iterator fi;
594 for (fi = _faces.begin(); fi != _faces.end(); ++fi) {
596 x_indexes.
add_int(face->_material_index);
599 (*x_meshMaterials)[
"nFaceIndexes"] = x_indexes.
size();
603 for (
size_t i = 0; i < _materials.size(); i++) {
607 suffix +
"_" + format_string(i));
610 (*x_meshMaterials)[
"nMaterials"] = (int)_materials.size();
612 return x_meshMaterials;
625 for (i = 0; i < vertices.
size(); i++) {
627 vertex->_point = vertices[i].
vec3();
632 for (i = 0; i < faces.
size(); i++) {
637 for (j = 0; j < faceIndices.
size(); j++) {
639 vertex._vertex_index = faceIndices[j].
i();
640 vertex._normal_index = -1;
642 face->_vertices.push_back(vertex);
644 _faces.push_back(face);
649 for (i = 0; i < num_objects; i++) {
692 if (xfile_cat.is_debug()) {
694 <<
"Ignoring mesh data object of unknown type: " 710 for (i = 0; i < normals.
size(); i++) {
712 normal->_normal = normals[i].
vec3();
713 normal->_has_normal =
true;
718 if (faceNormals.
size() != (int)_faces.size()) {
720 <<
"Incorrect number of faces in MeshNormals within " 721 << get_name() <<
"\n";
724 int num_normals = min(faceNormals.
size(), (int)_faces.size());
725 for (i = 0; i < num_normals; i++) {
728 const XFileDataObject &faceIndices = faceNormals[i][
"faceVertexIndices"];
730 if (faceIndices.
size() != (int)face->_vertices.size()) {
732 <<
"Incorrect number of vertices for face in MeshNormals within " 733 << get_name() <<
"\n";
736 int num_vertices = min(faceIndices.
size(), (int)face->_vertices.size());
737 for (j = 0; j < num_vertices; j++) {
738 face->_vertices[j]._normal_index = faceIndices[j].
i();
752 for (
int i = 0; i < vertexColors.
size(); i++) {
753 int vertex_index = vertexColors[i][
"index"].
i();
754 if (vertex_index < 0 || vertex_index >= (
int)_vertices.size()) {
756 <<
"Vertex index out of range in MeshVertexColors within " 757 << get_name() <<
"\n";
762 vertex->_color = LCAST(PN_stdfloat, vertexColors[i][
"indexColor"].vec4());
763 vertex->_has_color =
true;
776 if (textureCoords.
size() != (int)_vertices.size()) {
778 <<
"Wrong number of vertices in MeshTextureCoords within " 779 << get_name() <<
"\n";
782 int num_texcoords = min(textureCoords.
size(), (int)_vertices.size());
783 for (
int i = 0; i < num_texcoords; i++) {
785 vertex->_uv = textureCoords[i].
vec2();
786 vertex->_has_uv =
true;
799 _skin_weights.push_back(SkinWeightsData());
800 SkinWeightsData &data = _skin_weights.back();
802 data._joint_name = (*obj)[
"transformNodeName"].s();
807 if (weights.
size() != vertexIndices.
size()) {
809 <<
"Inconsistent number of vertices in SkinWeights within " << get_name() <<
"\n";
813 size_t num_weights = min(weights.
size(), vertexIndices.
size());
814 for (
size_t i = 0; i < num_weights; i++) {
815 int vindex = vertexIndices[i].
i();
816 double weight = weights[i].
d();
818 if (vindex < 0 || vindex > (
int)_vertices.size()) {
820 <<
"Illegal vertex index " << vindex <<
" in SkinWeights.\n";
823 data._weight_map[vindex] = weight;
827 data._matrix_offset = (*obj)[
"matrixOffset"][
"matrix"].mat4();
839 if (faceIndexes.
size() > (int)_faces.size()) {
841 <<
"Too many faces in MeshMaterialList within " << get_name() <<
"\n";
844 int material_index = -1;
846 while (i < faceIndexes.
size() && i < (int)_faces.size()) {
848 material_index = faceIndexes[i].
i();
849 face->_material_index = material_index;
855 while (i < (
int)_faces.size()) {
857 face->_material_index = material_index;
864 for (i = 0; i < num_objects; i++) {
875 if (xfile_cat.is_debug()) {
877 <<
"Ignoring material list object of unknown type: " A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
void clear()
Empties all data from the mesh.
XFileDataNode * make_x_colors(XFileNode *x_mesh, const std::string &suffix)
Creates a MeshVertexColors table for the mesh.
XFileDataNode * add_MeshTextureCoords(const std::string &name)
Creates a new MeshTextureCoords instance, as a child of this node.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool fill_mesh(XFileDataNode *obj)
Fills the structure based on the raw data from the X file's Mesh object.
XFileDataObject & add_int(int int_value)
Appends a new integer value to the data object, if it makes sense to do so.
XFileDataNode * add_MeshNormals(const std::string &name)
Creates a new MeshNormals instance, as a child of this node.
void set_pos(double pos)
Sets the vertex position.
bool has_normals() const
Returns true if any of the vertices or faces added to this mesh used a normal, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for nodes in the hierarchy that are not leaf nodes.
int i() const
Unambiguously returns the object's representation as an integer, or 0 if the object has no integer re...
This represents a single normal associated with an XFileFace.
bool has_uvs() const
Returns true if any of the vertices added to this mesh used a texture coordinate, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
XFileDataNode * make_x_material(XFileNode *x_meshMaterials, const std::string &suffix)
Creates a Material object for the material list.
bool fill_normals(XFileDataNode *obj)
Fills the structure based on the raw data from the MeshNormals template.
int add_vertex(EggVertex *egg_vertex, EggPrimitive *egg_prim)
Creates a new XFileVertex, if one does not already exist for the indicated vertex,...
void apply_to_egg(EggPrimitive *egg_prim, XFileToEggConverter *converter)
Applies the properties in the material to the indicated egg primitive.
int add_material(EggPrimitive *egg_prim)
Creates a new XFileMaterial, if one does not already exist for the indicated material,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
XFileDataObject & add_MeshFace(XFile *x_file)
Appends a new MeshFace instance.
XFileDataNode * make_x_material_list(XFileNode *x_mesh, const std::string &suffix)
Creates a MeshMaterialList table for the mesh.
void set_external_index(int external_index)
Sets a special index number that is associated with the EggVertex (but is not written to the egg file...
void set_from_egg(EggPrimitive *egg_prim)
Sets the structure up from the indicated egg data.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
XFileDataNode * add_Mesh(const std::string &name)
Creates a new Mesh instance, as a child of this node.
bool fill_material_list(XFileDataNode *obj)
Fills the structure based on the raw data from the MeshMaterialList template.
bool fill_skin_weights(XFileDataNode *obj)
Fills the structure based on the raw data from the SkinWeights template.
void set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_poly)
Sets the structure up from the indicated egg data.
int add_normal(EggVertex *egg_vertex, EggPrimitive *egg_prim)
Creates a new XFileNormal, if one does not already exist for the indicated normal,...
bool has_material() const
Returns true if this material represents something meaningful, or false if the default material is su...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_objects() const
Returns the list of child objects of this node.
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_polygon(EggPolygon *egg_poly)
Adds the indicated polygon to the mesh.
void set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim)
Sets the structure up from the indicated egg data.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
XFileMaterial * get_material(int n) const
Returns a pointer to the nth materials associated with the mesh.
XFileDataObject & add_Vector(XFile *x_file, const LVecBase3d &vector)
Appends a new Vector instance.
A single node of an X file.
bool fill_colors(XFileDataNode *obj)
Fills the structure based on the raw data from the MeshVertexColors template.
XFileDataObject & add_Coords2d(XFile *x_file, const LVecBase2d &coords)
Appends a new Coords2d instance.
XFileDataObject & add_IndexedColor(XFile *x_file, int index, const LColor &color)
Appends a new IndexedColor instance.
void transform(const LMatrix4d &mat)
Applies the indicated transformation matrix to the vertex.
void set_egg_parent(EggGroupNode *egg_parent)
Specifies the egg node that will eventually be the parent of this mesh, when create_polygons() is lat...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool fill_uvs(XFileDataNode *obj)
Fills the structure based on the raw data from the MeshTextureCoords template.
const LMatrix4d & get_node_to_vertex() const
Returns the transformation matrix suitable for converting vertices in the coordinate space of the nod...
bool fill_mesh_child(XFileDataNode *obj)
Fills the structure based on one of the children of the Mesh object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
XFileDataNode * make_x_uvs(XFileNode *x_mesh, const std::string &suffix)
Creates a MeshTextureCoords table for the mesh.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_from_egg(XFileMesh *mesh, EggPolygon *egg_poly)
Sets the structure up from the indicated egg data.
int size() const
Returns the number of nested data objects within this object.
const std::string & get_template_name() const
A convenience function to return the name of the template used to define this data object.
This represents a single vertex associated with an XFileFace.
XFileDataNode * make_x_mesh(XFileNode *x_parent, const std::string &suffix)
Creates an X structure corresponding to the mesh.
This represents a single face of an XFileMesh.
LVecBase2d vec2() const
Returns the object's representation as an LVecBase2d.
XFileDataNode * add_MeshVertexColors(const std::string &name)
Creates a new MeshVertexColors instance, as a child of this node.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
bool create_polygons(XFileToEggConverter *converter)
Creates a slew of EggPolygons according to the faces in the mesh, and adds them to the previously-ind...
This represents an X file "material", which consists of a color, lighting, and/or texture specificati...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is an abstract base class for an XFileNode which is also an XFileDataObject.
void ref_vertex(EggVertex *vert, double membership=1.0)
Adds the vertex to the set of those referenced by the group, at the indicated membership level.
bool has_colors() const
Returns true if any of the vertices or faces added to this mesh used a color, false otherwise.
EggGroup * find_joint(const std::string &joint_name)
This is called by set_animation_frame, for the purposes of building the frame data for the animation–...
int get_external_index() const
Returns the number set by set_external_index().
bool fill_material(XFileDataNode *obj)
Fills the structure based on the raw data from the X file's Material object.
XFileDataNode * get_object(int n) const
Returns the nth child object of this node.
XFileDataNode * add_MeshMaterialList(const std::string &name)
Creates a new MeshMaterialList instance, as a child of this node.
double d() const
Unambiguously returns the object's representation as a double, or 0.0 if the object has no double rep...
bool has_materials() const
Returns true if any of the faces added to this mesh used a real material, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool is_standard_object(const std::string &template_name) const
Returns true if this node represents an instance of the standard template with the indicated name,...
LVecBase3d vec3() const
Returns the object's representation as an LVecBase3d.
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
A collection of vertices.
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it.
void recompute_vertex_normals(double threshold, CoordinateSystem cs=CS_default)
Recomputes all the vertex normals for polygon geometry at this group node and below so that they accu...
The abstract base class for a number of different types of data elements that may be stored in the X ...
int get_num_materials() const
Returns the number of distinct materials associated with the mesh.
XFileDataNode * make_x_normals(XFileNode *x_mesh, const std::string &suffix)
Creates a MeshNormals table for the mesh.