add egg-optchar -qa

This commit is contained in:
David Rose 2004-10-11 20:41:09 +00:00
parent 21483c7e2b
commit b8ade26846
8 changed files with 186 additions and 7 deletions

View File

@ -149,11 +149,24 @@ EggOptchar() {
add_option
("q", "quantum", 0,
"Quantize joint membership values to the given unit. This is "
"the smallest significant change in joint membership. The "
"default is 0.01; specifying 0 means to preserve the original "
"values.",
"the smallest significant change in joint membership. There can "
"be a significant performance (and memory utilization) runtime "
"benefit for eliminating small differences in joint memberships "
"between neighboring vertices. The default is 0.01; specifying "
"0 means to preserve the original values.",
&EggOptchar::dispatch_double, NULL, &_vref_quantum);
add_option
("qa", "quantum[,hprxyzijkabc]", 0,
"Quantizes animation channels to the given unit. This rounds each "
"of the named components of all joints to the nearest multiple of unit. "
"There is no performance benefit, and little compression benefit, "
"for doing this; and this may introduce visible artifacts to the "
"animation. However, sometimes it is a useful tool for animation "
"analysis and comparison. This option may be repeated several times "
"to quantize different channels by a different amount.",
&EggOptchar::dispatch_double_components, NULL, &_quantize_anims);
_optimal_hierarchy = false;
_vref_quantum = 0.01;
}
@ -218,15 +231,18 @@ run() {
do_reparent();
}
// We currently do not implement optimizing morph sliders. Need
// to add this at some point; it's quite easy. Identity and empty
// morph sliders can simply be removed, while static sliders need
// to be applied to the vertices and then removed.
// Quantize the vertex memberships. We call this even if
// _vref_quantum is 0, because this also normalizes the vertex
// memberships.
quantize_vertices();
// We currently do not implement optimizing morph sliders. Need
// to add this at some point; it's quite easy. Identity and empty
// morph sliders can simply be removed, while static sliders need
// to be applied to the vertices and then removed.
// Also quantize the animation channels, if the user so requested.
quantize_channels();
// Finally, flag all the groups as the user requested.
if (!_flag_groups.empty()) {
@ -336,6 +352,63 @@ dispatch_name_components(const string &opt, const string &arg, void *var) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ProgramBase::dispatch_double_components
// Access: Protected, Static
// Description: Accepts a double value optionally followed by a comma
// and some of the nine standard component letters,
//
// The data pointer is to a DoubleStrings vector; the
// pair will be pushed onto the end of the vector.
////////////////////////////////////////////////////////////////////
bool EggOptchar::
dispatch_double_components(const string &opt, const string &arg, void *var) {
DoubleStrings *ip = (DoubleStrings *)var;
vector_string words;
tokenize(arg, words, ",");
bool valid_double = false;
DoubleString sp;
if (words.size() == 1) {
valid_double = string_to_double(words[0], sp._a);
} else if (words.size() == 2) {
valid_double = string_to_double(words[0], sp._a);
sp._b = words[1];
} else {
nout << "-" << opt
<< " requires a numeric value followed by a string.\n";
return false;
}
if (!valid_double) {
nout << "-" << opt
<< " requires a numeric value followed by a string.\n";
return false;
}
if (sp._b.empty()) {
sp._b = matrix_component_letters;
} else {
for (string::const_iterator si = sp._b.begin(); si != sp._b.end(); ++si) {
if (strchr(matrix_component_letters, *si) == NULL) {
nout << "Not a standard matrix component: \"" << *si << "\"\n"
<< "-" << opt << " requires a joint name followed by a set "
<< "of component names. The standard component names are \""
<< matrix_component_letters << "\".\n";
return false;
}
}
}
ip->push_back(sp);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ProgramBase::dispatch_flag_groups
// Access: Protected, Static
@ -775,6 +848,38 @@ zero_channels() {
return did_anything;
}
////////////////////////////////////////////////////////////////////
// Function: EggOptchar::quantize_channels
// Access: Private
// Description: Quantizes the channels specified by the user on the
// command line.
//
// Returns true if any operation was performed, false
// otherwise.
////////////////////////////////////////////////////////////////////
bool EggOptchar::
quantize_channels() {
bool did_anything = false;
int num_characters = _collection->get_num_characters();
DoubleStrings::const_iterator spi;
for (spi = _quantize_anims.begin(); spi != _quantize_anims.end(); ++spi) {
const DoubleString &p = (*spi);
for (int ci = 0; ci < num_characters; ci++) {
EggCharacterData *char_data = _collection->get_character(ci);
EggJointData *joint_data = char_data->get_root_joint();
if (joint_data != (EggJointData *)NULL) {
joint_data->quantize_channels(p._b, p._a);
did_anything = true;
}
}
}
return did_anything;
}
////////////////////////////////////////////////////////////////////
// Function: EggOptchar::analyze_joints
// Access: Private

View File

@ -54,6 +54,7 @@ protected:
private:
static bool dispatch_vector_string_pair(const string &opt, const string &arg, void *var);
static bool dispatch_name_components(const string &opt, const string &arg, void *var);
static bool dispatch_double_components(const string &opt, const string &arg, void *var);
static bool dispatch_flag_groups(const string &opt, const string &arg, void *var);
void determine_removed_components();
@ -64,6 +65,7 @@ private:
bool apply_user_reparents();
bool zero_channels();
bool quantize_channels();
void analyze_joints(EggJointData *joint_data, int level);
void analyze_sliders(EggCharacterData *char_data);
void list_joints(EggJointData *joint_data, int indent_level, bool verbose);
@ -99,6 +101,14 @@ private:
vector_string _drop_components;
vector_string _expose_components;
class DoubleString {
public:
double _a;
string _b;
};
typedef pvector<DoubleString> DoubleStrings;
DoubleStrings _quantize_anims;
typedef pvector<GlobPattern> Globs;
class FlagGroupsEntry {

View File

@ -400,6 +400,31 @@ zero_channels(const string &components) {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::quantize_channels
// Access: Public
// Description: Calls quantize_channels() on all models for this joint,
// and then recurses downwards to all joints below.
////////////////////////////////////////////////////////////////////
void EggJointData::
quantize_channels(const string &components, double quantum) {
BackPointers::iterator bpi;
for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
EggBackPointer *back = (*bpi);
if (back != (EggBackPointer *)NULL) {
EggJointPointer *joint;
DCAST_INTO_V(joint, back);
joint->quantize_channels(components, quantum);
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggJointData *child = (*ci);
child->quantize_channels(components, quantum);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::add_back_pointer
// Access: Public, Virtual

View File

@ -61,6 +61,7 @@ public:
void optimize();
void expose(EggGroup::DCSType dcs_type = EggGroup::DC_default);
void zero_channels(const string &components);
void quantize_channels(const string &components, double quantum);
virtual void add_back_pointer(int model_index, EggObject *egg_object);
virtual void write(ostream &out, int indent_level = 0) const;

View File

@ -125,3 +125,13 @@ expose(EggGroup::DCSType) {
void EggJointPointer::
zero_channels(const string &) {
}
////////////////////////////////////////////////////////////////////
// Function: EggJointPointer::quantize_channels
// Access: Public, Virtual
// Description: Rounds the named components of the transform to the
// nearest multiple of quantum.
////////////////////////////////////////////////////////////////////
void EggJointPointer::
quantize_channels(const string &, double) {
}

View File

@ -63,6 +63,7 @@ public:
virtual void optimize();
virtual void expose(EggGroup::DCSType dcs_type);
virtual void zero_channels(const string &components);
virtual void quantize_channels(const string &components, double quantum);
virtual EggJointPointer *make_new_joint(const string &name)=0;

View File

@ -250,6 +250,32 @@ zero_channels(const string &components) {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMatrixTablePointer::quantize_channels
// Access: Public, Virtual
// Description: Rounds the named components of the transform to the
// nearest multiple of quantum.
////////////////////////////////////////////////////////////////////
void EggMatrixTablePointer::
quantize_channels(const string &components, double quantum) {
if (_xform == (EggXfmSAnim *)NULL) {
return;
}
// This is similar to the above: we quantize children of the _xform
// object whose name is listed in the components.
string::const_iterator si;
for (si = components.begin(); si != components.end(); ++si) {
string table_name(1, *si);
EggNode *child = _xform->find_child(table_name);
if (child != (EggNode *)NULL &&
child->is_of_type(EggSAnimData::get_class_type())) {
EggSAnimData *anim = DCAST(EggSAnimData, child);
anim->quantize(quantum);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMatrixTablePointer::make_new_joint
// Access: Public, Virtual

View File

@ -50,6 +50,7 @@ public:
virtual void optimize();
virtual void zero_channels(const string &components);
virtual void quantize_channels(const string &components, double quantum);
virtual EggJointPointer *make_new_joint(const string &name);