mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-17 09:51:10 -04:00
*** empty log message ***
This commit is contained in:
parent
d212027cf1
commit
07709159f0
@ -448,7 +448,7 @@ _decompose_matrix(const LMatrix3<NumType> &mat,
|
||||
|
||||
default:
|
||||
linmath_cat.error()
|
||||
<< "Unexpected coordinate system!\n";
|
||||
<< "Unexpected coordinate system: " << (int)cs << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -546,7 +546,7 @@ _decompose_matrix(const LMatrix3<NumType> &mat,
|
||||
|
||||
default:
|
||||
linmath_cat.error()
|
||||
<< "Unexpected coordinate system!\n";
|
||||
<< "Unexpected coordinate system: " << (int)cs << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,8 @@ EggMultiBase() {
|
||||
"Force complete loading: load up the egg file along with all of its "
|
||||
"external references.",
|
||||
&EggMultiBase::dispatch_none, &_force_complete);
|
||||
|
||||
_coordinate_system = CS_yup_right;
|
||||
}
|
||||
|
||||
|
||||
@ -118,6 +120,13 @@ read_egg(const Filename &filename) {
|
||||
return (EggData *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (_got_coordinate_system) {
|
||||
data->set_coordinate_system(_coordinate_system);
|
||||
} else {
|
||||
_coordinate_system = data->get_coordinate_system();
|
||||
_got_coordinate_system = true;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ get_output_filename(const Filename &source_filename) const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggMultiFilter::write_eggs
|
||||
// Access: Protected
|
||||
// Access: Protected, Virtual
|
||||
// Description: Writes out all of the egg files in the _eggs vector,
|
||||
// to the output directory if one is specified, or over
|
||||
// the input files if -inplace was specified.
|
||||
|
@ -25,7 +25,7 @@ protected:
|
||||
virtual bool post_command_line();
|
||||
|
||||
Filename get_output_filename(const Filename &source_filename) const;
|
||||
void write_eggs();
|
||||
virtual void write_eggs();
|
||||
|
||||
protected:
|
||||
bool _allow_empty;
|
||||
|
@ -86,3 +86,16 @@ get_character(int i) const {
|
||||
nassertr(i >= 0 && i < (int)_characters.size(), (EggCharacterData *)NULL);
|
||||
return _characters[i];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterCollection::get_character_by_model_index
|
||||
// Access: Public
|
||||
// Description: Returns the character associated with the indicated
|
||||
// model index.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EggCharacterData *EggCharacterCollection::
|
||||
get_character_by_model_index(int model_index) const {
|
||||
nassertr(model_index >= 0 && model_index < (int)_characters_by_model_index.size(),
|
||||
(EggCharacterData *)NULL);
|
||||
return _characters_by_model_index[model_index];
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ add_egg(EggData *egg) {
|
||||
egg_info._models.push_back(model_root);
|
||||
|
||||
char_data->add_model(model_index, model_root);
|
||||
nassertr(model_index == (int)_characters_by_model_index.size(), -1);
|
||||
_characters_by_model_index.push_back(char_data);
|
||||
|
||||
match_egg_nodes(char_data, root_joint, egg_nodes,
|
||||
egg_index, model_index);
|
||||
@ -443,6 +445,7 @@ match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
EggNode *egg_node = (*ei);
|
||||
EggJointData *data = make_joint_data(char_data);
|
||||
joint_data->_children.push_back(data);
|
||||
data->_parent = joint_data;
|
||||
found_egg_match(char_data, data, egg_node, egg_index, model_index);
|
||||
}
|
||||
|
||||
@ -547,6 +550,7 @@ match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
EggNode *egg_node = (*ei);
|
||||
EggJointData *data = make_joint_data(char_data);
|
||||
joint_data->_children.push_back(data);
|
||||
data->_parent = joint_data;
|
||||
found_egg_match(char_data, data, egg_node, egg_index, model_index);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
INLINE EggCharacterData *get_character(int i) const;
|
||||
EggCharacterData *get_character_by_name(const string &character_name) const;
|
||||
|
||||
INLINE EggCharacterData *get_character_by_model_index(int model_index) const;
|
||||
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
virtual EggCharacterData *make_character_data();
|
||||
@ -61,6 +63,7 @@ public:
|
||||
|
||||
typedef vector<EggCharacterData *> Characters;
|
||||
Characters _characters;
|
||||
Characters _characters_by_model_index;
|
||||
|
||||
private:
|
||||
bool scan_hierarchy(EggNode *egg_node);
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "eggCharacterFilter.h"
|
||||
#include "eggCharacterCollection.h"
|
||||
#include "eggCharacterData.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -59,6 +60,26 @@ post_command_line() {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterFilter::write_eggs
|
||||
// Access: Protected, Virtual
|
||||
// Description: Writes out all of the egg files in the _eggs vector,
|
||||
// to the output directory if one is specified, or over
|
||||
// the input files if -inplace was specified.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggCharacterFilter::
|
||||
write_eggs() {
|
||||
// Optimize (that is, collapse redudant nodes) in all of the
|
||||
// characters' joint tables before writing them out.
|
||||
int num_characters = _collection->get_num_characters();
|
||||
for (int i = 0; i < num_characters; i++) {
|
||||
EggCharacterData *char_data = _collection->get_character(i);
|
||||
char_data->get_root_joint()->optimize();
|
||||
}
|
||||
|
||||
EggMultiFilter::write_eggs();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterFilter::make_collection
|
||||
// Access: Protected, Virtual
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
|
||||
protected:
|
||||
virtual bool post_command_line();
|
||||
virtual void write_eggs();
|
||||
|
||||
virtual EggCharacterCollection *make_collection();
|
||||
|
||||
|
@ -22,6 +22,7 @@ EggJointData(EggCharacterCollection *collection,
|
||||
EggCharacterData *char_data) :
|
||||
EggComponentData(collection, char_data)
|
||||
{
|
||||
_parent = (EggJointData *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -30,7 +31,7 @@ EggJointData(EggCharacterCollection *collection,
|
||||
// Description: Returns the first descendent joint found with the
|
||||
// indicated name, or NULL if no joint has that name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EggJointData *EggJointData::
|
||||
EggJointData *EggJointData::
|
||||
find_joint(const string &name) {
|
||||
Children::const_iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
@ -47,6 +48,120 @@ find_joint(const string &name) {
|
||||
return (EggJointData *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::get_num_frames
|
||||
// Access: Public
|
||||
// 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
|
||||
// Description: Returns the local transform matrix corresponding to
|
||||
// this joint position in the nth frame in the indicated
|
||||
// model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LMatrix4d EggJointData::
|
||||
get_frame(int model_index, int n) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
return LMatrix4d::ident_mat();
|
||||
}
|
||||
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, LMatrix4d::ident_mat());
|
||||
|
||||
return joint->get_frame(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::get_net_frame
|
||||
// Access: Public
|
||||
// Description: Returns the complete transform from the root
|
||||
// corresponding to this joint position in the nth frame
|
||||
// in the indicated model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LMatrix4d EggJointData::
|
||||
get_net_frame(int model_index, int n) const {
|
||||
LMatrix4d mat = get_frame(model_index, n);
|
||||
if (_parent != (EggJointData *)NULL) {
|
||||
mat = mat * _parent->get_net_frame(model_index, n);
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::do_rebuild
|
||||
// Access: Public
|
||||
// Description: Calls do_rebuild() on all models, and recursively on
|
||||
// all joints at this node and below. Returns true if
|
||||
// all models returned true, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointData::
|
||||
do_rebuild() {
|
||||
bool all_ok = true;
|
||||
|
||||
BackPointers::iterator bpi;
|
||||
for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
|
||||
EggBackPointer *back = (*bpi);
|
||||
if (back != (EggBackPointer *)NULL) {
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, false);
|
||||
if (!joint->do_rebuild()) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
EggJointData *child = (*ci);
|
||||
if (!child->do_rebuild()) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::optimize
|
||||
// Access: Public
|
||||
// Description: Calls optimize() on all models, and recursively on
|
||||
// all joints at this node and below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggJointData::
|
||||
optimize() {
|
||||
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->optimize();
|
||||
}
|
||||
}
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
EggJointData *child = (*ci);
|
||||
child->optimize();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::add_back_pointer
|
||||
// Access: Public, Virtual
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "eggComponentData.h"
|
||||
|
||||
#include <luse.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggJointData
|
||||
// Description : This is one node of a hierarchy of EggJointData
|
||||
@ -27,12 +29,20 @@ public:
|
||||
INLINE EggJointData *get_child(int n) const;
|
||||
EggJointData *find_joint(const string &name);
|
||||
|
||||
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;
|
||||
|
||||
bool do_rebuild();
|
||||
void optimize();
|
||||
|
||||
virtual void add_back_pointer(int model_index, EggObject *egg_object);
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
protected:
|
||||
typedef vector<EggJointData *> Children;
|
||||
Children _children;
|
||||
EggJointData *_parent;
|
||||
|
||||
friend class EggCharacterCollection;
|
||||
};
|
||||
|
@ -79,3 +79,48 @@ set_frame(int n, const LMatrix4d &mat) {
|
||||
nassertv(n == 0);
|
||||
_joint->set_transform(mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointNodePointer::add_rebuild_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Adds a new frame to the set of rebuild frames. See
|
||||
// begin_rebuild() and do_rebuild(). Returns true if
|
||||
// this is valid, false otherwise (e.g. adding multiple
|
||||
// frames to a static joint).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointNodePointer::
|
||||
add_rebuild_frame(const LMatrix4d &mat) {
|
||||
if (!_rebuild_frames.empty()) {
|
||||
// Only one frame may be added to a <Joint>.
|
||||
return false;
|
||||
}
|
||||
return EggJointPointer::add_rebuild_frame(mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointNodePointer::do_rebuild
|
||||
// Access: Public, Virtual
|
||||
// Description: Rebuilds the entire table all at once, based on the
|
||||
// frames added by repeated calls to add_rebuild_frame()
|
||||
// since the last call to begin_rebuild().
|
||||
//
|
||||
// Until do_rebuild() is called, the animation table is
|
||||
// not changed.
|
||||
//
|
||||
// The return value is true if all frames are
|
||||
// acceptable, or false if there is some problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointNodePointer::
|
||||
do_rebuild() {
|
||||
if (_rebuild_frames.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_rebuild_frames.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_joint->set_transform(_rebuild_frames[0]);
|
||||
_rebuild_frames.clear();
|
||||
return true;
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ public:
|
||||
virtual LMatrix4d get_frame(int n) const;
|
||||
virtual void set_frame(int n, const LMatrix4d &mat);
|
||||
|
||||
virtual bool add_rebuild_frame(const LMatrix4d &mat);
|
||||
virtual bool do_rebuild();
|
||||
|
||||
private:
|
||||
PT(EggGroup) _joint;
|
||||
|
||||
|
@ -20,3 +20,65 @@ bool EggJointPointer::
|
||||
add_frame(const LMatrix4d &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::begin_rebuild
|
||||
// Access: Public
|
||||
// Description: Resets the set of rebuild frames in preparation for
|
||||
// rebuilding the complete table of frames. Repeated
|
||||
// calls to add_rebuild_frame() will build up the frames
|
||||
// without changing the values returned by get_frame();
|
||||
// the table will eventually be updated when do_rebuild
|
||||
// is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggJointPointer::
|
||||
begin_rebuild() {
|
||||
_rebuild_frames.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::add_rebuild_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Adds a new frame to the set of rebuild frames. See
|
||||
// begin_rebuild() and do_rebuild(). Returns true if
|
||||
// this is valid, false otherwise (e.g. adding multiple
|
||||
// frames to a static joint).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointPointer::
|
||||
add_rebuild_frame(const LMatrix4d &mat) {
|
||||
_rebuild_frames.push_back(mat);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::do_rebuild
|
||||
// Access: Public, Virtual
|
||||
// Description: Rebuilds the entire table all at once, based on the
|
||||
// frames added by repeated calls to add_rebuild_frame()
|
||||
// since the last call to begin_rebuild().
|
||||
//
|
||||
// Until do_rebuild() is called, the animation table is
|
||||
// not changed.
|
||||
//
|
||||
// The return value is true if all frames are
|
||||
// acceptable, or false if there is some problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointPointer::
|
||||
do_rebuild() {
|
||||
if (_rebuild_frames.empty()) {
|
||||
return true;
|
||||
}
|
||||
_rebuild_frames.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::optimize
|
||||
// Access: Public, Virtual
|
||||
// Description: Resets the table before writing to disk so that
|
||||
// redundant rows (e.g. i { 1 1 1 1 1 1 1 1 }) are
|
||||
// collapsed out.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggJointPointer::
|
||||
optimize() {
|
||||
}
|
||||
|
@ -28,6 +28,16 @@ public:
|
||||
virtual void set_frame(int n, const LMatrix4d &mat)=0;
|
||||
virtual bool add_frame(const LMatrix4d &mat);
|
||||
|
||||
void begin_rebuild();
|
||||
virtual bool add_rebuild_frame(const LMatrix4d &mat);
|
||||
virtual bool do_rebuild();
|
||||
|
||||
virtual void optimize();
|
||||
|
||||
protected:
|
||||
typedef vector<LMatrix4d> RebuildFrames;
|
||||
RebuildFrames _rebuild_frames;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -29,6 +29,7 @@ EggMatrixTablePointer(EggObject *object) {
|
||||
if (child->get_name() == "xform") {
|
||||
if (child->is_of_type(EggXfmSAnim::get_class_type())) {
|
||||
_xform = DCAST(EggXfmSAnim, child);
|
||||
_xform->normalize();
|
||||
found = true;
|
||||
|
||||
} else if (child->is_of_type(EggXfmAnimData::get_class_type())) {
|
||||
@ -67,6 +68,12 @@ get_num_frames() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LMatrix4d EggMatrixTablePointer::
|
||||
get_frame(int n) const {
|
||||
if (get_num_frames() == 1) {
|
||||
// If we have exactly one frame, then we have as many frames as we
|
||||
// want; just repeat the first frame.
|
||||
n = 0;
|
||||
}
|
||||
|
||||
nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat());
|
||||
LMatrix4d mat;
|
||||
_xform->get_value(n, mat);
|
||||
@ -82,7 +89,7 @@ get_frame(int n) const {
|
||||
void EggMatrixTablePointer::
|
||||
set_frame(int n, const LMatrix4d &mat) {
|
||||
nassertv(n >= 0 && n < get_num_frames());
|
||||
// Do something here.
|
||||
_xform->set_value(n, mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -94,6 +101,58 @@ set_frame(int n, const LMatrix4d &mat) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggMatrixTablePointer::
|
||||
add_frame(const LMatrix4d &mat) {
|
||||
// Do something here.
|
||||
if (_xform == (EggXfmSAnim *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _xform->add_data(mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggMatrixTablePointer::do_rebuild
|
||||
// Access: Public, Virtual
|
||||
// Description: Rebuilds the entire table all at once, based on the
|
||||
// frames added by repeated calls to add_rebuild_frame()
|
||||
// since the last call to begin_rebuild().
|
||||
//
|
||||
// Until do_rebuild() is called, the animation table is
|
||||
// not changed.
|
||||
//
|
||||
// The return value is true if all frames are
|
||||
// acceptable, or false if there is some problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggMatrixTablePointer::
|
||||
do_rebuild() {
|
||||
if (_rebuild_frames.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_xform == (EggXfmSAnim *)NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_xform->clear_data();
|
||||
RebuildFrames::const_iterator fi;
|
||||
for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) {
|
||||
if (!_xform->add_data(*fi)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_rebuild_frames.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggMatrixTablePointer::optimize
|
||||
// Access: Public, Virtual
|
||||
// Description: Resets the table before writing to disk so that
|
||||
// redundant rows (e.g. i { 1 1 1 1 1 1 1 1 }) are
|
||||
// collapsed out.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggMatrixTablePointer::
|
||||
optimize() {
|
||||
if (_xform != (EggXfmSAnim *)NULL) {
|
||||
_xform->optimize();
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,10 @@ public:
|
||||
virtual void set_frame(int n, const LMatrix4d &mat);
|
||||
virtual bool add_frame(const LMatrix4d &mat);
|
||||
|
||||
virtual bool do_rebuild();
|
||||
|
||||
virtual void optimize();
|
||||
|
||||
private:
|
||||
PT(EggTable) _table;
|
||||
PT(EggXfmSAnim) _xform;
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#begin bin_target
|
||||
#define LOCAL_LIBS eggcharbase $[LOCAL_LIBS]
|
||||
#define TARGET egg-topstrip
|
||||
|
||||
#define SOURCES \
|
||||
eggTopstrip.cxx eggTopstrip.h
|
||||
|
||||
#end test_bin_target
|
||||
#end bin_target
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <eggCharacterData.h>
|
||||
#include <eggJointPointer.h>
|
||||
#include <eggTable.h>
|
||||
#include <compose_matrix.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggTopstrip::Constructor
|
||||
@ -43,7 +44,7 @@ EggTopstrip() {
|
||||
("n", "", 0,
|
||||
"Do not invert the matrix before applying. This causes an "
|
||||
"additive effect.",
|
||||
&EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform);
|
||||
&EggTopstrip::dispatch_false, &_got_invert_transform, &_invert_transform);
|
||||
|
||||
add_option
|
||||
("s", "[ijkphrxyz]", 0,
|
||||
@ -73,13 +74,15 @@ void EggTopstrip::
|
||||
run() {
|
||||
nassertv(_collection != (EggCharacterCollection *)NULL);
|
||||
nassertv(_collection->get_num_eggs() > 0);
|
||||
|
||||
check_transform_channels();
|
||||
|
||||
// Get the number of characters first, in case adding the
|
||||
// _channel_egg changes this.
|
||||
int num_characters = _collection->get_num_characters();
|
||||
|
||||
// Determine which model we'll be pulling the animation channels
|
||||
// from.
|
||||
// Determine which model and character we'll be pulling the
|
||||
// animation channels from.
|
||||
int from_model = -1;
|
||||
|
||||
if (!_channel_filename.empty()) {
|
||||
@ -108,27 +111,38 @@ run() {
|
||||
// Now process each character.
|
||||
for (int i = 0; i < num_characters; i++) {
|
||||
EggCharacterData *char_data = _collection->get_character(i);
|
||||
nout << "Processing " << char_data->get_name() << "\n";
|
||||
|
||||
EggJointData *root_joint = char_data->get_root_joint();
|
||||
|
||||
// We'll read the transform to apply from this character, which
|
||||
// will be the same character unless -r was specified.
|
||||
EggCharacterData *from_char = char_data;
|
||||
if (from_model != -1) {
|
||||
from_char = _collection->get_character_by_model_index(from_model);
|
||||
}
|
||||
|
||||
// Determine which joint we'll use to extract the transform to
|
||||
// apply.
|
||||
EggJointData *top_joint = (EggJointData *)NULL;
|
||||
if (_top_joint_name.empty()) {
|
||||
// The default top joint name is the alphabetically first joint
|
||||
// in the top level.
|
||||
if (root_joint->get_num_children() == 0) {
|
||||
nout << "Character " << char_data->get_name() << " has no joints.\n";
|
||||
nout << "Character " << from_char->get_name() << " has no joints.\n";
|
||||
exit(1);
|
||||
}
|
||||
top_joint = root_joint->get_child(0);
|
||||
} else {
|
||||
top_joint = char_data->find_joint(_top_joint_name);
|
||||
top_joint = from_char->find_joint(_top_joint_name);
|
||||
if (top_joint == (EggJointData *)NULL) {
|
||||
nout << "Character " << char_data->get_name()
|
||||
nout << "Character " << from_char->get_name()
|
||||
<< " has no joint named " << _top_joint_name << "\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// First, transform all the joints.
|
||||
int num_children = root_joint->get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
EggJointData *joint_data = root_joint->get_child(i);
|
||||
@ -141,14 +155,59 @@ run() {
|
||||
for (int m = 0; m < num_models; m++) {
|
||||
EggNode *node = char_data->get_model_root(m);
|
||||
if (!node->is_of_type(EggTable::get_class_type())) {
|
||||
strip_anim_vertices(node, m, from_model, top_joint);
|
||||
strip_anim_vertices(node, char_data->get_model_index(m),
|
||||
from_model, top_joint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, trigger the actual rebuilding of all the joint data.
|
||||
for (int i = 0; i < num_characters; i++) {
|
||||
EggCharacterData *char_data = _collection->get_character(i);
|
||||
char_data->get_root_joint()->do_rebuild();
|
||||
}
|
||||
|
||||
write_eggs();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggTopstrip::check_transform_channels
|
||||
// Access: Public
|
||||
// Description: Checks the _transform_channels string to ensure that
|
||||
// it contains only the expected nine letters, or a
|
||||
// subset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggTopstrip::
|
||||
check_transform_channels() {
|
||||
static string expected = "ijkphrxyz";
|
||||
static const int num_channels = 9;
|
||||
bool has_each[num_channels];
|
||||
memset(has_each, 0, num_channels * sizeof(bool));
|
||||
|
||||
for (size_t p = 0; p < _transform_channels.size(); p++) {
|
||||
int i = expected.find(_transform_channels[p]);
|
||||
if (i == (int)string::npos) {
|
||||
nout << "Invalid letter for -s: " << _transform_channels[p] << "\n";
|
||||
exit(1);
|
||||
}
|
||||
nassertv(i < num_channels);
|
||||
has_each[i] = true;
|
||||
}
|
||||
|
||||
_transform_channels = "";
|
||||
for (int i = 0; i < num_channels; i++) {
|
||||
if (has_each[i]) {
|
||||
_transform_channels += expected[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (_transform_channels.empty()) {
|
||||
nout << "No transform specified for -s.\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggTopstrip::strip_anim
|
||||
// Access: Public
|
||||
@ -160,47 +219,42 @@ void EggTopstrip::
|
||||
strip_anim(EggJointData *joint_data, int from_model, EggJointData *top_joint) {
|
||||
int num_models = joint_data->get_num_models();
|
||||
for (int i = 0; i < num_models; i++) {
|
||||
EggBackPointer *back = joint_data->get_model(i);
|
||||
if (back != (EggBackPointer *)NULL) {
|
||||
int model = (from_model < 0) ? i : from_model;
|
||||
|
||||
if (joint_data->has_model(i)) {
|
||||
if (!top_joint->has_model(model)) {
|
||||
nout << "Warning: Joint " << top_joint->get_name()
|
||||
<< " is not defined in all models.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int num_into_frames = joint_data->get_num_frames(i);
|
||||
int num_from_frames = top_joint->get_num_frames(model);
|
||||
|
||||
int num_frames = max(num_into_frames, num_from_frames);
|
||||
|
||||
EggBackPointer *back = joint_data->get_model(i);
|
||||
nassertv(back != (EggBackPointer *)NULL);
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_V(joint, back);
|
||||
|
||||
cerr << "joint is " << joint->get_type() << "\n";
|
||||
|
||||
int model = (from_model < 0) ? i : from_model;
|
||||
EggBackPointer *from_back = top_joint->get_model(model);
|
||||
if (from_back == (EggBackPointer *)NULL) {
|
||||
nout << "Joint " << top_joint->get_name() << " has no model index "
|
||||
<< model << "\n";
|
||||
exit(1);
|
||||
}
|
||||
EggJointPointer *from_joint;
|
||||
DCAST_INTO_V(from_joint, from_back);
|
||||
|
||||
int num_into_frames = joint->get_num_frames();
|
||||
int num_from_frames = from_joint->get_num_frames();
|
||||
|
||||
int num_frames = max(num_into_frames, num_from_frames);
|
||||
|
||||
for (int f = 0; f < num_frames; f++) {
|
||||
LMatrix4d start = joint->get_frame(f % num_into_frames);
|
||||
LMatrix4d strip = from_joint->get_frame(f % num_from_frames);
|
||||
|
||||
if (_invert_transform) {
|
||||
strip.invert_in_place();
|
||||
}
|
||||
|
||||
cerr << "Applying " << strip << " to " << f << " of "
|
||||
<< joint_data->get_name() << " model " << i << "\n";
|
||||
|
||||
if (f >= num_into_frames) {
|
||||
if (!joint->add_frame(start * strip)) {
|
||||
nout << "Cannot apply multiple frames of animation to a model file.\n"
|
||||
<< "In general, be careful when using -r and model files.\n";
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
joint->set_frame(f, start * strip);
|
||||
|
||||
// Compute and apply the new transforms.
|
||||
joint->begin_rebuild();
|
||||
|
||||
int f;
|
||||
for (f = 0; f < num_frames; f++) {
|
||||
LMatrix4d into = joint_data->get_frame(i, f % num_into_frames);
|
||||
LMatrix4d from = top_joint->get_net_frame(model, f % num_from_frames);
|
||||
|
||||
adjust_transform(from);
|
||||
|
||||
if (!joint->add_rebuild_frame(into * from)) {
|
||||
nout <<
|
||||
"Cannot apply multiple frames of animation to a model file.\n"
|
||||
"In general, -r cannot be used when a model file is being "
|
||||
"adjusted, unless the named source is a one-frame animation "
|
||||
"file, or another model file.\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,23 +271,81 @@ void EggTopstrip::
|
||||
strip_anim_vertices(EggNode *egg_node, int into_model, int from_model,
|
||||
EggJointData *top_joint) {
|
||||
int model = (from_model < 0) ? into_model : from_model;
|
||||
EggBackPointer *from_back = top_joint->get_model(model);
|
||||
if (from_back == (EggBackPointer *)NULL) {
|
||||
nout << "Joint " << top_joint->get_name() << " has no model index "
|
||||
<< model << "\n";
|
||||
exit(1);
|
||||
if (!top_joint->has_model(model)) {
|
||||
nout << "Warning: Joint " << top_joint->get_name()
|
||||
<< " is not defined in all models.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
EggJointPointer *from_joint;
|
||||
DCAST_INTO_V(from_joint, from_back);
|
||||
LMatrix4d from = top_joint->get_net_frame(model, 0);
|
||||
adjust_transform(from);
|
||||
|
||||
LMatrix4d strip = from_joint->get_frame(0);
|
||||
egg_node->transform_vertices_only(from);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggTopstrip::adjust_transform
|
||||
// Access: Public
|
||||
// Description: Adjust the transform extracted from the "top" joint
|
||||
// according to the -s and -i/-n options, prior to
|
||||
// applying it to the skeleton.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggTopstrip::
|
||||
adjust_transform(LMatrix4d &mat) const {
|
||||
if (_transform_channels.length() != 9) {
|
||||
// Decompose and recompose the matrix, so we can eliminate the
|
||||
// parts the user doesn't want.
|
||||
|
||||
LVecBase3d scale, hpr, translate;
|
||||
bool result = decompose_matrix(mat, scale, hpr, translate, _coordinate_system);
|
||||
if (!result) {
|
||||
nout << "Warning: skew transform in animation.\n";
|
||||
} else {
|
||||
LVecBase3d new_scale(1.0, 1.0, 1.0);
|
||||
LVecBase3d new_hpr(0.0, 0.0, 0.0);
|
||||
LVecBase3d new_translate(0.0, 0.0, 0.0);
|
||||
|
||||
for (size_t i = 0; i < _transform_channels.size(); i++) {
|
||||
switch (_transform_channels[i]) {
|
||||
case 'i':
|
||||
new_scale[0] = scale[0];
|
||||
break;
|
||||
case 'j':
|
||||
new_scale[1] = scale[1];
|
||||
break;
|
||||
case 'k':
|
||||
new_scale[2] = scale[2];
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
new_hpr[0] = hpr[0];
|
||||
break;
|
||||
case 'p':
|
||||
new_hpr[1] = hpr[1];
|
||||
break;
|
||||
case 'r':
|
||||
new_hpr[2] = hpr[2];
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
new_translate[0] = translate[0];
|
||||
break;
|
||||
case 'y':
|
||||
new_translate[1] = translate[1];
|
||||
break;
|
||||
case 'z':
|
||||
new_translate[2] = translate[2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
compose_matrix(mat, new_scale, new_hpr, new_translate, _coordinate_system);
|
||||
}
|
||||
}
|
||||
if (_invert_transform) {
|
||||
strip.invert_in_place();
|
||||
mat.invert_in_place();
|
||||
}
|
||||
|
||||
cerr << "Applying " << strip << " to vertices.\n";
|
||||
egg_node->transform_vertices_only(strip);
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,12 +29,15 @@ public:
|
||||
EggTopstrip();
|
||||
|
||||
void run();
|
||||
void check_transform_channels();
|
||||
|
||||
void strip_anim(EggJointData *joint_data, int from_model,
|
||||
EggJointData *top_joint);
|
||||
void strip_anim_vertices(EggNode *egg_node, int into_model,
|
||||
int from_model, EggJointData *top_joint);
|
||||
|
||||
void adjust_transform(LMatrix4d &mat) const;
|
||||
|
||||
|
||||
string _top_joint_name;
|
||||
bool _got_invert_transform;
|
||||
|
Loading…
x
Reference in New Issue
Block a user