Panda3D
|
00001 // Filename: somethingToEgg.cxx 00002 // Created by: drose (15Feb00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "somethingToEgg.h" 00016 #include "somethingToEggConverter.h" 00017 00018 #include "config_util.h" 00019 00020 //////////////////////////////////////////////////////////////////// 00021 // Function: SomethingToEgg::Constructor 00022 // Access: Public 00023 // Description: The first parameter to the constructor should be the 00024 // one-word name of the file format that is to be read, 00025 // for instance "OpenFlight" or "Alias". It's just used 00026 // in printing error messages and such. 00027 //////////////////////////////////////////////////////////////////// 00028 SomethingToEgg:: 00029 SomethingToEgg(const string &format_name, 00030 const string &preferred_extension, 00031 bool allow_last_param, bool allow_stdout) : 00032 EggConverter(format_name, preferred_extension, allow_last_param, allow_stdout) 00033 { 00034 clear_runlines(); 00035 if (_allow_last_param) { 00036 add_runline("[opts] input" + _preferred_extension + " output.egg"); 00037 } 00038 add_runline("[opts] -o output.egg input" + _preferred_extension); 00039 if (_allow_stdout) { 00040 add_runline("[opts] input" + _preferred_extension + " >output.egg"); 00041 } 00042 00043 // -f doesn't make sense if we aren't reading egg files. 00044 remove_option("f"); 00045 00046 redescribe_option 00047 ("cs", 00048 "Specify the coordinate system of the input " + _format_name + 00049 " file. Normally, this can inferred from the file itself."); 00050 00051 add_option 00052 ("noabs", "", 0, 00053 "Don't allow the input " + _format_name + " file to have absolute pathnames. " 00054 "If it does, abort with an error. This option is designed to help " 00055 "detect errors when populating or building a standalone model tree, " 00056 "which should be self-contained and include only relative pathnames.", 00057 &SomethingToEgg::dispatch_none, &_noabs); 00058 00059 add_option 00060 ("noexist", "", 0, 00061 "Don't treat it as an error if the input file references pathnames " 00062 "(e.g. textures) that don't exist. Normally, this will be flagged as " 00063 "an error and the command aborted; with this option, an egg file will " 00064 "be generated anyway, referencing pathnames that do not exist.", 00065 &SomethingToEgg::dispatch_none, &_noexist); 00066 00067 add_option 00068 ("ignore", "", 0, 00069 "Ignore non-fatal errors and generate an egg file anyway.", 00070 &SomethingToEgg::dispatch_none, &_allow_errors); 00071 00072 _input_units = DU_invalid; 00073 _output_units = DU_invalid; 00074 _animation_convert = AC_none; 00075 _got_start_frame = false; 00076 _got_end_frame = false; 00077 _got_frame_inc = false; 00078 _got_neutral_frame = false; 00079 _got_input_frame_rate = false; 00080 _got_output_frame_rate = false; 00081 _merge_externals = false; 00082 } 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: SomethingToEgg::add_units_options 00086 // Access: Public 00087 // Description: Adds -ui and -uo as valid options for this program. 00088 // If the user specifies -uo and -ui, or just -uo and 00089 // the program specifies -ui by setting _input_units, 00090 // the indicated units conversion will be automatically 00091 // applied before writing out the egg file. 00092 //////////////////////////////////////////////////////////////////// 00093 void SomethingToEgg:: 00094 add_units_options() { 00095 add_option 00096 ("ui", "units", 40, 00097 "Specify the units of the input " + _format_name + 00098 " file. Normally, this can be inferred from the file itself.", 00099 &SomethingToEgg::dispatch_units, NULL, &_input_units); 00100 00101 add_option 00102 ("uo", "units", 40, 00103 "Specify the units of the resulting egg file. If this is " 00104 "specified, the vertices in the egg file will be scaled as " 00105 "necessary to make the appropriate units conversion; otherwise, " 00106 "the vertices will be left as they are.", 00107 &SomethingToEgg::dispatch_units, NULL, &_output_units); 00108 } 00109 00110 //////////////////////////////////////////////////////////////////// 00111 // Function: SomethingToEgg::add_animation_options 00112 // Access: Public 00113 // Description: Adds options appropriate to animation packages. 00114 //////////////////////////////////////////////////////////////////// 00115 void SomethingToEgg:: 00116 add_animation_options() { 00117 add_option 00118 ("a", "animation-mode", 40, 00119 "Specifies how animation from the " + _format_name + " file is " 00120 "converted to egg, if at all. At present, the following keywords " 00121 "are supported: none, pose, flip, strobe, model, chan, or both. " 00122 "The default is none, which means not to convert animation.", 00123 &SomethingToEgg::dispatch_animation_convert, NULL, &_animation_convert); 00124 00125 add_option 00126 ("cn", "name", 40, 00127 "Specifies the name of the animation character. This should match " 00128 "between all of the model files and all of the channel files for a " 00129 "particular model and its associated channels.", 00130 &SomethingToEgg::dispatch_string, NULL, &_character_name); 00131 00132 add_option 00133 ("sf", "start-frame", 40, 00134 "Specifies the starting frame of animation to extract. If omitted, " 00135 "the first frame of the time slider will be used. For -a pose, this " 00136 "is the one frame of animation to extract.", 00137 &SomethingToEgg::dispatch_double, &_got_start_frame, &_start_frame); 00138 00139 add_option 00140 ("ef", "end-frame", 40, 00141 "Specifies the ending frame of animation to extract. If omitted, " 00142 "the last frame of the time slider will be used.", 00143 &SomethingToEgg::dispatch_double, &_got_end_frame, &_end_frame); 00144 00145 add_option 00146 ("if", "frame-inc", 40, 00147 "Specifies the increment between successive frames. If omitted, " 00148 "this is taken from the time slider settings, or 1.0 if the time " 00149 "slider does not specify.", 00150 &SomethingToEgg::dispatch_double, &_got_frame_inc, &_frame_inc); 00151 00152 add_option 00153 ("nf", "neutral-frame", 40, 00154 "Specifies the frame number to use for the neutral pose. The model " 00155 "will be set to this frame before extracting out the neutral character. " 00156 "If omitted, the current frame of the model is used. This is only " 00157 "relevant for -a model or -a both.", 00158 &SomethingToEgg::dispatch_double, &_got_neutral_frame, &_neutral_frame); 00159 00160 add_option 00161 ("fri", "fps", 40, 00162 "Specify the frame rate (frames per second) of the input " + _format_name + 00163 " file. Normally, this can be inferred from the file itself.", 00164 &SomethingToEgg::dispatch_double, &_got_input_frame_rate, &_input_frame_rate); 00165 00166 add_option 00167 ("fro", "fps", 40, 00168 "Specify the frame rate (frames per second) of the generated animation. " 00169 "If this is specified, the animation speed is scaled by the appropriate " 00170 "factor based on the frame rate of the input file (see -fri).", 00171 &SomethingToEgg::dispatch_double, &_got_output_frame_rate, &_output_frame_rate); 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: SomethingToEgg::add_merge_externals_options 00176 // Access: Public 00177 // Description: Adds -f. 00178 //////////////////////////////////////////////////////////////////// 00179 void SomethingToEgg:: 00180 add_merge_externals_options() { 00181 add_option 00182 ("f", "", 40, 00183 "Follow and convert all external references in the source file.", 00184 &SomethingToEgg::dispatch_none, &_merge_externals); 00185 } 00186 00187 //////////////////////////////////////////////////////////////////// 00188 // Function: SomethingToEgg::apply_units_scale 00189 // Access: Protected 00190 // Description: Applies the scale indicated by the input and output 00191 // units to the indicated egg file. This is normally 00192 // done automatically when the file is written out. 00193 //////////////////////////////////////////////////////////////////// 00194 void SomethingToEgg:: 00195 apply_units_scale(EggData *data) { 00196 if (_output_units != DU_invalid && _input_units != DU_invalid && 00197 _input_units != _output_units) { 00198 nout << "Converting from " << format_long_unit(_input_units) 00199 << " to " << format_long_unit(_output_units) << "\n"; 00200 double scale = convert_units(_input_units, _output_units); 00201 data->transform(LMatrix4d::scale_mat(scale)); 00202 } 00203 } 00204 00205 //////////////////////////////////////////////////////////////////// 00206 // Function: SomethingToEgg::apply_parameters 00207 // Access: Protected 00208 // Description: Copies the relevant parameters specified by the user 00209 // on the command line (if add_path_replace_options(), 00210 // add_path_store_options(), or add_animation_options() 00211 // was used) to the converter. 00212 //////////////////////////////////////////////////////////////////// 00213 void SomethingToEgg:: 00214 apply_parameters(SomethingToEggConverter &converter) { 00215 _path_replace->_noabs = _noabs; 00216 _path_replace->_exists = !_noexist; 00217 converter.set_path_replace(_path_replace); 00218 00219 converter.set_animation_convert(_animation_convert); 00220 converter.set_character_name(_character_name); 00221 if (_got_start_frame) { 00222 converter.set_start_frame(_start_frame); 00223 } 00224 if (_got_end_frame) { 00225 converter.set_end_frame(_end_frame); 00226 } 00227 if (_got_frame_inc) { 00228 converter.set_frame_inc(_frame_inc); 00229 } 00230 if (_got_neutral_frame) { 00231 converter.set_neutral_frame(_neutral_frame); 00232 } 00233 if (_got_input_frame_rate) { 00234 converter.set_input_frame_rate(_input_frame_rate); 00235 } 00236 if (_got_output_frame_rate) { 00237 converter.set_output_frame_rate(_output_frame_rate); 00238 } 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: SomethingToEgg::handle_args 00243 // Access: Protected 00244 // Description: 00245 //////////////////////////////////////////////////////////////////// 00246 bool SomethingToEgg:: 00247 handle_args(Args &args) { 00248 if (_allow_last_param && !_got_output_filename && args.size() > 1) { 00249 _got_output_filename = true; 00250 _output_filename = Filename::from_os_specific(args.back()); 00251 args.pop_back(); 00252 00253 if (!(_output_filename.get_extension() == "egg")) { 00254 nout << "Output filename " << _output_filename 00255 << " does not end in .egg. If this is really what you intended, " 00256 "use the -o output_file syntax.\n"; 00257 return false; 00258 } 00259 00260 if (!verify_output_file_safe()) { 00261 return false; 00262 } 00263 } 00264 00265 if (args.empty()) { 00266 nout << "You must specify the " << _format_name 00267 << " file to read on the command line.\n"; 00268 return false; 00269 } 00270 00271 if (args.size() != 1) { 00272 nout << "You may only specify one " << _format_name 00273 << " file to read on the command line. " 00274 << "You specified: "; 00275 Args::const_iterator ai; 00276 for (ai = args.begin(); ai != args.end(); ++ai) { 00277 nout << (*ai) << " "; 00278 } 00279 nout << "\n"; 00280 return false; 00281 } 00282 00283 _input_filename = Filename::from_os_specific(args[0]); 00284 00285 if (!_input_filename.exists()) { 00286 nout << "Cannot find input file " << _input_filename << "\n"; 00287 return false; 00288 } 00289 00290 if (!_got_path_directory && _got_output_filename) { 00291 // Put in the name of the output directory. 00292 _path_replace->_path_directory = _output_filename.get_dirname(); 00293 } 00294 00295 return true; 00296 } 00297 00298 //////////////////////////////////////////////////////////////////// 00299 // Function: SomethingToEgg::post_command_line 00300 // Access: Protected, Virtual 00301 // Description: This is called after the command line has been 00302 // completely processed, and it gives the program a 00303 // chance to do some last-minute processing and 00304 // validation of the options and arguments. It should 00305 // return true if everything is fine, false if there is 00306 // an error. 00307 //////////////////////////////////////////////////////////////////// 00308 bool SomethingToEgg:: 00309 post_command_line() { 00310 // Prepend the source filename to the model path. 00311 ConfigVariableSearchPath &model_path = get_model_path(); 00312 Filename directory = _input_filename.get_dirname(); 00313 if (directory.empty()) { 00314 directory = "."; 00315 } 00316 model_path.prepend_directory(directory); 00317 00318 return EggConverter::post_command_line(); 00319 } 00320 00321 //////////////////////////////////////////////////////////////////// 00322 // Function: SomethingToEgg::post_process_egg_file 00323 // Access: Protected, Virtual 00324 // Description: Performs any processing of the egg file that is 00325 // appropriate before writing it out. This includes any 00326 // normal adjustments the user requested via -np, etc. 00327 // 00328 // Normally, you should not need to call this function 00329 // directly; write_egg_file() calls it for you. You 00330 // should call this only if you do not use 00331 // write_egg_file() to write out the resulting egg file. 00332 //////////////////////////////////////////////////////////////////// 00333 void SomethingToEgg:: 00334 post_process_egg_file() { 00335 apply_units_scale(_data); 00336 EggConverter::post_process_egg_file(); 00337 } 00338 00339 //////////////////////////////////////////////////////////////////// 00340 // Function: SomethingToEgg::dispatch_animation_convert 00341 // Access: Protected, Static 00342 // Description: Dispatch function to set the given animation convert mode 00343 // according to the specified parameter. var is a 00344 // pointer to an AnimationConvert variable. 00345 //////////////////////////////////////////////////////////////////// 00346 bool SomethingToEgg:: 00347 dispatch_animation_convert(const string &opt, const string &arg, void *var) { 00348 AnimationConvert *ip = (AnimationConvert *)var; 00349 (*ip) = string_animation_convert(arg); 00350 if ((*ip) == AC_invalid) { 00351 nout << "Invalid keyword for -" << opt << ": " << arg << "\n"; 00352 return false; 00353 } 00354 00355 return true; 00356 }