*** empty log message ***

This commit is contained in:
David Rose 2001-02-27 20:44:40 +00:00
parent d212027cf1
commit 07709159f0
20 changed files with 541 additions and 67 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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];
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -31,6 +31,7 @@ public:
protected:
virtual bool post_command_line();
virtual void write_eggs();
virtual EggCharacterCollection *make_collection();

View File

@ -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

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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() {
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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;