Panda3D
xFileMaker.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file xFileMaker.cxx
10  * @author drose
11  * @date 2001-06-19
12  */
13 
14 #include "xFileMaker.h"
15 #include "xFileMesh.h"
16 #include "xFileMaterial.h"
17 #include "config_xfile.h"
18 
19 #include "pnotify.h"
20 #include "eggGroupNode.h"
21 #include "eggGroup.h"
22 #include "eggBin.h"
23 #include "eggPolysetMaker.h"
24 #include "eggVertexPool.h"
25 #include "eggVertex.h"
26 #include "eggPolygon.h"
27 #include "eggData.h"
28 #include "pvector.h"
29 #include "vector_int.h"
30 #include "string_utils.h"
31 #include "datagram.h"
32 
33 /**
34  *
35  */
36 XFileMaker::
37 XFileMaker() {
38  _mesh_index = 0;
39  _x_file = new XFile;
40 }
41 
42 /**
43  *
44  */
45 XFileMaker::
46 ~XFileMaker() {
47 }
48 
49 /**
50  * Writes the .x file data to the indicated filename; returns true on success,
51  * false otherwise.
52  */
53 bool XFileMaker::
54 write(const Filename &filename) {
55  return _x_file->write(filename);
56 }
57 
58 /**
59  * Adds the egg tree rooted at the indicated node to the X structure. This
60  * may be somewhat destructive of the egg tree. Returns true on success,
61  * false on failure.
62  */
63 bool XFileMaker::
64 add_tree(EggData *egg_data) {
65  _meshes.clear();
66 
67  // Now collect all the polygons together into polysets.
68  EggPolysetMaker pmaker;
69  pmaker.make_bins(egg_data);
70 
71  // And now we're ready to traverse the egg hierarchy.
72  if (!recurse_nodes(egg_data, _x_file)) {
73  return false;
74  }
75 
76  // Create X structures for all of the meshes we built up.
77  Meshes::iterator mi;
78  for (mi = _meshes.begin(); mi != _meshes.end(); ++mi) {
79  if (!finalize_mesh((*mi).first, (*mi).second)) {
80  return false;
81  }
82  }
83  _meshes.clear();
84 
85  return true;
86 }
87 
88 /**
89  * Adds the node to the DX structure, in whatever form it is supported.
90  */
91 bool XFileMaker::
92 add_node(EggNode *egg_node, XFileNode *x_parent) {
93  if (egg_node->is_of_type(EggBin::get_class_type())) {
94  return add_bin(DCAST(EggBin, egg_node), x_parent);
95 
96  } else if (egg_node->is_of_type(EggGroup::get_class_type())) {
97  return add_group(DCAST(EggGroup, egg_node), x_parent);
98 
99  } else if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
100  // A grouping node of some kind.
101  EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
102 
103  if (xfile_one_mesh) {
104  // Don't create any additional frames representing the egg hierarchy.
105  if (!recurse_nodes(egg_group, x_parent)) {
106  return false;
107  }
108 
109  } else {
110  // Create a Frame for each EggGroup.
111  XFileDataNode *x_frame = x_parent->add_Frame(egg_group->get_name());
112 
113  if (!recurse_nodes(egg_group, x_frame)) {
114  return false;
115  }
116  }
117 
118  return true;
119  }
120 
121  // Some unsupported node type. Ignore it.
122  return true;
123 }
124 
125 /**
126  * Adds a frame for the indicated group node.
127  */
128 bool XFileMaker::
129 add_group(EggGroup *egg_group, XFileNode *x_parent) {
130  if (xfile_one_mesh) {
131  // Don't create any additional frames representing the egg hierarchy.
132  if (!recurse_nodes(egg_group, x_parent)) {
133  return false;
134  }
135 
136  } else {
137  // Create a frame for each EggGroup.
138  XFileDataNode *x_frame = x_parent->add_Frame(egg_group->get_name());
139 
140  // Set the transform on the frame, if we have one.
141  if (egg_group->has_transform()) {
142  x_frame->add_FrameTransformMatrix(egg_group->get_transform3d());
143  }
144 
145  if (!recurse_nodes(egg_group, x_frame)) {
146  return false;
147  }
148  }
149 
150  return true;
151 }
152 
153 /**
154  * Determines what kind of object needs to be added for the indicated bin
155  * node.
156  */
157 bool XFileMaker::
158 add_bin(EggBin *egg_bin, XFileNode *x_parent) {
159  switch (egg_bin->get_bin_number()) {
160  case EggPolysetMaker::BN_polyset:
161  return add_polyset(egg_bin, x_parent);
162  }
163 
164  xfile_cat.error()
165  << "Unexpected bin type " << egg_bin->get_bin_number() << "\n";
166  return false;
167 }
168 
169 /**
170  * Adds a mesh object corresponding to the collection of polygons within the
171  * indicated bin.
172  */
173 bool XFileMaker::
174 add_polyset(EggBin *egg_bin, XFileNode *x_parent) {
175  // Make sure that all our polygons are reasonable.
176  egg_bin->remove_invalid_primitives(true);
177 
178  XFileMesh *mesh = get_mesh(x_parent);
179 
180  EggGroupNode::iterator ci;
181  for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
182  EggPolygon *poly;
183  DCAST_INTO_R(poly, *ci, false);
184 
185  mesh->add_polygon(poly);
186  }
187 
188  return true;
189 }
190 
191 
192 /**
193  * Adds each child of the indicated Node as a child of the indicated DX
194  * object.
195  */
196 bool XFileMaker::
197 recurse_nodes(EggGroupNode *egg_node, XFileNode *x_parent) {
198  EggGroupNode::iterator ci;
199  for (ci = egg_node->begin(); ci != egg_node->end(); ++ci) {
200  EggNode *child = (*ci);
201  if (!add_node(child, x_parent)) {
202  return false;
203  }
204  }
205 
206  return true;
207 }
208 
209 /**
210  * Returns a suitable XFileMesh object for creating meshes within the
211  * indicated x_parent object.
212  */
213 XFileMesh *XFileMaker::
214 get_mesh(XFileNode *x_parent) {
215  Meshes::iterator mi = _meshes.find(x_parent);
216  if (mi != _meshes.end()) {
217  // We've already started working on this x_parent before; use the same
218  // mesh object.
219  return (*mi).second;
220  }
221 
222  // We haven't seen this x_parent before; create a new mesh object.
223  XFileMesh *mesh = new XFileMesh;
224  _meshes.insert(Meshes::value_type(x_parent, mesh));
225  return mesh;
226 }
227 
228 
229 /**
230  * Creates the actual X structures corresponding to the indicated XFileMesh
231  * object.
232  */
233 bool XFileMaker::
234 finalize_mesh(XFileNode *x_parent, XFileMesh *mesh) {
235  // Get a unique number for each mesh.
236  _mesh_index++;
237  std::string mesh_index = format_string(_mesh_index);
238 
239  // Finally, create the Mesh object.
240  mesh->make_x_mesh(x_parent, mesh_index);
241 
242  return true;
243 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const LMatrix4d & get_transform3d() const
Returns the overall transform as a 4x4 matrix.
Definition: eggTransform.I:212
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
XFileDataNode * add_Frame(const std::string &name)
Creates a new Frame instance, as a child of this node.
Definition: xFileNode.cxx:421
This is a collection of polygons; i.e.
Definition: xFileMesh.h:45
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool add_tree(EggData *egg_data)
Adds the egg tree rooted at the indicated node to the X structure.
Definition: xFileMaker.cxx:64
void add_polygon(EggPolygon *egg_poly)
Adds the indicated polygon to the mesh.
Definition: xFileMesh.cxx:97
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
A single node of an X file.
Definition: xFileNode.h:39
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int remove_invalid_primitives(bool recurse)
Removes primitives at this level and below which appear to be degenerate; e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
XFileDataNode * add_FrameTransformMatrix(const LMatrix4d &mat)
Creates a new FrameTransformMatrix instance, as a child of this node.
Definition: xFileNode.cxx:436
A single polygon.
Definition: eggPolygon.h:24
XFileDataNode * make_x_mesh(XFileNode *x_parent, const std::string &suffix)
Creates an X structure corresponding to the mesh.
Definition: xFileMesh.cxx:449
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:35
This is an abstract base class for an XFileNode which is also an XFileDataObject.
Definition: xFileDataNode.h:33
int make_bins(EggGroupNode *root_group)
The main entry point to EggBinMaker.
Definition: eggBinMaker.cxx:67
A specialization on EggBinMaker for making polysets that share the same basic rendering characteristi...
This represents the complete contents of an X file (file.x) in memory.
Definition: xFile.h:32
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool write(const Filename &filename)
Writes the .x file data to the indicated filename; returns true on success, false otherwise.
Definition: xFileMaker.cxx:54
A type of group node that holds related subnodes.
Definition: eggBin.h:26
bool has_transform() const
Returns true if the transform is nonempty, false if it is empty (no transform components have been ad...
Definition: eggTransform.I:143