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