00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "eggWriter.h"
00020
00021 #include "string_utils.h"
00022 #include "compose_matrix.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 EggWriter::
00044 EggWriter(bool allow_last_param, bool allow_stdout) :
00045 WithOutputFile(allow_last_param, allow_stdout, false)
00046 {
00047
00048
00049 _preferred_extension = ".egg";
00050
00051 clear_runlines();
00052 if (_allow_last_param) {
00053 add_runline("[opts] output.egg");
00054 }
00055 add_runline("[opts] -o output.egg");
00056 if (_allow_stdout) {
00057 add_runline("[opts] >output.egg");
00058 }
00059
00060 string o_description;
00061
00062 if (_allow_stdout) {
00063 if (_allow_last_param) {
00064 o_description =
00065 "Specify the filename to which the resulting egg file will be written. "
00066 "If this option is omitted, the last parameter name is taken to be the "
00067 "name of the output file, or standard output is used if there are no "
00068 "other parameters.";
00069 } else {
00070 o_description =
00071 "Specify the filename to which the resulting egg file will be written. "
00072 "If this option is omitted, the egg file is written to standard output.";
00073 }
00074 } else {
00075 if (_allow_last_param) {
00076 o_description =
00077 "Specify the filename to which the resulting egg file will be written. "
00078 "If this option is omitted, the last parameter name is taken to be the "
00079 "name of the output file.";
00080 } else {
00081 o_description =
00082 "Specify the filename to which the resulting egg file will be written.";
00083 }
00084 }
00085
00086 add_option
00087 ("o", "filename", 50, o_description,
00088 &EggWriter::dispatch_filename, &_got_output_filename, &_output_filename);
00089
00090 redescribe_option
00091 ("cs",
00092 "Specify the coordinate system of the resulting egg file. This may be "
00093 "one of 'y-up', 'z-up', 'y-up-left', or 'z-up-left'. The default is "
00094 "y-up.");
00095
00096 _normals_mode = NM_preserve;
00097 _normals_threshold = 0.0;
00098
00099 _got_transform = false;
00100 _transform = LMatrix4d::ident_mat();
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 void EggWriter::
00113 add_normals_options() {
00114 static NormalsMode strip = NM_strip;
00115 static NormalsMode polygon = NM_polygon;
00116 static NormalsMode vertex = NM_vertex;
00117 static NormalsMode preserve = NM_preserve;
00118
00119 add_option
00120 ("no", "", 48,
00121 "Strip all normals.",
00122 &EggWriter::dispatch_normals, NULL, &strip);
00123
00124 add_option
00125 ("np", "", 48,
00126 "Strip existing normals and redefine polygon normals.",
00127 &EggWriter::dispatch_normals, NULL, &polygon);
00128
00129 add_option
00130 ("nv", "threshold", 48,
00131 "Strip existing normals and redefine vertex normals. Consider an edge "
00132 "between adjacent polygons to be smooth if the angle between them "
00133 "is less than threshold degrees.",
00134 &EggWriter::dispatch_normals, NULL, &vertex);
00135
00136 add_option
00137 ("nn", "", 48,
00138 "Preserve normals exactly as they are. This is the default.",
00139 &EggWriter::dispatch_normals, NULL, &preserve);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 void EggWriter::
00151 add_transform_options() {
00152 add_option
00153 ("TS", "sx[,sy,sz]", 49,
00154 "Scale the model uniformly by the given factor (if only one number "
00155 "is given) or in each axis by sx, sy, sz (if three numbers are given).",
00156 &EggWriter::dispatch_scale, &_got_transform, &_transform);
00157
00158 add_option
00159 ("TR", "x,y,z", 49,
00160 "Rotate the model x degrees about the x axis, then y degrees about the "
00161 "y axis, and then z degrees about the z axis.",
00162 &EggWriter::dispatch_rotate_xyz, &_got_transform, &_transform);
00163
00164 add_option
00165 ("TA", "angle,x,y,z", 49,
00166 "Rotate the model angle degrees counterclockwise about the given "
00167 "axis.",
00168 &EggWriter::dispatch_rotate_axis, &_got_transform, &_transform);
00169
00170 add_option
00171 ("TT", "x,y,z", 49,
00172 "Translate the model by the indicated amount.\n\n"
00173 "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
00174 "applied in the order they are encountered on the command line.",
00175 &EggWriter::dispatch_translate, &_got_transform, &_transform);
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 EggWriter *EggWriter::
00191 as_writer() {
00192 return this;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void EggWriter::
00208 post_process_egg_file() {
00209 if (_got_transform) {
00210 nout << "Applying transform matrix:\n";
00211 _transform.write(nout, 2);
00212 LVecBase3d scale, hpr, translate;
00213 if (decompose_matrix(_transform, scale, hpr, translate,
00214 _data.get_coordinate_system())) {
00215 nout << "(scale " << scale << ", hpr " << hpr << ", translate "
00216 << translate << ")\n";
00217 }
00218 _data.transform(_transform);
00219 }
00220
00221 switch (_normals_mode) {
00222 case NM_strip:
00223 nout << "Stripping normals.\n";
00224 _data.strip_normals();
00225 _data.remove_unused_vertices();
00226 break;
00227
00228 case NM_polygon:
00229 nout << "Recomputing polygon normals.\n";
00230 _data.recompute_polygon_normals();
00231 _data.remove_unused_vertices();
00232 break;
00233
00234 case NM_vertex:
00235 nout << "Recomputing vertex normals.\n";
00236 _data.recompute_vertex_normals(_normals_threshold);
00237 _data.remove_unused_vertices();
00238 break;
00239
00240 case NM_preserve:
00241
00242 break;
00243 }
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 void EggWriter::
00256 write_egg_file() {
00257 post_process_egg_file();
00258 _data.write_egg(get_output());
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 bool EggWriter::
00270 handle_args(ProgramBase::Args &args) {
00271 if (!check_last_arg(args, 0)) {
00272 return false;
00273 }
00274
00275 if (!args.empty()) {
00276 nout << "Unexpected arguments on command line:\n";
00277 Args::const_iterator ai;
00278 for (ai = args.begin(); ai != args.end(); ++ai) {
00279 nout << (*ai) << " ";
00280 }
00281 nout << "\r";
00282 return false;
00283 }
00284
00285 if (!_got_path_directory && _got_output_filename) {
00286
00287 _path_replace->_path_directory = _output_filename.get_dirname();
00288 }
00289
00290 return true;
00291 }
00292
00293
00294
00295
00296
00297
00298 bool EggWriter::
00299 post_command_line() {
00300 if (!_allow_stdout && !_got_output_filename) {
00301 nout << "You must specify the filename to write with -o.\n";
00302 return false;
00303 }
00304
00305 append_command_comment(_data);
00306
00307 return EggBase::post_command_line();
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 bool EggWriter::
00319 dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
00320 EggBase *base = (EggBase *)self;
00321 EggWriter *me = base->as_writer();
00322 return me->ns_dispatch_normals(opt, arg, mode);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 bool EggWriter::
00334 ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
00335 _normals_mode = *(NormalsMode *)mode;
00336
00337 if (_normals_mode == NM_vertex) {
00338 if (!string_to_double(arg, _normals_threshold)) {
00339 nout << "Invalid numeric parameter for -" << opt << ": "
00340 << arg << "\n";
00341 return false;
00342 }
00343 }
00344
00345 return true;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354 bool EggWriter::
00355 dispatch_scale(const string &opt, const string &arg, void *var) {
00356 LMatrix4d *transform = (LMatrix4d *)var;
00357
00358 vector_string words;
00359 tokenize(arg, words, ",");
00360
00361 double sx, sy, sz;
00362
00363 bool okflag = false;
00364 if (words.size() == 3) {
00365 okflag =
00366 string_to_double(words[0], sx) &&
00367 string_to_double(words[1], sy) &&
00368 string_to_double(words[2], sz);
00369
00370 } else if (words.size() == 1) {
00371 okflag =
00372 string_to_double(words[0], sx);
00373 sy = sz = sx;
00374 }
00375
00376 if (!okflag) {
00377 nout << "-" << opt
00378 << " requires one or three numbers separated by commas.\n";
00379 return false;
00380 }
00381
00382 *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);
00383
00384 return true;
00385 }
00386
00387
00388
00389
00390
00391
00392
00393 bool EggWriter::
00394 dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
00395 EggBase *base = (EggBase *)self;
00396 EggWriter *me = base->as_writer();
00397 return me->ns_dispatch_rotate_xyz(opt, arg, var);
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 bool EggWriter::
00407 ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
00408 LMatrix4d *transform = (LMatrix4d *)var;
00409
00410 vector_string words;
00411 tokenize(arg, words, ",");
00412
00413 LVecBase3d xyz;
00414
00415 bool okflag = false;
00416 if (words.size() == 3) {
00417 okflag =
00418 string_to_double(words[0], xyz[0]) &&
00419 string_to_double(words[1], xyz[1]) &&
00420 string_to_double(words[2], xyz[2]);
00421 }
00422
00423 if (!okflag) {
00424 nout << "-" << opt
00425 << " requires three numbers separated by commas.\n";
00426 return false;
00427 }
00428
00429 LMatrix4d mat =
00430 LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
00431 LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
00432 LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);
00433
00434 *transform = (*transform) * mat;
00435
00436 return true;
00437 }
00438
00439
00440
00441
00442
00443
00444
00445 bool EggWriter::
00446 dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
00447 EggBase *base = (EggBase *)self;
00448 EggWriter *me = base->as_writer();
00449 return me->ns_dispatch_rotate_axis(opt, arg, var);
00450 }
00451
00452
00453
00454
00455
00456
00457
00458 bool EggWriter::
00459 ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
00460 LMatrix4d *transform = (LMatrix4d *)var;
00461
00462 vector_string words;
00463 tokenize(arg, words, ",");
00464
00465 double angle;
00466 LVecBase3d axis;
00467
00468 bool okflag = false;
00469 if (words.size() == 4) {
00470 okflag =
00471 string_to_double(words[0], angle) &&
00472 string_to_double(words[1], axis[0]) &&
00473 string_to_double(words[2], axis[1]) &&
00474 string_to_double(words[3], axis[2]);
00475 }
00476
00477 if (!okflag) {
00478 nout << "-" << opt
00479 << " requires four numbers separated by commas.\n";
00480 return false;
00481 }
00482
00483 *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);
00484
00485 return true;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494 bool EggWriter::
00495 dispatch_translate(const string &opt, const string &arg, void *var) {
00496 LMatrix4d *transform = (LMatrix4d *)var;
00497
00498 vector_string words;
00499 tokenize(arg, words, ",");
00500
00501 LVector3d trans;
00502
00503 bool okflag = false;
00504 if (words.size() == 3) {
00505 okflag =
00506 string_to_double(words[0], trans[0]) &&
00507 string_to_double(words[1], trans[1]) &&
00508 string_to_double(words[2], trans[2]);
00509 }
00510
00511 if (!okflag) {
00512 nout << "-" << opt
00513 << " requires three numbers separated by commas.\n";
00514 return false;
00515 }
00516
00517 *transform = (*transform) * LMatrix4d::translate_mat(trans);
00518
00519 return true;
00520 }