Panda3D

eggBase.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 eggBase.cxx
10 * @author drose
11 * @date 2000-02-14
12 */
13
14 #include "eggBase.h"
15
16 #include "eggGroupNode.h"
17 #include "eggTexture.h"
18 #include "eggFilenameNode.h"
19 #include "eggComment.h"
20 #include "dcast.h"
21 #include "string_utils.h"
22
23 using std::string;
24
25 /**
26 *
27 */
28 EggBase::
29 EggBase() {
30 add_option
31 ("cs", "coordinate-system", 80,
32 "Specify the coordinate system to operate in. This may be one of "
33 "'y-up', 'z-up', 'y-up-left', or 'z-up-left'.",
34 &EggBase::dispatch_coordinate_system,
35 &_got_coordinate_system, &_coordinate_system);
36
37 _normals_mode = NM_preserve;
38 _normals_threshold = 0.0;
39
40 _got_tbnall = false;
41 _got_tbnauto = false;
42 _make_points = false;
43
44 _got_transform = false;
45 _transform = LMatrix4d::ident_mat();
46
47 _got_coordinate_system = false;
48 _coordinate_system = CS_yup_right;
49
50 _noabs = false;
51 }
52
53 /**
54 * Adds -no, -np, etc. as valid options for this program. If the user
55 * specifies one of the options on the command line, the normals will be
56 * adjusted when the egg file is written out.
57 */
58 void EggBase::
59 add_normals_options() {
60 static NormalsMode strip = NM_strip;
61 static NormalsMode polygon = NM_polygon;
62 static NormalsMode vertex = NM_vertex;
63 static NormalsMode preserve = NM_preserve;
64
65 add_option
66 ("no", "", 48,
67 "Strip all normals.",
68 &EggBase::dispatch_normals, nullptr, &strip);
69
70 add_option
71 ("np", "", 48,
72 "Strip existing normals and redefine polygon normals.",
73 &EggBase::dispatch_normals, nullptr, &polygon);
74
75 add_option
76 ("nv", "threshold", 48,
77 "Strip existing normals and redefine vertex normals. Consider an edge "
78 "between adjacent polygons to be smooth if the angle between them "
79 "is less than threshold degrees.",
80 &EggBase::dispatch_normals, nullptr, &vertex);
81
82 add_option
83 ("nn", "", 48,
84 "Preserve normals exactly as they are. This is the default.",
85 &EggBase::dispatch_normals, nullptr, &preserve);
86
87 add_option
88 ("tbn", "name", 48,
89 "Compute tangent and binormal for the named texture coordinate "
90 "set(s). The name may include wildcard characters such as * and ?. "
91 "The normal must already exist or have been computed via one of the "
92 "above options. The tangent and binormal are used to implement "
93 "bump mapping and related texture-based lighting effects. This option "
94 "may be repeated as necessary to name multiple texture coordinate sets.",
95 &EggBase::dispatch_vector_string, nullptr, &_tbn_names);
96
97 add_option
98 ("tbnall", "", 48,
99 "Compute tangent and binormal for all texture coordinate "
100 "sets. This is equivalent to -tbn \"*\".",
101 &EggBase::dispatch_none, &_got_tbnall);
102
103 add_option
104 ("tbnauto", "", 48,
105 "Compute tangent and binormal for all normal maps. ",
106 &EggBase::dispatch_none, &_got_tbnauto);
107 }
108
109 /**
110 * Adds -points as a valid option for this program.
111 */
112 void EggBase::
113 add_points_options() {
114 add_option
115 ("points", "", 46,
116 "Construct <PointLight> entries for any unreferenced vertices, to make them visible.",
117 &EggBase::dispatch_none, &_make_points);
118 }
119
120 /**
121 * Adds -TS, -TT, etc. as valid options for this program. If the user
122 * specifies one of the options on the command line, the data will be
123 * transformed when the egg file is written out.
124 */
125 void EggBase::
126 add_transform_options() {
127 add_option
128 ("TS", "sx[,sy,sz]", 49,
129 "Scale the model uniformly by the given factor (if only one number "
130 "is given) or in each axis by sx, sy, sz (if three numbers are given).",
131 &EggBase::dispatch_scale, &_got_transform, &_transform);
132
133 add_option
134 ("TR", "x,y,z", 49,
135 "Rotate the model x degrees about the x axis, then y degrees about the "
136 "y axis, and then z degrees about the z axis.",
137 &EggBase::dispatch_rotate_xyz, &_got_transform, &_transform);
138
139 add_option
140 ("TA", "angle,x,y,z", 49,
141 "Rotate the model angle degrees counterclockwise about the given "
142 "axis.",
143 &EggBase::dispatch_rotate_axis, &_got_transform, &_transform);
144
145 add_option
146 ("TT", "x,y,z", 49,
147 "Translate the model by the indicated amount.\n\n"
148 "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
149 "applied in the order they are encountered on the command line.",
150 &EggBase::dispatch_translate, &_got_transform, &_transform);
151 }
152
153 /**
154 * Recursively walks the egg hierarchy. Any filenames encountered are
155 * replaced according to the indicated PathReplace.
156 */
157 void EggBase::
158 convert_paths(EggNode *node, PathReplace *path_replace,
159 const DSearchPath &additional_path) {
160 if (node->is_of_type(EggTexture::get_class_type())) {
161 EggTexture *egg_tex = DCAST(EggTexture, node);
162 Filename fullpath, outpath;
163 path_replace->full_convert_path(egg_tex->get_filename(), additional_path,
164 fullpath, outpath);
165 egg_tex->set_filename(outpath);
166 egg_tex->set_fullpath(fullpath);
167
168 if (egg_tex->has_alpha_filename()) {
169 Filename alpha_fullpath, alpha_outpath;
170 path_replace->full_convert_path(egg_tex->get_alpha_filename(), additional_path,
171 alpha_fullpath, alpha_outpath);
172 egg_tex->set_alpha_filename(alpha_outpath);
173 egg_tex->set_alpha_fullpath(alpha_fullpath);
174 }
175
176 } else if (node->is_of_type(EggFilenameNode::get_class_type())) {
177 EggFilenameNode *egg_fnode = DCAST(EggFilenameNode, node);
178
179 Filename fullpath, outpath;
180 path_replace->full_convert_path(egg_fnode->get_filename(), additional_path,
181 fullpath, outpath);
182 egg_fnode->set_filename(outpath);
183 egg_fnode->set_fullpath(fullpath);
184
185 } else if (node->is_of_type(EggGroupNode::get_class_type())) {
186 EggGroupNode *egg_group = DCAST(EggGroupNode, node);
187 EggGroupNode::const_iterator ci;
188 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
189 convert_paths(*ci, path_replace, additional_path);
190 }
191 }
192 }
193
194 /**
195 * Inserts a comment into the beginning of the indicated egg file
196 * corresponding to the command line that invoked this program.
197 *
198 * Normally this function is called automatically when appropriate by
199 * EggWriter, and it's not necessary to call it explicitly.
200 */
201 void EggBase::
202 append_command_comment(EggData *data) {
203 append_command_comment(data, get_exec_command());
204 }
205
206 /**
207 * Inserts a comment into the beginning of the indicated egg file
208 * corresponding to the command line that invoked this program.
209 *
210 * Normally this function is called automatically when appropriate by
211 * EggWriter, and it's not necessary to call it explicitly.
212 */
213 void EggBase::
214 append_command_comment(EggData *data, const string &comment) {
215 data->insert(data->begin(), new EggComment("", comment));
216 }
217
218 /**
219 * Accepts one of -no, -np, etc. and sets _normals_mode as indicated. The
220 * void * argument is a pointer to a NormalsMode variable that indicates which
221 * switch was passed.
222 */
223 bool EggBase::
224 dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
225 EggBase *base = (EggBase *)self;
226 return base->ns_dispatch_normals(opt, arg, mode);
227 }
228
229 /**
230 * Accepts one of -no, -np, etc. and sets _normals_mode as indicated. The
231 * void * argument is a pointer to a NormalsMode variable that indicates which
232 * switch was passed.
233 */
234 bool EggBase::
235 ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
236 _normals_mode = *(NormalsMode *)mode;
237
238 if (_normals_mode == NM_vertex) {
239 if (!string_to_double(arg, _normals_threshold)) {
240 nout << "Invalid numeric parameter for -" << opt << ": "
241 << arg << "\n";
242 return false;
243 }
244 }
245
246 return true;
247 }
248
249 /**
250 * Handles -TS, which specifies a scale transform. Var is an LMatrix4d.
251 */
252 bool EggBase::
253 dispatch_scale(const string &opt, const string &arg, void *var) {
254 LMatrix4d *transform = (LMatrix4d *)var;
255
256 vector_string words;
257 tokenize(arg, words, ",");
258
259 double sx, sy, sz;
260
261 bool okflag = false;
262 if (words.size() == 3) {
263 okflag =
264 string_to_double(words[0], sx) &&
265 string_to_double(words[1], sy) &&
266 string_to_double(words[2], sz);
267
268 } else if (words.size() == 1) {
269 okflag =
270 string_to_double(words[0], sx);
271 sy = sz = sx;
272 }
273
274 if (!okflag) {
275 nout << "-" << opt
276 << " requires one or three numbers separated by commas.\n";
277 return false;
278 }
279
280 *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);
281
282 return true;
283 }
284
285 /**
286 * Handles -TR, which specifies a rotate transform about the three cardinal
287 * axes. Var is an LMatrix4d.
288 */
289 bool EggBase::
290 dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
291 EggBase *base = (EggBase *)self;
292 return base->ns_dispatch_rotate_xyz(opt, arg, var);
293 }
294
295 /**
296 * Handles -TR, which specifies a rotate transform about the three cardinal
297 * axes. Var is an LMatrix4d.
298 */
299 bool EggBase::
300 ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
301 LMatrix4d *transform = (LMatrix4d *)var;
302
303 vector_string words;
304 tokenize(arg, words, ",");
305
306 LVecBase3d xyz;
307
308 bool okflag = false;
309 if (words.size() == 3) {
310 okflag =
311 string_to_double(words[0], xyz[0]) &&
312 string_to_double(words[1], xyz[1]) &&
313 string_to_double(words[2], xyz[2]);
314 }
315
316 if (!okflag) {
317 nout << "-" << opt
318 << " requires three numbers separated by commas.\n";
319 return false;
320 }
321
322 LMatrix4d mat =
323 LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
324 LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
325 LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);
326
327 *transform = (*transform) * mat;
328
329 return true;
330 }
331
332 /**
333 * Handles -TA, which specifies a rotate transform about an arbitrary axis.
334 * Var is an LMatrix4d.
335 */
336 bool EggBase::
337 dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
338 EggBase *base = (EggBase *)self;
339 return base->ns_dispatch_rotate_axis(opt, arg, var);
340 }
341
342 /**
343 * Handles -TA, which specifies a rotate transform about an arbitrary axis.
344 * Var is an LMatrix4d.
345 */
346 bool EggBase::
347 ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
348 LMatrix4d *transform = (LMatrix4d *)var;
349
350 vector_string words;
351 tokenize(arg, words, ",");
352
353 double angle;
354 LVecBase3d axis;
355
356 bool okflag = false;
357 if (words.size() == 4) {
358 okflag =
359 string_to_double(words[0], angle) &&
360 string_to_double(words[1], axis[0]) &&
361 string_to_double(words[2], axis[1]) &&
362 string_to_double(words[3], axis[2]);
363 }
364
365 if (!okflag) {
366 nout << "-" << opt
367 << " requires four numbers separated by commas.\n";
368 return false;
369 }
370
371 *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);
372
373 return true;
374 }
375
376 /**
377 * Handles -TT, which specifies a translate transform. Var is an LMatrix4d.
378 */
379 bool EggBase::
380 dispatch_translate(const string &opt, const string &arg, void *var) {
381 LMatrix4d *transform = (LMatrix4d *)var;
382
383 vector_string words;
384 tokenize(arg, words, ",");
385
386 LVector3d trans;
387
388 bool okflag = false;
389 if (words.size() == 3) {
390 okflag =
391 string_to_double(words[0], trans[0]) &&
392 string_to_double(words[1], trans[1]) &&
393 string_to_double(words[2], trans[2]);
394 }
395
396 if (!okflag) {
397 nout << "-" << opt
398 << " requires three numbers separated by commas.\n";
399 return false;
400 }
401
402 *transform = (*transform) * LMatrix4d::translate_mat(trans);
403
404 return true;
405 }
DSearchPath
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition: dSearchPath.h:28
EggBase
This is a base class for both EggSingleBase and EggMultiBase.
Definition: eggBase.h:29
EggBase::add_points_options
void add_points_options()
Adds -points as a valid option for this program.
Definition: eggBase.cxx:113
EggBase::add_normals_options
void add_normals_options()
Adds -no, -np, etc.
Definition: eggBase.cxx:59
EggBase::convert_paths
static void convert_paths(EggNode *node, PathReplace *path_replace, const DSearchPath &additional_path)
Recursively walks the egg hierarchy.
Definition: eggBase.cxx:158
EggBase::add_transform_options
void add_transform_options()
Adds -TS, -TT, etc.
Definition: eggBase.cxx:126
EggComment
A comment that appears in an egg file within a <Comment> entry.
Definition: eggComment.h:24
EggData
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
EggFilenameNode
This is an egg node that contains a filename.
Definition: eggFilenameNode.h:27
EggFilenameNode::set_fullpath
void set_fullpath(const Filename &fullpath)
Records the full pathname to the file, for the benefit of get_fullpath().
Definition: eggFilenameNode.I:90
EggFilenameNode::get_filename
const Filename & get_filename() const
Returns a nonmodifiable reference to the filename.
Definition: eggFilenameNode.I:58
EggGroupNode
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:36
EggTexture
Defines a texture map that may be applied to geometry.
Definition: eggTexture.h:30
EggTexture::get_alpha_filename
get_alpha_filename
Returns the separate file assigned for the alpha channel.
Definition: eggTexture.h:347
EggTexture::set_alpha_fullpath
set_alpha_fullpath
Records the full pathname to the file, for the benefit of get_alpha_fullpath().
Definition: eggTexture.h:348
EggTexture::set_alpha_filename
set_alpha_filename
Specifies a separate file that will be loaded in with the 1- or 3-component texture and applied as th...
Definition: eggTexture.h:347
EggTexture::has_alpha_filename
has_alpha_filename
Returns true if a separate file for the alpha component has been applied, false otherwise.
Definition: eggTexture.h:347
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PathReplace
This encapsulates the user's command-line request to replace existing, incorrect pathnames to models ...
Definition: pathReplace.h:36
PathReplace::full_convert_path
void full_convert_path(const Filename &orig_filename, const DSearchPath &additional_path, Filename &resolved_path, Filename &output_path)
Converts the input path into two different forms: A resolved path, and an output path.
Definition: pathReplace.cxx:198
ProgramBase
This is intended to be the base class for most general-purpose utility programs in the PANDATOOL tree...
Definition: programBase.h:34
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:467
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
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggBase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggComment.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggFilenameNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggGroupNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggTexture.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string_to_double
double string_to_double(const string &str, string &tail)
A string-interface wrapper around the C library strtol().
Definition: string_utils.cxx:354
tokenize
void tokenize(const string &str, vector_string &words, const string &delimiters, bool discard_repeated_delimiters)
Chops the source string up into pieces delimited by any of the characters specified in delimiters.
Definition: string_utils.cxx:170
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.