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 }
EggVertex::get_index
int get_index() const
Returns the index number of the vertex within its pool.
Definition: eggVertex.I:277
EggVertexPool::get_vertex
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...
Definition: eggVertexPool.cxx:115
EggVertex::get_pos4
LPoint4d get_pos4() const
This is always valid, regardless of the value of get_num_dimensions.
Definition: eggVertex.I:145
WithOutputFile::get_output
std::ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout,...
Definition: withOutputFile.cxx:50
eggVertexPool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggPrimitive.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggToC
Definition: eggToC.h:30
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertex::get_num_dimensions
int get_num_dimensions() const
Returns the number of dimensions the vertex uses.
Definition: eggVertex.I:99
eggPolysetMaker.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggGroupNode
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
EggPrimitive
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
Definition: eggPrimitive.h:47
EggToSomething
This is the general base class for a file-converter program that reads some model file format and gen...
Definition: eggToSomething.h:26
EggAttributes::get_color
LColor get_color() const
Returns the color set on this particular attribute.
Definition: eggAttributes.I:91
ProgramBase::parse_command_line
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_...
Definition: programBase.cxx:274
ProgramBase::get_exec_command
std::string get_exec_command() const
Returns the command that invoked this program, as a shell-friendly string, suitable for pasting into ...
Definition: programBase.cxx:455
EggPolysetMaker::set_properties
void set_properties(int properties)
Sets the set of properties that determines which polygons are allowed to be grouped together into a s...
Definition: eggPolysetMaker.cxx:34
EggVertex
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition: eggVertex.h:39
eggVertex.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggGroupNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertexPool::get_highest_index
int get_highest_index() const
Returns the highest index number used by any vertex in the pool (except forward references).
Definition: eggVertexPool.cxx:156
EggVertex::get_uv
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition: eggVertex.I:179
EggVertex::has_uv
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition: eggVertex.I:158
eggBin.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggVertexPool
A collection of vertices.
Definition: eggVertexPool.h:41
EggBinMaker::make_bins
int make_bins(EggGroupNode *root_group)
The main entry point to EggBinMaker.
Definition: eggBinMaker.cxx:67
eggToC.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:35
EggPolysetMaker
A specialization on EggBinMaker for making polysets that share the same basic rendering characteristi...
Definition: eggPolysetMaker.h:32
EggBin
A type of group node that holds related subnodes.
Definition: eggBin.h:26
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
EggPrimitive::get_pool
get_pool
Returns the vertex pool associated with the vertices of the primitive, or NULL if the primitive has n...
Definition: eggPrimitive.h:192
eggPolygon.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.