|
|
@@ -23,6 +23,7 @@
|
|
|
#include "eggFilenameNode.h"
|
|
|
#include "eggComment.h"
|
|
|
#include "dcast.h"
|
|
|
+#include "string_utils.h"
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: EggBase::Constructor
|
|
|
@@ -39,40 +40,86 @@ EggBase() {
|
|
|
&_got_coordinate_system, &_coordinate_system);
|
|
|
|
|
|
_coordinate_system = CS_yup_right;
|
|
|
+
|
|
|
+ _normals_mode = NM_preserve;
|
|
|
+ _normals_threshold = 0.0;
|
|
|
+
|
|
|
+ _got_transform = false;
|
|
|
+ _transform = LMatrix4d::ident_mat();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: EggBase::as_reader
|
|
|
-// Access: Public, Virtual
|
|
|
-// Description: Returns this object as an EggReader pointer, if it is
|
|
|
-// in fact an EggReader, or NULL if it is not.
|
|
|
-//
|
|
|
-// This is intended to work around the C++ limitation
|
|
|
-// that prevents downcasts past virtual inheritance.
|
|
|
-// Since both EggReader and EggWriter inherit virtually
|
|
|
-// from EggBase, we need functions like this to downcast
|
|
|
-// to the appropriate pointer.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-EggReader *EggBase::
|
|
|
-as_reader() {
|
|
|
- return (EggReader *)NULL;
|
|
|
+// Function: EggBase::add_normals_options
|
|
|
+// Access: Public
|
|
|
+// Description: Adds -no, -np, etc. as valid options for this
|
|
|
+// program. If the user specifies one of the options on
|
|
|
+// the command line, the normals will be adjusted when
|
|
|
+// the egg file is written out.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void EggBase::
|
|
|
+add_normals_options() {
|
|
|
+ static NormalsMode strip = NM_strip;
|
|
|
+ static NormalsMode polygon = NM_polygon;
|
|
|
+ static NormalsMode vertex = NM_vertex;
|
|
|
+ static NormalsMode preserve = NM_preserve;
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("no", "", 48,
|
|
|
+ "Strip all normals.",
|
|
|
+ &EggBase::dispatch_normals, NULL, &strip);
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("np", "", 48,
|
|
|
+ "Strip existing normals and redefine polygon normals.",
|
|
|
+ &EggBase::dispatch_normals, NULL, &polygon);
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("nv", "threshold", 48,
|
|
|
+ "Strip existing normals and redefine vertex normals. Consider an edge "
|
|
|
+ "between adjacent polygons to be smooth if the angle between them "
|
|
|
+ "is less than threshold degrees.",
|
|
|
+ &EggBase::dispatch_normals, NULL, &vertex);
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("nn", "", 48,
|
|
|
+ "Preserve normals exactly as they are. This is the default.",
|
|
|
+ &EggBase::dispatch_normals, NULL, &preserve);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: EggBase::as_writer
|
|
|
-// Access: Public, Virtual
|
|
|
-// Description: Returns this object as an EggWriter pointer, if it is
|
|
|
-// in fact an EggWriter, or NULL if it is not.
|
|
|
-//
|
|
|
-// This is intended to work around the C++ limitation
|
|
|
-// that prevents downcasts past virtual inheritance.
|
|
|
-// Since both EggReader and EggWriter inherit virtually
|
|
|
-// from EggBase, we need functions like this to downcast
|
|
|
-// to the appropriate pointer.
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-EggWriter *EggBase::
|
|
|
-as_writer() {
|
|
|
- return (EggWriter *)NULL;
|
|
|
+// Function: EggBase::add_transform_options
|
|
|
+// Access: Public
|
|
|
+// Description: Adds -TS, -TT, etc. as valid options for this
|
|
|
+// program. If the user specifies one of the options on
|
|
|
+// the command line, the data will be transformed when
|
|
|
+// the egg file is written out.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void EggBase::
|
|
|
+add_transform_options() {
|
|
|
+ add_option
|
|
|
+ ("TS", "sx[,sy,sz]", 49,
|
|
|
+ "Scale the model uniformly by the given factor (if only one number "
|
|
|
+ "is given) or in each axis by sx, sy, sz (if three numbers are given).",
|
|
|
+ &EggBase::dispatch_scale, &_got_transform, &_transform);
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("TR", "x,y,z", 49,
|
|
|
+ "Rotate the model x degrees about the x axis, then y degrees about the "
|
|
|
+ "y axis, and then z degrees about the z axis.",
|
|
|
+ &EggBase::dispatch_rotate_xyz, &_got_transform, &_transform);
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("TA", "angle,x,y,z", 49,
|
|
|
+ "Rotate the model angle degrees counterclockwise about the given "
|
|
|
+ "axis.",
|
|
|
+ &EggBase::dispatch_rotate_axis, &_got_transform, &_transform);
|
|
|
+
|
|
|
+ add_option
|
|
|
+ ("TT", "x,y,z", 49,
|
|
|
+ "Translate the model by the indicated amount.\n\n"
|
|
|
+ "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
|
|
|
+ "applied in the order they are encountered on the command line.",
|
|
|
+ &EggBase::dispatch_translate, &_got_transform, &_transform);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -116,21 +163,6 @@ convert_paths(EggNode *node, PathReplace *path_replace,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-// Function: EggBase::post_command_line
|
|
|
-// Access: Protected, Virtual
|
|
|
-// Description:
|
|
|
-////////////////////////////////////////////////////////////////////
|
|
|
-bool EggBase::
|
|
|
-post_command_line() {
|
|
|
- if (_got_coordinate_system) {
|
|
|
- _data.set_coordinate_system(_coordinate_system);
|
|
|
- }
|
|
|
-
|
|
|
- return ProgramBase::post_command_line();
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: EggBase::append_command_comment
|
|
|
// Access: Protected
|
|
|
@@ -162,3 +194,212 @@ void EggBase::
|
|
|
append_command_comment(EggData &data, const string &comment) {
|
|
|
data.insert(data.begin(), new EggComment("", comment));
|
|
|
}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::dispatch_normals
|
|
|
+// Access: Protected, Static
|
|
|
+// Description: Accepts one of -no, -np, etc. and sets _normals_mode
|
|
|
+// as indicated. The void * argument is a pointer to a
|
|
|
+// NormalsMode variable that indicates which switch was
|
|
|
+// passed.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+dispatch_normals(ProgramBase *self, const string &opt, const string &arg, void *mode) {
|
|
|
+ EggBase *base = (EggBase *)self;
|
|
|
+ return base->ns_dispatch_normals(opt, arg, mode);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::ns_dispatch_normals
|
|
|
+// Access: Protected
|
|
|
+// Description: Accepts one of -no, -np, etc. and sets _normals_mode
|
|
|
+// as indicated. The void * argument is a pointer to a
|
|
|
+// NormalsMode variable that indicates which switch was
|
|
|
+// passed.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+ns_dispatch_normals(const string &opt, const string &arg, void *mode) {
|
|
|
+ _normals_mode = *(NormalsMode *)mode;
|
|
|
+
|
|
|
+ if (_normals_mode == NM_vertex) {
|
|
|
+ if (!string_to_double(arg, _normals_threshold)) {
|
|
|
+ nout << "Invalid numeric parameter for -" << opt << ": "
|
|
|
+ << arg << "\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::dispatch_scale
|
|
|
+// Access: Protected, Static
|
|
|
+// Description: Handles -TS, which specifies a scale transform. Var
|
|
|
+// is an LMatrix4d.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+dispatch_scale(const string &opt, const string &arg, void *var) {
|
|
|
+ LMatrix4d *transform = (LMatrix4d *)var;
|
|
|
+
|
|
|
+ vector_string words;
|
|
|
+ tokenize(arg, words, ",");
|
|
|
+
|
|
|
+ double sx, sy, sz;
|
|
|
+
|
|
|
+ bool okflag = false;
|
|
|
+ if (words.size() == 3) {
|
|
|
+ okflag =
|
|
|
+ string_to_double(words[0], sx) &&
|
|
|
+ string_to_double(words[1], sy) &&
|
|
|
+ string_to_double(words[2], sz);
|
|
|
+
|
|
|
+ } else if (words.size() == 1) {
|
|
|
+ okflag =
|
|
|
+ string_to_double(words[0], sx);
|
|
|
+ sy = sz = sx;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!okflag) {
|
|
|
+ nout << "-" << opt
|
|
|
+ << " requires one or three numbers separated by commas.\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ *transform = (*transform) * LMatrix4d::scale_mat(sx, sy, sz);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::dispatch_rotate_xyz
|
|
|
+// Access: Protected, Static
|
|
|
+// Description: Handles -TR, which specifies a rotate transform about
|
|
|
+// the three cardinal axes. Var is an LMatrix4d.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+dispatch_rotate_xyz(ProgramBase *self, const string &opt, const string &arg, void *var) {
|
|
|
+ EggBase *base = (EggBase *)self;
|
|
|
+ return base->ns_dispatch_rotate_xyz(opt, arg, var);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::ns_dispatch_rotate_xyz
|
|
|
+// Access: Protected
|
|
|
+// Description: Handles -TR, which specifies a rotate transform about
|
|
|
+// the three cardinal axes. Var is an LMatrix4d.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+ns_dispatch_rotate_xyz(const string &opt, const string &arg, void *var) {
|
|
|
+ LMatrix4d *transform = (LMatrix4d *)var;
|
|
|
+
|
|
|
+ vector_string words;
|
|
|
+ tokenize(arg, words, ",");
|
|
|
+
|
|
|
+ LVecBase3d xyz;
|
|
|
+
|
|
|
+ bool okflag = false;
|
|
|
+ if (words.size() == 3) {
|
|
|
+ okflag =
|
|
|
+ string_to_double(words[0], xyz[0]) &&
|
|
|
+ string_to_double(words[1], xyz[1]) &&
|
|
|
+ string_to_double(words[2], xyz[2]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!okflag) {
|
|
|
+ nout << "-" << opt
|
|
|
+ << " requires three numbers separated by commas.\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ LMatrix4d mat =
|
|
|
+ LMatrix4d::rotate_mat(xyz[0], LVector3d(1.0, 0.0, 0.0), _coordinate_system) *
|
|
|
+ LMatrix4d::rotate_mat(xyz[1], LVector3d(0.0, 1.0, 0.0), _coordinate_system) *
|
|
|
+ LMatrix4d::rotate_mat(xyz[2], LVector3d(0.0, 0.0, 1.0), _coordinate_system);
|
|
|
+
|
|
|
+ *transform = (*transform) * mat;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::dispatch_rotate_axis
|
|
|
+// Access: Protected, Static
|
|
|
+// Description: Handles -TA, which specifies a rotate transform about
|
|
|
+// an arbitrary axis. Var is an LMatrix4d.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+dispatch_rotate_axis(ProgramBase *self, const string &opt, const string &arg, void *var) {
|
|
|
+ EggBase *base = (EggBase *)self;
|
|
|
+ return base->ns_dispatch_rotate_axis(opt, arg, var);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::ns_dispatch_rotate_axis
|
|
|
+// Access: Protected
|
|
|
+// Description: Handles -TA, which specifies a rotate transform about
|
|
|
+// an arbitrary axis. Var is an LMatrix4d.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+ns_dispatch_rotate_axis(const string &opt, const string &arg, void *var) {
|
|
|
+ LMatrix4d *transform = (LMatrix4d *)var;
|
|
|
+
|
|
|
+ vector_string words;
|
|
|
+ tokenize(arg, words, ",");
|
|
|
+
|
|
|
+ double angle;
|
|
|
+ LVecBase3d axis;
|
|
|
+
|
|
|
+ bool okflag = false;
|
|
|
+ if (words.size() == 4) {
|
|
|
+ okflag =
|
|
|
+ string_to_double(words[0], angle) &&
|
|
|
+ string_to_double(words[1], axis[0]) &&
|
|
|
+ string_to_double(words[2], axis[1]) &&
|
|
|
+ string_to_double(words[3], axis[2]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!okflag) {
|
|
|
+ nout << "-" << opt
|
|
|
+ << " requires four numbers separated by commas.\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ *transform = (*transform) * LMatrix4d::rotate_mat(angle, axis, _coordinate_system);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: EggBase::dispatch_translate
|
|
|
+// Access: Protected, Static
|
|
|
+// Description: Handles -TT, which specifies a translate transform.
|
|
|
+// Var is an LMatrix4d.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool EggBase::
|
|
|
+dispatch_translate(const string &opt, const string &arg, void *var) {
|
|
|
+ LMatrix4d *transform = (LMatrix4d *)var;
|
|
|
+
|
|
|
+ vector_string words;
|
|
|
+ tokenize(arg, words, ",");
|
|
|
+
|
|
|
+ LVector3d trans;
|
|
|
+
|
|
|
+ bool okflag = false;
|
|
|
+ if (words.size() == 3) {
|
|
|
+ okflag =
|
|
|
+ string_to_double(words[0], trans[0]) &&
|
|
|
+ string_to_double(words[1], trans[1]) &&
|
|
|
+ string_to_double(words[2], trans[2]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!okflag) {
|
|
|
+ nout << "-" << opt
|
|
|
+ << " requires three numbers separated by commas.\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ *transform = (*transform) * LMatrix4d::translate_mat(trans);
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|