00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggReader.h"
00016
00017 #include "pnmImage.h"
00018 #include "config_util.h"
00019 #include "eggTextureCollection.h"
00020 #include "eggGroup.h"
00021 #include "eggGroupNode.h"
00022 #include "eggSwitchCondition.h"
00023 #include "string_utils.h"
00024 #include "dcast.h"
00025
00026
00027
00028
00029
00030
00031 EggReader::
00032 EggReader() {
00033 clear_runlines();
00034 add_runline("[opts] input.egg");
00035
00036 redescribe_option
00037 ("cs",
00038 "Specify the coordinate system to operate in. This may be "
00039 " one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default "
00040 "is the coordinate system of the input egg file.");
00041
00042 add_option
00043 ("f", "", 80,
00044 "Force complete loading: load up the egg file along with all of its "
00045 "external references.",
00046 &EggReader::dispatch_none, &_force_complete);
00047
00048 add_option
00049 ("noabs", "", 0,
00050 "Don't allow the input egg file to have absolute pathnames. "
00051 "If it does, abort with an error. This option is designed to help "
00052 "detect errors when populating or building a standalone model tree, "
00053 "which should be self-contained and include only relative pathnames.",
00054 &EggReader::dispatch_none, &_noabs);
00055
00056 _tex_type = (PNMFileType *)NULL;
00057 _delod = -1.0;
00058
00059 _got_tex_dirname = false;
00060 _got_tex_extension = false;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 void EggReader::
00077 add_texture_options() {
00078 add_option
00079 ("td", "dirname", 40,
00080 "Copy textures to the indicated directory. The copy is performed "
00081 "only if the destination file does not exist or is older than the "
00082 "source file.",
00083 &EggReader::dispatch_filename, &_got_tex_dirname, &_tex_dirname);
00084
00085 add_option
00086 ("te", "ext", 40,
00087 "Rename textures to have the indicated extension. This also "
00088 "automatically copies them to the new filename (possibly in a "
00089 "different directory if -td is also specified), and may implicitly "
00090 "convert to a different image format according to the extension.",
00091 &EggReader::dispatch_string, &_got_tex_extension, &_tex_extension);
00092
00093 add_option
00094 ("tt", "type", 40,
00095 "Explicitly specifies the image format to convert textures to "
00096 "when copying them via -td or -te. Normally, this is unnecessary as "
00097 "the image format can be determined by the extension, but sometimes "
00098 "the extension is insufficient to unambiguously specify an image "
00099 "type.",
00100 &EggReader::dispatch_image_type, NULL, &_tex_type);
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 void EggReader::
00114 add_delod_options(double default_delod) {
00115 _delod = default_delod;
00116
00117 if (default_delod < 0) {
00118 add_option
00119 ("delod", "dist", 40,
00120 "Eliminate LOD's by choosing the level that would be appropriate for "
00121 "a camera at the indicated fixed distance from each LOD. "
00122 "Use -delod -1 to keep all the LOD's as they are, which is "
00123 "the default.\n",
00124 &EggReader::dispatch_double, NULL, &_delod);
00125
00126 } else {
00127 add_option
00128 ("delod", "dist", 40,
00129 "Eliminate LOD's by choosing the level that would be appropriate for "
00130 "a camera at the indicated fixed distance from each LOD. "
00131 "Use -delod -1 to keep all the LOD's as they are. The default value "
00132 "is " + format_string(default_delod) + ".",
00133 &EggReader::dispatch_double, NULL, &_delod);
00134 }
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 EggReader *EggReader::
00150 as_reader() {
00151 return this;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 void EggReader::
00164 pre_process_egg_file() {
00165 }
00166
00167
00168
00169
00170
00171
00172 bool EggReader::
00173 handle_args(ProgramBase::Args &args) {
00174 if (args.empty()) {
00175 nout << "You must specify the egg file(s) to read on the command line.\n";
00176 return false;
00177 }
00178
00179
00180
00181
00182 if (!args.empty()) {
00183 _data->set_egg_filename(Filename::from_os_specific(args[0]));
00184 }
00185 Args::const_iterator ai;
00186 for (ai = args.begin(); ai != args.end(); ++ai) {
00187 Filename filename = Filename::from_os_specific(*ai);
00188
00189 EggData file_data;
00190 if (!file_data.read(filename)) {
00191
00192
00193
00194 exit(1);
00195 }
00196
00197 if (_noabs && file_data.original_had_absolute_pathnames()) {
00198 nout << filename.get_basename()
00199 << " includes absolute pathnames!\n";
00200 exit(1);
00201 }
00202
00203 DSearchPath file_path;
00204 file_path.append_directory(filename.get_dirname());
00205
00206 if (_force_complete) {
00207 if (!file_data.load_externals()) {
00208 exit(1);
00209 }
00210 }
00211
00212
00213
00214 convert_paths(&file_data, _path_replace, file_path);
00215
00216 _data->merge(file_data);
00217 }
00218
00219 pre_process_egg_file();
00220
00221 return true;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 bool EggReader::
00235 post_command_line() {
00236 return EggSingleBase::post_command_line();
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 bool EggReader::
00248 do_reader_options() {
00249 bool okflag = true;
00250
00251 if (_got_tex_dirname || _got_tex_extension) {
00252 if (!copy_textures()) {
00253 okflag = false;
00254 }
00255 }
00256
00257 if (_delod >= 0.0) {
00258 do_delod(_data);
00259 }
00260
00261 return okflag;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 bool EggReader::
00273 copy_textures() {
00274 bool success = true;
00275 EggTextureCollection textures;
00276 textures.find_used_textures(_data);
00277
00278 EggTextureCollection::const_iterator ti;
00279 for (ti = textures.begin(); ti != textures.end(); ++ti) {
00280 EggTexture *tex = (*ti);
00281 Filename orig_filename = tex->get_filename();
00282 if (!orig_filename.exists()) {
00283 bool found = orig_filename.resolve_filename(get_model_path());
00284 if (!found) {
00285 nout << "Cannot find " << orig_filename << "\n";
00286 success = false;
00287 continue;
00288 }
00289 }
00290
00291 Filename new_filename = orig_filename;
00292 if (_got_tex_dirname) {
00293 new_filename.set_dirname(_tex_dirname);
00294 }
00295 if (_got_tex_extension) {
00296 new_filename.set_extension(_tex_extension);
00297 }
00298
00299 if (orig_filename != new_filename) {
00300 tex->set_filename(new_filename);
00301
00302
00303 int compare =
00304 orig_filename.compare_timestamps(new_filename, true, true);
00305 if (compare > 0) {
00306
00307 nout << "Reading " << orig_filename << "\n";
00308 PNMImage image;
00309 if (!image.read(orig_filename)) {
00310 nout << " unable to read!\n";
00311 success = false;
00312 } else {
00313 nout << "Writing " << new_filename << "\n";
00314 if (!image.write(new_filename, _tex_type)) {
00315 nout << " unable to write!\n";
00316 success = false;
00317 }
00318 }
00319 }
00320 }
00321 }
00322
00323 return success;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 bool EggReader::
00335 do_delod(EggNode *node) {
00336 if (node->is_of_type(EggGroup::get_class_type())) {
00337 EggGroup *group = DCAST(EggGroup, node);
00338 if (group->has_lod()) {
00339 const EggSwitchCondition &cond = group->get_lod();
00340 if (cond.is_of_type(EggSwitchConditionDistance::get_class_type())) {
00341 const EggSwitchConditionDistance *dist =
00342 DCAST(EggSwitchConditionDistance, &cond);
00343 if (_delod >= dist->_switch_out && _delod < dist->_switch_in) {
00344
00345
00346 nout << "Preserving LOD " << node->get_name()
00347 << " (" << dist->_switch_out << " to " << dist->_switch_in
00348 << ")\n";
00349 group->clear_lod();
00350 } else {
00351
00352 nout << "Eliminating LOD " << node->get_name()
00353 << " (" << dist->_switch_out << " to " << dist->_switch_in
00354 << ")\n";
00355 return false;
00356 }
00357 }
00358 }
00359 }
00360
00361
00362 if (node->is_of_type(EggGroupNode::get_class_type())) {
00363 EggGroupNode *group = DCAST(EggGroupNode, node);
00364 EggGroupNode::iterator ci;
00365 ci = group->begin();
00366 while (ci != group->end()) {
00367 EggNode *child = *ci;
00368 ++ci;
00369
00370 if (!do_delod(child)) {
00371 group->remove_child(child);
00372 }
00373 }
00374 }
00375
00376 return true;
00377 }