add fixrest

This commit is contained in:
David Rose 2003-07-22 18:11:19 +00:00
parent 8e132cb763
commit 85636c31ca
8 changed files with 89 additions and 41 deletions

View File

@ -45,6 +45,7 @@ EggOptchar() {
add_path_store_options();
add_normals_options();
add_transform_options();
add_fixrest_option();
set_program_description
("egg-optchar performs basic optimizations of a character model "

View File

@ -673,21 +673,28 @@ write(ostream &out, int indent_level) const {
// detected, such as inconsistent animation tables.
//
// In addition to reporting this errors, calling this
// function will also ensure that they are all repaired
// (although certain kinds of errors will be repaired
// regardless).
// function will also ensure that they are all repaired.
// Pass force_initial_rest_frame as true to also force
// rest frames from different models to be the same if
// they are initially different.
////////////////////////////////////////////////////////////////////
void EggCharacterCollection::
check_errors(ostream &out) {
check_errors(ostream &out, bool force_initial_rest_frame) {
Characters::const_iterator ci;
for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
EggCharacterData *char_data = (*ci);
int num_joints = char_data->get_num_joints();
for (int j = 0; j < num_joints; j++) {
EggJointData *joint_data = char_data->get_joint(j);
if (joint_data->_forced_rest_frames_equal) {
out << "Warning: rest frames for " << joint_data->get_name()
<< " were different.\n";
if (joint_data->rest_frames_differ()) {
if (force_initial_rest_frame) {
joint_data->force_initial_rest_frame();
out << "Forced rest frames the same for " << joint_data->get_name()
<< ".\n";
} else {
out << "Warning: rest frames for " << joint_data->get_name()
<< " differ.\n";
}
}
}

View File

@ -55,7 +55,7 @@ public:
INLINE EggCharacterData *get_character_by_model_index(int model_index) const;
virtual void write(ostream &out, int indent_level = 0) const;
void check_errors(ostream &out);
void check_errors(ostream &out, bool force_initial_rest_frame);
virtual EggCharacterData *make_character_data();
virtual EggJointData *make_joint_data(EggCharacterData *char_data);

View File

@ -29,6 +29,8 @@
EggCharacterFilter::
EggCharacterFilter() : EggMultiFilter(false) {
_collection = (EggCharacterCollection *)NULL;
_force_initial_rest_frame = false;
}
////////////////////////////////////////////////////////////////////
@ -43,6 +45,23 @@ EggCharacterFilter::
}
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterFilter::add_fixrest_option
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void EggCharacterFilter::
add_fixrest_option() {
add_option
("fixrest", "", 50,
"Specify this to force all the initial rest frames of the various "
"model files to the same value as the first model specified. This "
"is a fairly drastic way to repair models whose initial rest frame "
"values are completely bogus, but should not be performed when the "
"input models are correct.",
&EggCharacterFilter::dispatch_none, &_force_initial_rest_frame);
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterFilter::post_command_line
@ -70,7 +89,7 @@ post_command_line() {
}
}
_collection->check_errors(nout);
_collection->check_errors(nout, _force_initial_rest_frame);
return true;
}

View File

@ -42,6 +42,8 @@ public:
EggCharacterFilter();
virtual ~EggCharacterFilter();
void add_fixrest_option();
protected:
virtual bool post_command_line();
virtual void write_eggs();
@ -49,6 +51,7 @@ protected:
virtual EggCharacterCollection *make_collection();
EggCharacterCollection *_collection;
bool _force_initial_rest_frame;
};
#endif

View File

@ -61,6 +61,19 @@ has_rest_frame() const {
return _has_rest_frame;
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::rest_frames_differ
// Access: Public
// Description: Returns true if the rest frames for different models
// differ in their initial value. This is not
// technically an error, but it is unusual enough to be
// suspicious.
////////////////////////////////////////////////////////////////////
INLINE bool EggJointData::
rest_frames_differ() const {
return _rest_frames_differ;
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::get_rest_frame
// Access: Public

View File

@ -41,7 +41,7 @@ EggJointData(EggCharacterCollection *collection,
_parent = (EggJointData *)NULL;
_new_parent = (EggJointData *)NULL;
_has_rest_frame = false;
_forced_rest_frames_equal = false;
_rest_frames_differ = false;
}
////////////////////////////////////////////////////////////////////
@ -103,6 +103,33 @@ get_net_frame(int model_index, int n) const {
return mat;
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::force_initial_rest_frame
// Access: Public
// Description: Forces all of the joints to have the same rest frame
// value as the first joint read in. This is a drastic
// way to repair models whose rest frame values are
// completely bogus, but should not be performed on
// models that are otherwise correct.
////////////////////////////////////////////////////////////////////
void EggJointData::
force_initial_rest_frame() {
if (!has_rest_frame()) {
return;
}
int num_models = get_num_models();
for (int model_index = 0; model_index < num_models; model_index++) {
if (has_model(model_index)) {
EggJointPointer *joint;
DCAST_INTO_V(joint, get_model(model_index));
if (joint->is_of_type(EggJointNodePointer::get_class_type())) {
joint->set_frame(0, get_rest_frame());
}
}
}
_rest_frames_differ = false;
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::move_vertices_to
// Access: Public
@ -185,8 +212,8 @@ optimize() {
////////////////////////////////////////////////////////////////////
// Function: EggJointData::expose
// Access: Public
// Description: Calls expose() on all models, and recursively on
// all joints at this node and below.
// Description: Calls expose() on all models for this joint, but does
// not recurse downwards.
////////////////////////////////////////////////////////////////////
void EggJointData::
expose(EggGroup::DCSType dcs_type) {
@ -199,19 +226,13 @@ expose(EggGroup::DCSType dcs_type) {
joint->expose(dcs_type);
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggJointData *child = (*ci);
child->expose(dcs_type);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::zero_channels
// Access: Public
// Description: Calls zero_channels() on all models, and recursively on
// all joints at this node and below.
// Description: Calls zero_channels() on all models for this joint,
// but does not recurse downwards.
////////////////////////////////////////////////////////////////////
void EggJointData::
zero_channels(const string &components) {
@ -224,12 +245,6 @@ zero_channels(const string &components) {
joint->zero_channels(components);
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggJointData *child = (*ci);
child->zero_channels(components);
}
}
////////////////////////////////////////////////////////////////////
@ -253,21 +268,9 @@ add_back_pointer(int model_index, EggObject *egg_object) {
// If this new node doesn't come within an acceptable tolerance
// of our first reading of this joint's rest frame, set a
// warning flag.
if (!_rest_frame.almost_equal(joint->get_frame(0), 0.001)) {
_forced_rest_frames_equal = true;
if (!_rest_frame.almost_equal(joint->get_frame(0), 0.0001)) {
_rest_frames_differ = true;
}
// In any case, ensure the rest frames are exactly equal.
// Actually, this may not be a good idea; it is, in fact, valid
// (although unusual) for different models to have different
// rest frames, provided their vertices appriopriately reflect
// the different rest frames. But we do have at least one
// character, Mickey, for which some of the lower-level LOD's
// have different rest frames that are in fact completely wrong,
// so forcing them all to the same value is correct in that
// case. Maybe this should be a command-line option.
joint->set_frame(0, _rest_frame);
}
} else if (egg_object->is_of_type(EggTable::get_class_type())) {

View File

@ -47,7 +47,9 @@ public:
LMatrix4d get_net_frame(int model_index, int n) const;
INLINE bool has_rest_frame() const;
INLINE bool rest_frames_differ() const;
INLINE const LMatrix4d &get_rest_frame() const;
void force_initial_rest_frame();
INLINE void reparent_to(EggJointData *new_parent);
void move_vertices_to(EggJointData *new_owner);
@ -72,7 +74,7 @@ private:
LMatrix4d get_new_frame(int model_index, int n);
bool _has_rest_frame;
bool _forced_rest_frames_equal;
bool _rest_frames_differ;
LMatrix4d _rest_frame;
// These are used to cache the above results for optimizing