Panda3D
Loading...
Searching...
No Matches
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 */
36XFileMaker::
37XFileMaker() {
38 _mesh_index = 0;
39 _x_file = new XFile;
40}
41
42/**
43 *
44 */
45XFileMaker::
46~XFileMaker() {
47}
48
49/**
50 * Writes the .x file data to the indicated filename; returns true on success,
51 * false otherwise.
52 */
54write(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 */
64add_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 */
91bool XFileMaker::
92add_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 */
128bool XFileMaker::
129add_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 */
157bool XFileMaker::
158add_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 */
173bool XFileMaker::
174add_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 */
196bool XFileMaker::
197recurse_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 */
213XFileMesh *XFileMaker::
214get_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 */
233bool XFileMaker::
234finalize_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}
int make_bins(EggGroupNode *root_group)
The main entry point to EggBinMaker.
A type of group node that holds related subnodes.
Definition eggBin.h:26
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition eggData.h:37
A base class for nodes in the hierarchy that are not leaf nodes.
int remove_invalid_primitives(bool recurse)
Removes primitives at this level and below which appear to be degenerate; e.g.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition eggGroup.h:34
A base class for things that may be directly added into the egg hierarchy.
Definition eggNode.h:36
A single polygon.
Definition eggPolygon.h:24
A specialization on EggBinMaker for making polysets that share the same basic rendering characteristi...
const LMatrix4d & get_transform3d() const
Returns the overall transform as a 4x4 matrix.
bool has_transform() const
Returns true if the transform is nonempty, false if it is empty (no transform components have been ad...
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
This is an abstract base class for an XFileNode which is also an XFileDataObject.
bool write(const Filename &filename)
Writes the .x file data to the indicated filename; returns true on success, false otherwise.
bool add_tree(EggData *egg_data)
Adds the egg tree rooted at the indicated node to the X structure.
This is a collection of polygons; i.e.
Definition xFileMesh.h:45
XFileDataNode * make_x_mesh(XFileNode *x_parent, const std::string &suffix)
Creates an X structure corresponding to the mesh.
void add_polygon(EggPolygon *egg_poly)
Adds the indicated polygon to the mesh.
Definition xFileMesh.cxx:97
A single node of an X file.
Definition xFileNode.h:40
XFileDataNode * add_Frame(const std::string &name)
Creates a new Frame instance, as a child of this node.
XFileDataNode * add_FrameTransformMatrix(const LMatrix4d &mat)
Creates a new FrameTransformMatrix instance, as a child of this node.
This represents the complete contents of an X file (file.x) in memory.
Definition xFile.h:32
bool write(Filename filename) const
Opens the indicated filename for output and writes a parseable description of all the known distribut...
Definition xFile.cxx:130
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.