Panda3D
eggToC.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 eggToC.cxx
10  * @author drose
11  * @date 2001-08-03
12  */
13 
14 #include "eggToC.h"
15 
16 #include "eggVertexPool.h"
17 #include "eggVertex.h"
18 #include "eggPolygon.h"
19 #include "eggPrimitive.h"
20 #include "eggGroupNode.h"
21 #include "eggPolysetMaker.h"
22 #include "eggBin.h"
23 #include "string_utils.h"
24 
25 using std::ostream;
26 using std::string;
27 
28 /**
29  *
30  */
31 EggToC::
32 EggToC() :
33  EggToSomething("C", ".c", true, true)
34 {
35  set_program_brief("convert .egg geometry into compilable C tables");
36  set_program_description
37  ("This program reads Egg files and outputs code that will almost "
38  "compile as a C or C++ program. You get to define the data structures "
39  "for the program after the fact; the program only generates tables "
40  "of vertices and polygons.");
41 
42  // -f is always in effect for egg2c. It doesn't make sense to provide it as
43  // an option to the user.
44  remove_option("f");
45 
46  add_option
47  ("v", "", 0,
48  "Generate a table of vertex positions.",
49  &EggToC::dispatch_none, &_vertices);
50 
51  add_option
52  ("u", "", 0,
53  "Generate a table of UV's per each vertex.",
54  &EggToC::dispatch_none, &_uvs);
55 
56  add_option
57  ("vn", "", 0,
58  "Generate a table of normals per each vertex.",
59  &EggToC::dispatch_none, &_vertex_normals);
60 
61  add_option
62  ("vc", "", 0,
63  "Generate a table of colors per each vertex.",
64  &EggToC::dispatch_none, &_vertex_colors);
65 
66  add_option
67  ("p", "", 0,
68  "Generate a table of polygons that index into the above tables.",
69  &EggToC::dispatch_none, &_polygons);
70 
71  add_option
72  ("pn", "", 0,
73  "Generate a table of normals per each polygon.",
74  &EggToC::dispatch_none, &_polygon_normals);
75 
76  add_option
77  ("pc", "", 0,
78  "Generate a table of colors per each polygon.",
79  &EggToC::dispatch_none, &_polygon_colors);
80 
81  add_option
82  ("t", "", 0,
83  "Output only triangles by subdividing higher-order polygons.",
84  &EggToC::dispatch_none, &_triangulate_polygons);
85 }
86 
87 /**
88  *
89  */
90 void EggToC::
91 run() {
92  nout << "Removing invalid primitives.\n";
93  int num_removed = _data->remove_invalid_primitives(true);
94  nout << " (" << num_removed << " removed.)\n";
95 
96  if (_triangulate_polygons) {
97  nout << "Triangulating polygons.\n";
98  int num_produced = _data->triangulate_polygons(~0);
99  nout << " (" << num_produced << " triangles produced.)\n";
100  }
101 
102  _data->apply_texmats();
103  _data->flatten_transforms();
104  _data->remove_unused_vertices(true);
105 
106  // Collect all the polygons together into polysets.
107  EggPolysetMaker pmaker;
108  pmaker.set_properties(0);
109  pmaker.make_bins(_data);
110 
111  get_output()
112  << "/*\n"
113  << " * Generated by:\n"
114  << " * " << get_exec_command() << "\n"
115  << " *\n"
116  << " */\n\n";
117 
118  _next_vpool_index = 0;
119  _next_bin_index = 0;
120  traverse(_data);
121 }
122 
123 /**
124  *
125  */
126 void EggToC::
127 traverse(EggNode *node) {
128  if (node->is_of_type(EggVertexPool::get_class_type())) {
129  write_vertex_pool(DCAST(EggVertexPool, node));
130 
131  } else if (node->is_of_type(EggBin::get_class_type())) {
132  write_bin(DCAST(EggBin, node));
133 
134  } else if (node->is_of_type(EggGroupNode::get_class_type())) {
135  EggGroupNode *group = DCAST(EggGroupNode, node);
136 
137  EggGroupNode::const_iterator ci;
138  for (ci = group->begin(); ci != group->end(); ++ci) {
139  traverse(*ci);
140  }
141  }
142 }
143 
144 /**
145  *
146  */
147 void EggToC::
148 write_vertex_pool(EggVertexPool *vpool) {
149  int highest_index = vpool->get_highest_index();
150  int i;
151 
152  ostream &out = get_output();
153  out << "/* Vertex pool index " << _next_vpool_index
154  << ": " << vpool->get_name() << " */\n";
155  _vertex_pools[vpool] = _next_vpool_index;
156  _next_vpool_index++;
157 
158  if (_vertices) {
159  out << "/* Vertex definition for " << vpool->get_name() << " */\n"
160  << "vertex vertices_" << vpool->get_name() << "[" << highest_index
161  << "] = {\n";
162  for (i = 0; i < highest_index; i++) {
163  EggVertex *vert = vpool->get_vertex(i);
164  if (vert == nullptr) {
165  out << " vertex(), /* " << i << " */\n";
166  } else {
167  LPoint4d p = vert->get_pos4();
168  switch (vert->get_num_dimensions()) {
169  case 1:
170  out << " vertex(" << p[0] << "), /* " << i << " */\n";
171  break;
172 
173  case 2:
174  out << " vertex(" << p[0] << ", " << p[1]
175  << "), /* " << i << " */\n";
176  break;
177 
178  case 3:
179  out << " vertex(" << p[0] << ", " << p[1] << ", " << p[2]
180  << "), /* " << i << " */\n";
181  break;
182 
183  case 4:
184  out << " vertex(" << p[0] << ", " << p[1] << ", " << p[2]
185  << ", " << p[3] << "), /* " << i << " */\n";
186  break;
187 
188  default:
189  out << " vertex(), /* error */\n";
190  }
191  }
192  }
193  out << "};\n\n";
194  }
195 
196  if (_uvs) {
197  out << "/* UV's for " << vpool->get_name() << " */\n"
198  << "uv uvs_" << vpool->get_name() << "[" << highest_index
199  << "] = {\n";
200  for (i = 0; i < highest_index; i++) {
201  EggVertex *vert = vpool->get_vertex(i);
202  if (vert == nullptr || !vert->has_uv()) {
203  out << " uv(), /* " << i << " */\n";
204  } else {
205  LTexCoordd uv = vert->get_uv();
206  out << " uv(" << uv[0] << ", " << uv[1]
207  << "), /* " << i << " */\n";
208  }
209  }
210  out << "};\n\n";
211  }
212 
213  if (_vertex_normals) {
214  out << "/* Vertex normals for " << vpool->get_name() << " */\n"
215  << "normal normals_" << vpool->get_name() << "[" << highest_index
216  << "] = {\n";
217  for (i = 0; i < highest_index; i++) {
218  EggVertex *vert = vpool->get_vertex(i);
219  if (vert == nullptr || !vert->has_normal()) {
220  out << " normal(), /* " << i << " */\n";
221  } else {
222  LNormald n = vert->get_normal();
223  out << " normal(" << n[0] << ", " << n[1] << ", " << n[2]
224  << "), /* " << i << " */\n";
225  }
226  }
227  out << "};\n\n";
228  }
229 
230  if (_vertex_colors) {
231  out << "/* Vertex colors for " << vpool->get_name() << " */\n"
232  << "color colors_" << vpool->get_name() << "[" << highest_index
233  << "] = {\n";
234  for (i = 0; i < highest_index; i++) {
235  EggVertex *vert = vpool->get_vertex(i);
236  if (vert == nullptr || !vert->has_color()) {
237  out << " color(), /* " << i << " */\n";
238  } else {
239  LColor c = vert->get_color();
240  out << " color(" << c[0] << ", " << c[1] << ", " << c[2]
241  << ", " << c[3] << "), /* " << i << " */\n";
242  }
243  }
244  out << "};\n\n";
245  }
246 }
247 
248 
249 /**
250  *
251  */
252 void EggToC::
253 write_bin(EggBin *bin) {
254  ostream &out = get_output();
255  string bin_name = bin->get_name();
256  if (bin_name.empty()) {
257  bin_name = format_string(_next_bin_index);
258  _next_bin_index++;
259  }
260 
261  out << "/* Polygon group " << bin_name << " */\n";
262 
263  size_t num_children = bin->size();
264 
265  if (_polygons) {
266  out << "/* Polygon definitions for " << bin_name << " */\n";
267  string prim_type = "polygon";
268  if (_triangulate_polygons) {
269  prim_type = "triangle";
270  }
271 
272  out << prim_type << " polys_" << bin_name << "[" << num_children
273  << "] = {\n";
274 
275  if (_triangulate_polygons) {
276  out << " /* vpool index, vertex0, vertex1, vertex2 */\n";
277  } else {
278  out << " /* vpool index, num vertices, vertex0, vertex1, vertex2, ... */\n";
279  }
280 
281  EggGroupNode::const_iterator ci;
282  size_t prim_index = 0;
283  for (ci = bin->begin(); ci != bin->end(); ++ci) {
284  EggNode *child = (*ci);
285  if (!child->is_of_type(EggPrimitive::get_class_type())) {
286  out << " " << prim_type << "(), /* error */\n";
287  } else {
288  EggPrimitive *prim = DCAST(EggPrimitive, child);
289  EggVertexPool *vpool = prim->get_pool();
290  int vpool_index = -1;
291  VertexPools::const_iterator pi = _vertex_pools.find(vpool);
292  if (pi != _vertex_pools.end()) {
293  vpool_index = (*pi).second;
294  }
295 
296  out << " " << prim_type << "(" << vpool_index;
297  if (!_triangulate_polygons) {
298  out << ", " << prim->size();
299  }
300  EggPrimitive::const_iterator vi;
301  for (vi = prim->begin(); vi != prim->end(); ++vi) {
302  EggVertex *vert = (*vi);
303  out << ", " << vert->get_index();
304  }
305  out << "), /* " << prim_index << " */\n";
306  prim_index++;
307  }
308  }
309  out << "};\n\n";
310  }
311 
312  if (_polygon_normals) {
313  ostream &out = get_output();
314  out << "/* Polygon normals for " << bin_name << " */\n";
315  out << "normal polys_" << bin_name << "[" << num_children
316  << "] = {\n";
317 
318  EggGroupNode::const_iterator ci;
319  size_t prim_index = 0;
320  for (ci = bin->begin(); ci != bin->end(); ++ci) {
321  EggNode *child = (*ci);
322  if (!child->is_of_type(EggPrimitive::get_class_type())) {
323  out << " normal(), /* error */\n";
324  } else {
325  EggPrimitive *prim = DCAST(EggPrimitive, child);
326  if (!prim->has_normal()) {
327  out << " normal(), /* " << prim_index << " */\n";
328  } else {
329  LNormald n = prim->get_normal();
330  out << " normal(" << n[0] << ", " << n[1] << ", " << n[2]
331  << "), /* " << prim_index << " */\n";
332  }
333  prim_index++;
334  }
335  }
336  out << "};\n\n";
337  }
338 
339  if (_polygon_colors) {
340  ostream &out = get_output();
341  out << "/* Polygon colors for " << bin_name << " */\n";
342  out << "color polys_" << bin_name << "[" << num_children
343  << "] = {\n";
344 
345  EggGroupNode::const_iterator ci;
346  size_t prim_index = 0;
347  for (ci = bin->begin(); ci != bin->end(); ++ci) {
348  EggNode *child = (*ci);
349  if (!child->is_of_type(EggPrimitive::get_class_type())) {
350  out << " color(), /* error */\n";
351  } else {
352  EggPrimitive *prim = DCAST(EggPrimitive, child);
353  if (!prim->has_color()) {
354  out << " color(), /* " << prim_index << " */\n";
355  } else {
356  LColor c = prim->get_color();
357  out << " color(" << c[0] << ", " << c[1] << ", " << c[2]
358  << ", " << c[3] << "), /* " << prim_index << " */\n";
359  }
360  prim_index++;
361  }
362  }
363  out << "};\n\n";
364  }
365 }
366 
367 
368 int main(int argc, char *argv[]) {
369  EggToC prog;
370  prog.parse_command_line(argc, argv);
371  prog.run();
372  return 0;
373 }
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:47
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_dimensions() const
Returns the number of dimensions the vertex uses.
Definition: eggVertex.I:99
void set_properties(int properties)
Sets the set of properties that determines which polygons are allowed to be grouped together into a s...
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
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.
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition: eggVertex.I:179
EggVertex * get_vertex(int index) const
Returns the vertex in the pool with the indicated index number, or NULL if no vertices have that inde...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Definition: eggToC.h:30
LColor get_color() const
Returns the color set on this particular attribute.
Definition: eggAttributes.I:91
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:277
int get_highest_index() const
Returns the highest index number used by any vertex in the pool (except forward references).
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::string get_exec_command() const
Returns the command that invoked this program, as a shell-friendly string, suitable for pasting into ...
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:158
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_pool
Returns the vertex pool associated with the vertices of the primitive, or NULL if the primitive has n...
Definition: eggPrimitive.h:192
This is the general base class for a file-converter program that reads some model file format and gen...
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:35
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...
LPoint4d get_pos4() const
This is always valid, regardless of the value of get_num_dimensions.
Definition: eggVertex.I:145
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.
std::ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout,...
A collection of vertices.
Definition: eggVertexPool.h:41
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A type of group node that holds related subnodes.
Definition: eggBin.h:26