00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eggBase.h"
00016
00017 #include "eggGroupNode.h"
00018 #include "eggTexture.h"
00019 #include "eggFilenameNode.h"
00020 #include "eggComment.h"
00021 #include "dcast.h"
00022 #include "string_utils.h"
00023
00024
00025
00026
00027
00028
00029 EggBase::
00030 EggBase() {
00031 add_option
00032 ("cs", "coordinate-system", 80,
00033 "Specify the coordinate system to operate in. This may be one of "
00034 "'y-up', 'z-up', 'y-up-left', or 'z-up-left'.",
00035 &EggBase::dispatch_coordinate_system,
00036 &_got_coordinate_system, &_coordinate_system);
00037
00038 _normals_mode = NM_preserve;
00039 _normals_threshold = 0.0;
00040
00041 _got_tbnall = false;
00042 _got_tbnauto = false;
00043 _make_points = false;
00044
00045 _got_transform = false;
00046 _transform = LMatrix4d::ident_mat();
00047
00048 _got_coordinate_system = false;
00049 _coordinate_system = CS_yup_right;
00050
00051 _noabs = false;
00052 }
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 void EggBase::
00063 add_normals_options() {
00064 static NormalsMode strip = NM_strip;
00065 static NormalsMode polygon = NM_polygon;
00066 static NormalsMode vertex = NM_vertex;
00067 static NormalsMode preserve = NM_preserve;
00068
00069 add_option
00070 ("no", "", 48,
00071 "Strip all normals.",
00072 &EggBase::dispatch_normals, NULL, &strip);
00073
00074 add_option
00075 ("np", "", 48,
00076 "Strip existing normals and redefine polygon normals.",
00077 &EggBase::dispatch_normals, NULL, &polygon);
00078
00079 add_option
00080 ("nv", "threshold", 48,
00081 "Strip existing normals and redefine vertex normals. Consider an edge "
00082 "between adjacent polygons to be smooth if the angle between them "
00083 "is less than threshold degrees.",
00084 &EggBase::dispatch_normals, NULL, &vertex);
00085
00086 add_option
00087 ("nn", "", 48,
00088 "Preserve normals exactly as they are. This is the default.",
00089 &EggBase::dispatch_normals, NULL, &preserve);
00090
00091 add_option
00092 ("tbn", "name", 48,
00093 "Compute tangent and binormal for the named texture coordinate "
00094 "set(s). The name may include wildcard characters such as * and ?. "
00095 "The normal must already exist or have been computed via one of the "
00096 "above options. The tangent and binormal are used to implement "
00097 "bump mapping and related texture-based lighting effects. This option "
00098 "may be repeated as necessary to name multiple texture coordinate sets.",
00099 &EggBase::dispatch_vector_string, NULL, &_tbn_names);
00100
00101 add_option
00102 ("tbnall", "", 48,
00103 "Compute tangent and binormal for all texture coordinate "
00104 "sets. This is equivalent to -tbn \"*\".",
00105 &EggBase::dispatch_none, &_got_tbnall);
00106
00107 add_option
00108 ("tbnauto", "", 48,
00109 "Compute tangent and binormal for all normal maps. ",
00110 &EggBase::dispatch_none, &_got_tbnauto);
00111 }
00112
00113
00114
00115
00116
00117
00118 void EggBase::
00119 add_points_options() {
00120 add_option
00121 ("points", "", 46,
00122 "Construct <PointLight> entries for any unreferenced vertices, to make them visible.",
00123 &EggBase::dispatch_none, &_make_points);
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 void EggBase::
00135 add_transform_options() {
00136 add_option
00137 ("TS", "sx[,sy,sz]", 49,
00138 "Scale the model uniformly by the given factor (if only one number "
00139 "is given) or in each axis by sx, sy, sz (if three numbers are given).",
00140 &EggBase::dispatch_scale, &_got_transform, &_transform);
00141
00142 add_option
00143 ("TR", "x,y,z", 49,
00144 "Rotate the model x degrees about the x axis, then y degrees about the "
00145 "y axis, and then z degrees about the z axis.",
00146 &EggBase::dispatch_rotate_xyz, &_got_transform, &_transform);
00147
00148 add_option
00149 ("TA", "angle,x,y,z", 49,
00150 "Rotate the model angle degrees counterclockwise about the given "
00151 "axis.",
00152 &EggBase::dispatch_rotate_axis, &_got_transform, &_transform);
00153
00154 add_option
00155 ("TT", "x,y,z", 49,
00156 "Translate the model by the indicated amount.\n\n"
00157 "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
00158 "applied in the order they are encountered on the command line.",
00159 &EggBase::dispatch_translate, &_got_transform, &_transform);
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169 void EggBase::
00170 convert_paths(EggNode *node, PathReplace *path_replace,
00171 const DSearchPath &additional_path) {
00172 if (node->is_of_type(EggTexture::get_class_type())) {
00173 EggTexture *egg_tex = DCAST(EggTexture, node);
00174 Filename fullpath, outpath;
00175 path_replace->full_convert_path(egg_tex->get_filename(), additional_path,
00176 fullpath, outpath);
00177 egg_tex->set_filename(outpath);
00178 egg_tex->set_fullpath(fullpath);
00179
00180 if (egg_tex->has_alpha_filename()) {
00181 Filename alpha_fullpath, alpha_outpath;
00182 path_replace->full_convert_path(egg_tex->get_alpha_filename(), additional_path,
00183 alpha_fullpath, alpha_outpath);
00184 egg_tex->set_alpha_filename(alpha_outpath);
00185 egg_tex->set_alpha_fullpath(alpha_fullpath);
00186 }
00187
00188 } else if (node->is_of_type(EggFilenameNode::get_class_type())) {
00189 EggFilenameNode *egg_fnode = DCAST(EggFilenameNode, node);
00190
00191 Filename fullpath, outpath;
00192 path_replace->full_convert_path(egg_fnode->get_filename(), additional_path,
00193 fullpath, outpath);
00194 egg_fnode->set_filename(outpath);
00195 egg_fnode->set_fullpath(fullpath);
00196
00197 } else if (node->is_of_type(EggGroupNode::get_class_type())) {
00198 EggGroupNode *egg_group = DCAST(EggGroupNode, node);
00199 EggGroupNode::const_iterator ci;
00200 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
00201 convert_paths(*ci, path_replace, additional_path);
00202 }
00203 }
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 void EggBase::
00218 append_command_comment(EggData *data) {
00219 append_command_comment(data, get_exec_command());
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 void EggBase::
00234 append_command_comment(EggData *data, const string &comment) {
00235 data->insert(data->begin(), new EggComment("", comment));
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 bool EggBase::
00247 dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
00248 EggBase *base = (EggBase *)self;
00249 return base->ns_dispatch_normals(opt, arg, mode);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 bool EggBase::
00261 ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
00262 _normals_mode = *(NormalsMode *)mode;
00263
00264 if (_normals_mode == NM_vertex) {
00265 if (!string_to_double(arg, _normals_threshold)) {
00266 nout << "Invalid numeric parameter for -" << opt << ": "
00267 << arg << "\n";
00268 return false;
00269 }
00270 }
00271
00272 return true;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 bool EggBase::
00282 dispatch_scale(const string &opt, const string &arg, void *var) {
00283 LMatrix4d *transform = (LMatrix4d *)var;
00284
00285 vector_string words;
00286 tokenize(arg, words, ",");
00287
00288 double sx, sy, sz;
00289
00290 bool okflag = false;
00291 if (words.size() == 3) {
00292 okflag =
00293 string_to_double(words[0], sx) &&
00294 string_to_double(words[1], sy) &&
00295 string_to_double(words[2], sz);
00296
00297 } else if (words.size() == 1) {
00298 okflag =
00299 string_to_double(words[0], sx);
00300 sy = sz = sx;
00301 }
00302
00303 if (!okflag) {
00304 nout << "-" << opt
00305 << " requires one or three numbers separated by commas.\n";
00306 return false;
00307 }
00308
00309 *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);
00310
00311 return true;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320 bool EggBase::
00321 dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
00322 EggBase *base = (EggBase *)self;
00323 return base->ns_dispatch_rotate_xyz(opt, arg, var);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332 bool EggBase::
00333 ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
00334 LMatrix4d *transform = (LMatrix4d *)var;
00335
00336 vector_string words;
00337 tokenize(arg, words, ",");
00338
00339 LVecBase3d xyz;
00340
00341 bool okflag = false;
00342 if (words.size() == 3) {
00343 okflag =
00344 string_to_double(words[0], xyz[0]) &&
00345 string_to_double(words[1], xyz[1]) &&
00346 string_to_double(words[2], xyz[2]);
00347 }
00348
00349 if (!okflag) {
00350 nout << "-" << opt
00351 << " requires three numbers separated by commas.\n";
00352 return false;
00353 }
00354
00355 LMatrix4d mat =
00356 LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
00357 LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
00358 LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);
00359
00360 *transform = (*transform) * mat;
00361
00362 return true;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 bool EggBase::
00372 dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
00373 EggBase *base = (EggBase *)self;
00374 return base->ns_dispatch_rotate_axis(opt, arg, var);
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 bool EggBase::
00384 ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
00385 LMatrix4d *transform = (LMatrix4d *)var;
00386
00387 vector_string words;
00388 tokenize(arg, words, ",");
00389
00390 double angle;
00391 LVecBase3d axis;
00392
00393 bool okflag = false;
00394 if (words.size() == 4) {
00395 okflag =
00396 string_to_double(words[0], angle) &&
00397 string_to_double(words[1], axis[0]) &&
00398 string_to_double(words[2], axis[1]) &&
00399 string_to_double(words[3], axis[2]);
00400 }
00401
00402 if (!okflag) {
00403 nout << "-" << opt
00404 << " requires four numbers separated by commas.\n";
00405 return false;
00406 }
00407
00408 *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);
00409
00410 return true;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 bool EggBase::
00420 dispatch_translate(const string &opt, const string &arg, void *var) {
00421 LMatrix4d *transform = (LMatrix4d *)var;
00422
00423 vector_string words;
00424 tokenize(arg, words, ",");
00425
00426 LVector3d trans;
00427
00428 bool okflag = false;
00429 if (words.size() == 3) {
00430 okflag =
00431 string_to_double(words[0], trans[0]) &&
00432 string_to_double(words[1], trans[1]) &&
00433 string_to_double(words[2], trans[2]);
00434 }
00435
00436 if (!okflag) {
00437 nout << "-" << opt
00438 << " requires three numbers separated by commas.\n";
00439 return false;
00440 }
00441
00442 *transform = (*transform) * LMatrix4d::translate_mat(trans);
00443
00444 return true;
00445 }