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