handle some broken egg files more gracefully
This commit is contained in:
parent
6b7baa43d7
commit
c9e4bbc9c0
|
|
@ -30,6 +30,17 @@ EggBackPointer::
|
|||
EggBackPointer() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggBackPointer::extend_to
|
||||
// Access: Public, Virtual
|
||||
// Description: Extends the table to the indicated number of frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggBackPointer::
|
||||
extend_to(int num_frames) {
|
||||
// Whoops, can't extend this kind of table!
|
||||
nassertv(false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggBackPointer::has_vertices
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ class EggBackPointer : public TypedObject {
|
|||
public:
|
||||
EggBackPointer();
|
||||
|
||||
virtual int get_num_frames() const=0;
|
||||
virtual void extend_to(int num_frames);
|
||||
virtual bool has_vertices() const;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ add_egg(EggData *egg) {
|
|||
}
|
||||
egg_info._models.push_back(model_root);
|
||||
|
||||
char_data->add_model(model_index, model_root);
|
||||
char_data->add_model(model_index, model_root, egg);
|
||||
nassertr(model_index == (int)_characters_by_model_index.size(), -1);
|
||||
_characters_by_model_index.push_back(char_data);
|
||||
root_joint->add_back_pointer(model_index, desc._root_node);
|
||||
|
|
@ -663,3 +663,42 @@ write(ostream &out, int indent_level) const {
|
|||
char_data->write(out, indent_level);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterCollection::check_errors
|
||||
// Access: Public
|
||||
// Description: Can be called after the collection has been
|
||||
// completely filled up with egg files to output any
|
||||
// messages from warning conditions that have been
|
||||
// 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).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggCharacterCollection::
|
||||
check_errors(ostream &out) {
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
int num_models = char_data->get_num_models();
|
||||
for (int mi = 0; mi < num_models; mi++) {
|
||||
int model_index = char_data->get_model_index(mi);
|
||||
if (!char_data->check_num_frames(model_index)) {
|
||||
out << "Warning: animation from "
|
||||
<< char_data->get_egg_data(model_index)->get_egg_filename().get_basename()
|
||||
<< " had an inconsistent number of frames.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +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);
|
||||
|
||||
virtual EggCharacterData *make_character_data();
|
||||
virtual EggJointData *make_joint_data(EggCharacterData *char_data);
|
||||
|
|
|
|||
|
|
@ -68,6 +68,19 @@ get_model_root(int n) const {
|
|||
return _models[n]._model_root;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterData::get_egg_data
|
||||
// Access: Public
|
||||
// Description: Returns the EggData representing the egg file that
|
||||
// defined this particular model. Note that one egg
|
||||
// file might contain multiple models.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EggData *EggCharacterData::
|
||||
get_egg_data(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_models.size(), (EggData *)NULL);
|
||||
return _models[n]._egg_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterData::get_root_joint
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -65,10 +65,11 @@ EggCharacterData::
|
|||
// file: in either case, a hierarchy of joints.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggCharacterData::
|
||||
add_model(int model_index, EggNode *model_root) {
|
||||
add_model(int model_index, EggNode *model_root, EggData *egg_data) {
|
||||
Model m;
|
||||
m._model_index = model_index;
|
||||
m._model_root = model_root;
|
||||
m._egg_data = egg_data;
|
||||
_models.push_back(m);
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +103,49 @@ get_num_frames(int model_index) const {
|
|||
return max_num_frames;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterData::check_num_frames
|
||||
// Access: Public
|
||||
// Description: Walks through each component and ensures that all
|
||||
// have the same number of frames of animation (except
|
||||
// for those that contain 0 or 1 frames, of course).
|
||||
// Returns true if all are valid, false if there is a
|
||||
// discreprency (in which case the shorter component are
|
||||
// extended).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggCharacterData::
|
||||
check_num_frames(int model_index) {
|
||||
int max_num_frames = 0;
|
||||
bool any_violations = false;
|
||||
Components::const_iterator ci;
|
||||
for (ci = _components.begin(); ci != _components.end(); ++ci) {
|
||||
EggComponentData *component = (*ci);
|
||||
int num_frames = component->get_num_frames(model_index);
|
||||
if (num_frames > 1 && max_num_frames > 1 &&
|
||||
max_num_frames != num_frames) {
|
||||
// If we have two different opinions about the number of frames
|
||||
// (other than 0 or 1), we have a discrepency. This is an error
|
||||
// condition.
|
||||
any_violations = true;
|
||||
}
|
||||
max_num_frames = max(max_num_frames, num_frames);
|
||||
}
|
||||
|
||||
if (any_violations) {
|
||||
// Now go back through and force all components to the appropriate
|
||||
// length.
|
||||
for (ci = _components.begin(); ci != _components.end(); ++ci) {
|
||||
EggComponentData *component = (*ci);
|
||||
int num_frames = component->get_num_frames(model_index);
|
||||
if (num_frames > 1 && max_num_frames != num_frames) {
|
||||
component->extend_to(model_index, max_num_frames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !any_violations;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterData::do_reparent
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "eggJointData.h"
|
||||
|
||||
#include "eggNode.h"
|
||||
#include "eggData.h"
|
||||
#include "pointerTo.h"
|
||||
#include "namable.h"
|
||||
|
||||
|
|
@ -64,11 +65,13 @@ public:
|
|||
EggCharacterData(EggCharacterCollection *collection);
|
||||
virtual ~EggCharacterData();
|
||||
|
||||
void add_model(int model_index, EggNode *model_root);
|
||||
void add_model(int model_index, EggNode *model_root, EggData *egg_data);
|
||||
INLINE int get_num_models() const;
|
||||
INLINE int get_model_index(int n) const;
|
||||
INLINE EggNode *get_model_root(int n) const;
|
||||
INLINE EggData *get_egg_data(int n) const;
|
||||
int get_num_frames(int model_index) const;
|
||||
bool check_num_frames(int model_index);
|
||||
|
||||
INLINE EggJointData *get_root_joint() const;
|
||||
INLINE EggJointData *find_joint(const string &name) const;
|
||||
|
|
@ -91,6 +94,7 @@ protected:
|
|||
public:
|
||||
int _model_index;
|
||||
PT(EggNode) _model_root;
|
||||
PT(EggData) _egg_data;
|
||||
};
|
||||
typedef pvector<Model> Models;
|
||||
Models _models;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,8 @@ post_command_line() {
|
|||
}
|
||||
}
|
||||
|
||||
_collection->check_errors(nout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef EGGCHARACTERFILTER_H
|
||||
#define EGGCHARACTERFILTER_H
|
||||
|
||||
#include <pandatoolbase.h>
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "eggMultiFilter.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,35 @@ matches_name(const string &name) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggComponentData::get_num_frames
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the number of frames of animation for this
|
||||
// particular component in the indicated model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggComponentData::
|
||||
get_num_frames(int model_index) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
return 0;
|
||||
}
|
||||
return back->get_num_frames();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggComponentData::extend_to
|
||||
// Access: Public, Virtual
|
||||
// Description: Extends the number of frames in the indicated model
|
||||
// (presumably an animation table model) to the given
|
||||
// number.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggComponentData::
|
||||
extend_to(int model_index, int num_frames) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
nassertv(back != (EggBackPointer *)NULL);
|
||||
return back->extend_to(num_frames);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggComponentData::set_model
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ public:
|
|||
void add_name(const string &name);
|
||||
bool matches_name(const string &name) const;
|
||||
|
||||
virtual int get_num_frames(int model_index) const=0;
|
||||
int get_num_frames(int model_index) const;
|
||||
void extend_to(int model_index, int num_frames) const;
|
||||
|
||||
virtual void add_back_pointer(int model_index, EggObject *egg_object)=0;
|
||||
virtual void write(ostream &out, int indent_level = 0) const=0;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,32 @@ get_child(int n) const {
|
|||
return _children[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::has_rest_frame
|
||||
// Access: Public
|
||||
// Description: Returns true if the joint knows its rest frame, false
|
||||
// otherwise. In general, this will be true as long as
|
||||
// the joint is included in at least one model file, or
|
||||
// false if it appears only in animation files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool EggJointData::
|
||||
has_rest_frame() const {
|
||||
return _has_rest_frame;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::get_rest_frame
|
||||
// Access: Public
|
||||
// Description: Returns the rest frame of the joint. This is the
|
||||
// matrix value that appears for the joint in each model
|
||||
// file; it should be the same transform in each model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LMatrix4d &EggJointData::
|
||||
get_rest_frame() const {
|
||||
nassertr(has_rest_frame(), LMatrix4d::ident_mat());
|
||||
return _rest_frame;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::reparent_to
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ EggJointData(EggCharacterCollection *collection,
|
|||
{
|
||||
_parent = (EggJointData *)NULL;
|
||||
_new_parent = (EggJointData *)NULL;
|
||||
_has_rest_frame = false;
|
||||
_forced_rest_frames_equal = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -65,25 +67,6 @@ find_joint(const string &name) {
|
|||
return (EggJointData *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::get_num_frames
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the number of frames of animation for this
|
||||
// particular joint in the indicated model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggJointData::
|
||||
get_num_frames(int model_index) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, 0);
|
||||
|
||||
return joint->get_num_frames();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::get_frame
|
||||
// Access: Public
|
||||
|
|
@ -262,6 +245,30 @@ add_back_pointer(int model_index, EggObject *egg_object) {
|
|||
// It must be a <Joint>.
|
||||
EggJointNodePointer *joint = new EggJointNodePointer(egg_object);
|
||||
set_model(model_index, joint);
|
||||
if (!_has_rest_frame) {
|
||||
_rest_frame = joint->get_frame(0);
|
||||
_has_rest_frame = true;
|
||||
|
||||
} else {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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())) {
|
||||
// It's a <Table> with an "xform" child beneath it.
|
||||
|
|
|
|||
|
|
@ -43,10 +43,12 @@ public:
|
|||
INLINE EggJointData *get_child(int n) const;
|
||||
EggJointData *find_joint(const string &name);
|
||||
|
||||
virtual int get_num_frames(int model_index) const;
|
||||
LMatrix4d get_frame(int model_index, int n) const;
|
||||
LMatrix4d get_net_frame(int model_index, int n) const;
|
||||
|
||||
INLINE bool has_rest_frame() const;
|
||||
INLINE const LMatrix4d &get_rest_frame() const;
|
||||
|
||||
INLINE void reparent_to(EggJointData *new_parent);
|
||||
void move_vertices_to(EggJointData *new_owner);
|
||||
|
||||
|
|
@ -69,6 +71,10 @@ private:
|
|||
const LMatrix4d &get_new_net_frame_inv(int model_index, int n);
|
||||
LMatrix4d get_new_frame(int model_index, int n);
|
||||
|
||||
bool _has_rest_frame;
|
||||
bool _forced_rest_frames_equal;
|
||||
LMatrix4d _rest_frame;
|
||||
|
||||
// These are used to cache the above results for optimizing
|
||||
// do_compute_reparent().
|
||||
LMatrix4d _new_net_frame, _new_net_frame_inv;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,28 @@ get_num_frames() const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggMatrixTablePointer::extend_to
|
||||
// Access: Public, Virtual
|
||||
// Description: Extends the table to the indicated number of frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggMatrixTablePointer::
|
||||
extend_to(int num_frames) {
|
||||
nassertv(_xform != (EggXfmSAnim *)NULL);
|
||||
_xform->normalize();
|
||||
int num_rows = _xform->get_num_rows();
|
||||
LMatrix4d last_mat;
|
||||
if (num_rows == 0) {
|
||||
last_mat = LMatrix4d::ident_mat();
|
||||
} else {
|
||||
_xform->get_value(num_rows - 1, last_mat);
|
||||
}
|
||||
|
||||
while (num_rows < num_frames) {
|
||||
_xform->add_data(last_mat);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggMatrixTablePointer::get_frame
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ class EggMatrixTablePointer : public EggJointPointer {
|
|||
public:
|
||||
EggMatrixTablePointer(EggObject *object);
|
||||
|
||||
virtual int get_num_frames() const;
|
||||
virtual int get_num_frames() const;
|
||||
virtual void extend_to(int num_frames);
|
||||
virtual LMatrix4d get_frame(int n) const;
|
||||
virtual void set_frame(int n, const LMatrix4d &mat);
|
||||
virtual bool add_frame(const LMatrix4d &mat);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,27 @@ get_num_frames() const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggScalarTablePointer::extend_to
|
||||
// Access: Public, Virtual
|
||||
// Description: Extends the table to the indicated number of frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggScalarTablePointer::
|
||||
extend_to(int num_frames) {
|
||||
nassertv(_data != (EggSAnimData *)NULL);
|
||||
int num_rows = _data->get_num_rows();
|
||||
double last_value;
|
||||
if (num_rows == 0) {
|
||||
last_value = 0.0;
|
||||
} else {
|
||||
last_value = _data->get_value(num_rows - 1);
|
||||
}
|
||||
|
||||
while (num_rows < num_frames) {
|
||||
_data->add_data(last_value);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggScalarTablePointer::get_frame
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
EggScalarTablePointer(EggObject *object);
|
||||
|
||||
virtual int get_num_frames() const;
|
||||
virtual void extend_to(int num_frames);
|
||||
virtual double get_frame(int n) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -40,25 +40,6 @@ EggSliderData(EggCharacterCollection *collection,
|
|||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggSliderData::get_num_frames
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the number of frames of animation for this
|
||||
// particular slider in the indicated model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggSliderData::
|
||||
get_num_frames(int model_index) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EggSliderPointer *slider;
|
||||
DCAST_INTO_R(slider, back, 0);
|
||||
|
||||
return slider->get_num_frames();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggSliderData::get_frame
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef EGGSLIDERDATA_H
|
||||
#define EGGSLIDERDATA_H
|
||||
|
||||
#include <pandatoolbase.h>
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "eggComponentData.h"
|
||||
|
||||
|
|
@ -37,7 +37,6 @@ public:
|
|||
EggSliderData(EggCharacterCollection *collection,
|
||||
EggCharacterData *char_data);
|
||||
|
||||
virtual int get_num_frames(int model_index) const;
|
||||
double get_frame(int model_index, int n) const;
|
||||
|
||||
virtual void add_back_pointer(int model_index, EggObject *egg_object);
|
||||
|
|
|
|||
Loading…
Reference in New Issue