Panda3D
Loading...
Searching...
No Matches
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
25using std::ostream;
26using std::string;
27
28/**
29 *
30 */
31EggToC::
32EggToC() :
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 */
90void EggToC::
91run() {
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 */
126void EggToC::
127traverse(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 */
147void EggToC::
148write_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 */
252void EggToC::
253write_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
368int main(int argc, char *argv[]) {
369 EggToC prog;
370 prog.parse_command_line(argc, argv);
371 prog.run();
372 return 0;
373}
LColor get_color() const
Returns the color set on this particular attribute.
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
A base class for nodes in the hierarchy that are not leaf nodes.
A base class for things that may be directly added into the egg hierarchy.
Definition eggNode.h:36
A specialization on EggBinMaker for making polysets that share the same basic rendering characteristi...
void set_properties(int properties)
Sets the set of properties that determines which polygons are allowed to be grouped together into a s...
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
get_pool
Returns the vertex pool associated with the vertices of the primitive, or NULL if the primitive has n...
This is the general base class for a file-converter program that reads some model file format and gen...
A collection of vertices.
int get_highest_index() const
Returns the highest index number used by any vertex in the pool (except forward references).
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...
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
Definition eggVertex.h:39
bool has_uv() const
Returns true if the vertex has an unnamed UV coordinate pair, false otherwise.
Definition eggVertex.I:158
int get_index() const
Returns the index number of the vertex within its pool.
Definition eggVertex.I:277
LTexCoordd get_uv() const
Returns the unnamed UV coordinate pair on the vertex.
Definition eggVertex.I:179
int get_num_dimensions() const
Returns the number of dimensions the vertex uses.
Definition eggVertex.I:99
LPoint4d get_pos4() const
This is always valid, regardless of the value of get_num_dimensions.
Definition eggVertex.I:145
std::string get_exec_command() const
Returns the command that invoked this program, as a shell-friendly string, suitable for pasting into ...
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_...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
std::ostream & get_output()
Returns an output stream that corresponds to the user's intended egg file output–either stdout,...
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.