Panda3D
 All Classes Functions Variables Enumerations
somethingToEgg.cxx
1 // Filename: somethingToEgg.cxx
2 // Created by: drose (15Feb00)
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 "somethingToEgg.h"
16 #include "somethingToEggConverter.h"
17 
18 #include "config_util.h"
19 
20 ////////////////////////////////////////////////////////////////////
21 // Function: SomethingToEgg::Constructor
22 // Access: Public
23 // Description: The first parameter to the constructor should be the
24 // one-word name of the file format that is to be read,
25 // for instance "OpenFlight" or "Alias". It's just used
26 // in printing error messages and such.
27 ////////////////////////////////////////////////////////////////////
29 SomethingToEgg(const string &format_name,
30  const string &preferred_extension,
31  bool allow_last_param, bool allow_stdout) :
32  EggConverter(format_name, preferred_extension, allow_last_param, allow_stdout)
33 {
34  clear_runlines();
35  if (_allow_last_param) {
36  add_runline("[opts] input" + _preferred_extension + " output.egg");
37  }
38  add_runline("[opts] -o output.egg input" + _preferred_extension);
39  if (_allow_stdout) {
40  add_runline("[opts] input" + _preferred_extension + " >output.egg");
41  }
42 
43  // -f doesn't make sense if we aren't reading egg files.
44  remove_option("f");
45 
46  redescribe_option
47  ("cs",
48  "Specify the coordinate system of the input " + _format_name +
49  " file. Normally, this can inferred from the file itself.");
50 
51  add_option
52  ("noabs", "", 0,
53  "Don't allow the input " + _format_name + " file to have absolute pathnames. "
54  "If it does, abort with an error. This option is designed to help "
55  "detect errors when populating or building a standalone model tree, "
56  "which should be self-contained and include only relative pathnames.",
57  &SomethingToEgg::dispatch_none, &_noabs);
58 
59  add_option
60  ("noexist", "", 0,
61  "Don't treat it as an error if the input file references pathnames "
62  "(e.g. textures) that don't exist. Normally, this will be flagged as "
63  "an error and the command aborted; with this option, an egg file will "
64  "be generated anyway, referencing pathnames that do not exist.",
65  &SomethingToEgg::dispatch_none, &_noexist);
66 
67  add_option
68  ("ignore", "", 0,
69  "Ignore non-fatal errors and generate an egg file anyway.",
70  &SomethingToEgg::dispatch_none, &_allow_errors);
71 
72  _input_units = DU_invalid;
73  _output_units = DU_invalid;
74  _animation_convert = AC_none;
75  _got_start_frame = false;
76  _got_end_frame = false;
77  _got_frame_inc = false;
78  _got_neutral_frame = false;
79  _got_input_frame_rate = false;
80  _got_output_frame_rate = false;
81  _merge_externals = false;
82 }
83 
84 ////////////////////////////////////////////////////////////////////
85 // Function: SomethingToEgg::add_units_options
86 // Access: Public
87 // Description: Adds -ui and -uo as valid options for this program.
88 // If the user specifies -uo and -ui, or just -uo and
89 // the program specifies -ui by setting _input_units,
90 // the indicated units conversion will be automatically
91 // applied before writing out the egg file.
92 ////////////////////////////////////////////////////////////////////
95  add_option
96  ("ui", "units", 40,
97  "Specify the units of the input " + _format_name +
98  " file. Normally, this can be inferred from the file itself.",
99  &SomethingToEgg::dispatch_units, NULL, &_input_units);
100 
101  add_option
102  ("uo", "units", 40,
103  "Specify the units of the resulting egg file. If this is "
104  "specified, the vertices in the egg file will be scaled as "
105  "necessary to make the appropriate units conversion; otherwise, "
106  "the vertices will be left as they are.",
107  &SomethingToEgg::dispatch_units, NULL, &_output_units);
108 }
109 
110 ////////////////////////////////////////////////////////////////////
111 // Function: SomethingToEgg::add_animation_options
112 // Access: Public
113 // Description: Adds options appropriate to animation packages.
114 ////////////////////////////////////////////////////////////////////
115 void SomethingToEgg::
117  add_option
118  ("a", "animation-mode", 40,
119  "Specifies how animation from the " + _format_name + " file is "
120  "converted to egg, if at all. At present, the following keywords "
121  "are supported: none, pose, flip, strobe, model, chan, or both. "
122  "The default is none, which means not to convert animation.",
123  &SomethingToEgg::dispatch_animation_convert, NULL, &_animation_convert);
124 
125  add_option
126  ("cn", "name", 40,
127  "Specifies the name of the animation character. This should match "
128  "between all of the model files and all of the channel files for a "
129  "particular model and its associated channels.",
130  &SomethingToEgg::dispatch_string, NULL, &_character_name);
131 
132  add_option
133  ("sf", "start-frame", 40,
134  "Specifies the starting frame of animation to extract. If omitted, "
135  "the first frame of the time slider will be used. For -a pose, this "
136  "is the one frame of animation to extract.",
137  &SomethingToEgg::dispatch_double, &_got_start_frame, &_start_frame);
138 
139  add_option
140  ("ef", "end-frame", 40,
141  "Specifies the ending frame of animation to extract. If omitted, "
142  "the last frame of the time slider will be used.",
143  &SomethingToEgg::dispatch_double, &_got_end_frame, &_end_frame);
144 
145  add_option
146  ("if", "frame-inc", 40,
147  "Specifies the increment between successive frames. If omitted, "
148  "this is taken from the time slider settings, or 1.0 if the time "
149  "slider does not specify.",
150  &SomethingToEgg::dispatch_double, &_got_frame_inc, &_frame_inc);
151 
152  add_option
153  ("nf", "neutral-frame", 40,
154  "Specifies the frame number to use for the neutral pose. The model "
155  "will be set to this frame before extracting out the neutral character. "
156  "If omitted, the current frame of the model is used. This is only "
157  "relevant for -a model or -a both.",
158  &SomethingToEgg::dispatch_double, &_got_neutral_frame, &_neutral_frame);
159 
160  add_option
161  ("fri", "fps", 40,
162  "Specify the frame rate (frames per second) of the input " + _format_name +
163  " file. Normally, this can be inferred from the file itself.",
164  &SomethingToEgg::dispatch_double, &_got_input_frame_rate, &_input_frame_rate);
165 
166  add_option
167  ("fro", "fps", 40,
168  "Specify the frame rate (frames per second) of the generated animation. "
169  "If this is specified, the animation speed is scaled by the appropriate "
170  "factor based on the frame rate of the input file (see -fri).",
171  &SomethingToEgg::dispatch_double, &_got_output_frame_rate, &_output_frame_rate);
172 }
173 
174 ////////////////////////////////////////////////////////////////////
175 // Function: SomethingToEgg::add_merge_externals_options
176 // Access: Public
177 // Description: Adds -f.
178 ////////////////////////////////////////////////////////////////////
179 void SomethingToEgg::
181  add_option
182  ("f", "", 40,
183  "Follow and convert all external references in the source file.",
184  &SomethingToEgg::dispatch_none, &_merge_externals);
185 }
186 
187 ////////////////////////////////////////////////////////////////////
188 // Function: SomethingToEgg::apply_units_scale
189 // Access: Protected
190 // Description: Applies the scale indicated by the input and output
191 // units to the indicated egg file. This is normally
192 // done automatically when the file is written out.
193 ////////////////////////////////////////////////////////////////////
194 void SomethingToEgg::
195 apply_units_scale(EggData *data) {
196  if (_output_units != DU_invalid && _input_units != DU_invalid &&
197  _input_units != _output_units) {
198  nout << "Converting from " << format_long_unit(_input_units)
199  << " to " << format_long_unit(_output_units) << "\n";
200  double scale = convert_units(_input_units, _output_units);
201  data->transform(LMatrix4d::scale_mat(scale));
202  }
203 }
204 
205 ////////////////////////////////////////////////////////////////////
206 // Function: SomethingToEgg::apply_parameters
207 // Access: Protected
208 // Description: Copies the relevant parameters specified by the user
209 // on the command line (if add_path_replace_options(),
210 // add_path_store_options(), or add_animation_options()
211 // was used) to the converter.
212 ////////////////////////////////////////////////////////////////////
213 void SomethingToEgg::
214 apply_parameters(SomethingToEggConverter &converter) {
215  _path_replace->_noabs = _noabs;
216  _path_replace->_exists = !_noexist;
217  converter.set_path_replace(_path_replace);
218 
219  converter.set_animation_convert(_animation_convert);
220  converter.set_character_name(_character_name);
221  if (_got_start_frame) {
222  converter.set_start_frame(_start_frame);
223  }
224  if (_got_end_frame) {
225  converter.set_end_frame(_end_frame);
226  }
227  if (_got_frame_inc) {
228  converter.set_frame_inc(_frame_inc);
229  }
230  if (_got_neutral_frame) {
231  converter.set_neutral_frame(_neutral_frame);
232  }
233  if (_got_input_frame_rate) {
234  converter.set_input_frame_rate(_input_frame_rate);
235  }
236  if (_got_output_frame_rate) {
237  converter.set_output_frame_rate(_output_frame_rate);
238  }
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: SomethingToEgg::handle_args
243 // Access: Protected
244 // Description:
245 ////////////////////////////////////////////////////////////////////
246 bool SomethingToEgg::
247 handle_args(Args &args) {
248  if (_allow_last_param && !_got_output_filename && args.size() > 1) {
249  _got_output_filename = true;
250  _output_filename = Filename::from_os_specific(args.back());
251  args.pop_back();
252 
253  if (!(_output_filename.get_extension() == "egg")) {
254  nout << "Output filename " << _output_filename
255  << " does not end in .egg. If this is really what you intended, "
256  "use the -o output_file syntax.\n";
257  return false;
258  }
259 
260  if (!verify_output_file_safe()) {
261  return false;
262  }
263  }
264 
265  if (args.empty()) {
266  nout << "You must specify the " << _format_name
267  << " file to read on the command line.\n";
268  return false;
269  }
270 
271  if (args.size() != 1) {
272  nout << "You may only specify one " << _format_name
273  << " file to read on the command line. "
274  << "You specified: ";
275  Args::const_iterator ai;
276  for (ai = args.begin(); ai != args.end(); ++ai) {
277  nout << (*ai) << " ";
278  }
279  nout << "\n";
280  return false;
281  }
282 
283  _input_filename = Filename::from_os_specific(args[0]);
284 
285  if (!_input_filename.exists()) {
286  nout << "Cannot find input file " << _input_filename << "\n";
287  return false;
288  }
289 
290  if (!_got_path_directory && _got_output_filename) {
291  // Put in the name of the output directory.
292  _path_replace->_path_directory = _output_filename.get_dirname();
293  }
294 
295  return true;
296 }
297 
298 ////////////////////////////////////////////////////////////////////
299 // Function: SomethingToEgg::post_command_line
300 // Access: Protected, Virtual
301 // Description: This is called after the command line has been
302 // completely processed, and it gives the program a
303 // chance to do some last-minute processing and
304 // validation of the options and arguments. It should
305 // return true if everything is fine, false if there is
306 // an error.
307 ////////////////////////////////////////////////////////////////////
308 bool SomethingToEgg::
309 post_command_line() {
310  // Prepend the source filename to the model path.
311  ConfigVariableSearchPath &model_path = get_model_path();
312  Filename directory = _input_filename.get_dirname();
313  if (directory.empty()) {
314  directory = ".";
315  }
316  model_path.prepend_directory(directory);
317 
318  return EggConverter::post_command_line();
319 }
320 
321 ////////////////////////////////////////////////////////////////////
322 // Function: SomethingToEgg::post_process_egg_file
323 // Access: Protected, Virtual
324 // Description: Performs any processing of the egg file that is
325 // appropriate before writing it out. This includes any
326 // normal adjustments the user requested via -np, etc.
327 //
328 // Normally, you should not need to call this function
329 // directly; write_egg_file() calls it for you. You
330 // should call this only if you do not use
331 // write_egg_file() to write out the resulting egg file.
332 ////////////////////////////////////////////////////////////////////
333 void SomethingToEgg::
334 post_process_egg_file() {
335  apply_units_scale(_data);
337 }
338 
339 ////////////////////////////////////////////////////////////////////
340 // Function: SomethingToEgg::dispatch_animation_convert
341 // Access: Protected, Static
342 // Description: Dispatch function to set the given animation convert mode
343 // according to the specified parameter. var is a
344 // pointer to an AnimationConvert variable.
345 ////////////////////////////////////////////////////////////////////
346 bool SomethingToEgg::
347 dispatch_animation_convert(const string &opt, const string &arg, void *var) {
348  AnimationConvert *ip = (AnimationConvert *)var;
349  (*ip) = string_animation_convert(arg);
350  if ((*ip) == AC_invalid) {
351  nout << "Invalid keyword for -" << opt << ": " << arg << "\n";
352  return false;
353  }
354 
355  return true;
356 }
This is similar to a ConfigVariableList, but it returns its list as a DSearchPath, as a list of directories.
void transform(const LMatrix4d &mat)
Applies the indicated transformation to the node and all of its descendants.
Definition: eggNode.I:313
void set_frame_inc(double frame_inc)
Specifies the increment between frames to extract.
void add_animation_options()
Adds options appropriate to animation packages.
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
string get_dirname() const
Returns the directory part of the filename.
Definition: filename.I:424
void set_neutral_frame(double neutral_frame)
Specifies the frame of animation to represent the neutral pose of the model.
This is the primary interface into all the egg data, and the root of the egg file structure...
Definition: eggData.h:41
SomethingToEgg(const string &format_name, const string &preferred_extension=string(), bool allow_last_param=true, bool allow_stdout=true)
The first parameter to the constructor should be the one-word name of the file format that is to be r...
void set_character_name(const string &character_name)
Specifies the name of the character generated.
This is a general base class for programs that convert between egg files and some other format...
Definition: eggConverter.h:28
void set_start_frame(double start_frame)
Specifies the starting frame of the animation to convert, in the units specified by set_input_frame_r...
void set_end_frame(double end_frame)
Specifies the ending frame of the animation to convert, in the units specified by set_input_frame_rat...
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
void set_path_replace(PathReplace *path_replace)
Replaces the PathReplace object (which specifies how to mangle paths from the source to the destinati...
void set_animation_convert(AnimationConvert animation_convert)
Specifies how source animation will be converted into egg structures.
virtual void post_process_egg_file()
Performs any processing of the egg file that is appropriate before writing it out.
Definition: eggWriter.cxx:125
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1356
void add_merge_externals_options()
Adds -f.
void set_output_frame_rate(double output_frame_rate)
Specifies the number of frames per second that the resulting animation should be played at...
void set_input_frame_rate(double input_frame_rate)
Specifies the number of frames per second that is represented by the &quot;frame&quot; unit in the animation pa...
This is a base class for a family of converter classes that manage a conversion from some file type t...
void prepend_directory(const Filename &directory)
Adds a new directory to the front of the search list.
void add_units_options()
Adds -ui and -uo as valid options for this program.
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).
Definition: filename.cxx:332