mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
reduce memory usage for egg-optchar
This commit is contained in:
parent
fa2e6e4992
commit
9b67ed9caf
@ -13,8 +13,11 @@
|
||||
#define SOURCES \
|
||||
config_eggcharbase.h eggBackPointer.h \
|
||||
eggCharacterCollection.h eggCharacterCollection.I \
|
||||
eggCharacterData.h eggCharacterData.I eggCharacterFilter.h \
|
||||
eggComponentData.h eggComponentData.I eggJointData.h \
|
||||
eggCharacterData.h eggCharacterData.I \
|
||||
eggCharacterDb.I eggCharacterDb.h \
|
||||
eggCharacterFilter.h \
|
||||
eggComponentData.h eggComponentData.I \
|
||||
eggJointData.h \
|
||||
eggJointData.I eggJointPointer.h eggJointPointer.I \
|
||||
eggJointNodePointer.h \
|
||||
eggMatrixTablePointer.h eggScalarTablePointer.h \
|
||||
@ -24,6 +27,7 @@
|
||||
#define INCLUDED_SOURCES \
|
||||
config_eggcharbase.cxx eggBackPointer.cxx \
|
||||
eggCharacterCollection.cxx eggCharacterData.cxx \
|
||||
eggCharacterDb.cxx \
|
||||
eggCharacterFilter.cxx eggComponentData.cxx eggJointData.cxx \
|
||||
eggJointPointer.cxx eggJointNodePointer.cxx \
|
||||
eggMatrixTablePointer.cxx eggScalarTablePointer.cxx \
|
||||
@ -34,7 +38,9 @@
|
||||
#define INSTALL_HEADERS \
|
||||
eggBackPointer.h \
|
||||
eggCharacterCollection.I eggCharacterCollection.h \
|
||||
eggCharacterData.I eggCharacterData.h eggCharacterFilter.h \
|
||||
eggCharacterData.I eggCharacterData.h \
|
||||
eggCharacterDb.I eggCharacterDb.h \
|
||||
eggCharacterFilter.h \
|
||||
eggComponentData.I eggComponentData.h \
|
||||
eggJointData.h eggJointData.I \
|
||||
eggJointPointer.h eggJointPointer.I \
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "eggCharacterData.h"
|
||||
#include "eggCharacterCollection.h"
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggJointData.h"
|
||||
#include "eggSliderData.h"
|
||||
#include "indent.h"
|
||||
@ -227,8 +228,13 @@ do_reparent() {
|
||||
// frame.
|
||||
Models::const_iterator mi;
|
||||
for (mi = _models.begin(); mi != _models.end(); ++mi) {
|
||||
EggCharacterDb db;
|
||||
int model_index = (*mi)._model_index;
|
||||
int num_frames = get_num_frames(model_index);
|
||||
nout << " computing " << (mi - _models.begin()) + 1
|
||||
<< " of " << _models.size()
|
||||
<< ": " << (*mi)._egg_data->get_egg_filename()
|
||||
<< " (" << num_frames << " frames)\n";
|
||||
for (int f = 0; f < num_frames; f++) {
|
||||
// First, walk through all the joints and flush the computed net
|
||||
// transforms from before.
|
||||
@ -242,20 +248,26 @@ do_reparent() {
|
||||
// caching net transforms as necessary.
|
||||
for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
|
||||
EggJointData *joint_data = (*ji);
|
||||
if (!joint_data->do_compute_reparent(model_index, f)) {
|
||||
if (!joint_data->do_compute_reparent(model_index, f, db)) {
|
||||
// Oops, we got an invalid transform.
|
||||
invalid_set.insert(joint_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, apply the computations to the joints.
|
||||
for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
|
||||
EggJointData *joint_data = (*ji);
|
||||
if (!joint_data->do_joint_rebuild(model_index, db)) {
|
||||
invalid_set.insert(joint_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove all of the old children and add in the new children.
|
||||
for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
|
||||
EggJointData *joint_data = (*ji);
|
||||
if (!joint_data->do_finish_reparent()) {
|
||||
invalid_set.insert(joint_data);
|
||||
}
|
||||
joint_data->do_finish_reparent();
|
||||
}
|
||||
|
||||
// Report the set of joints that failed. It really shouldn't be
|
||||
@ -299,19 +311,21 @@ do_reparent() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggCharacterData::
|
||||
choose_optimal_hierarchy() {
|
||||
EggCharacterDb db;
|
||||
|
||||
Joints::const_iterator ji, jj;
|
||||
for (ji = _joints.begin(); ji != _joints.end(); ++ji) {
|
||||
EggJointData *joint_data = (*ji);
|
||||
|
||||
EggJointData *best_parent = joint_data->get_parent();
|
||||
int best_score = joint_data->score_reparent_to(best_parent);
|
||||
int best_score = joint_data->score_reparent_to(best_parent, db);
|
||||
|
||||
for (jj = _joints.begin(); jj != _joints.end(); ++jj) {
|
||||
EggJointData *possible_parent = (*jj);
|
||||
if (possible_parent != joint_data && possible_parent != best_parent &&
|
||||
!joint_data->is_new_ancestor(possible_parent)) {
|
||||
|
||||
int score = joint_data->score_reparent_to(possible_parent);
|
||||
int score = joint_data->score_reparent_to(possible_parent, db);
|
||||
if (score >= 0 && (best_score < 0 || score < best_score)) {
|
||||
best_parent = possible_parent;
|
||||
best_score = score;
|
||||
@ -322,7 +336,7 @@ choose_optimal_hierarchy() {
|
||||
// Also consider reparenting the node to the root.
|
||||
EggJointData *possible_parent = get_root_joint();
|
||||
if (possible_parent != best_parent) {
|
||||
int score = joint_data->score_reparent_to(possible_parent);
|
||||
int score = joint_data->score_reparent_to(possible_parent, db);
|
||||
if (score >= 0 && (best_score < 0 || score < best_score)) {
|
||||
best_parent = possible_parent;
|
||||
best_score = score;
|
||||
@ -377,6 +391,36 @@ make_slider(const string &name) {
|
||||
return slider;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterData::estimate_db_size
|
||||
// Access: Public
|
||||
// Description: Returns the estimated amount of memory, in megabytes,
|
||||
// that will be required to perform the do_reparent()
|
||||
// operation. This is used mainly be EggCharacterDb to
|
||||
// decide up front whether to store this data in-RAM or
|
||||
// on-disk.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t EggCharacterData::
|
||||
estimate_db_size() const {
|
||||
// Count how much memory we will need to store the interim
|
||||
// transforms. This is models * joints * frames * 3 *
|
||||
// sizeof(LMatrix4d).
|
||||
size_t mj_frames = 0;
|
||||
Models::const_iterator mi;
|
||||
for (mi = _models.begin(); mi != _models.end(); ++mi) {
|
||||
int model_index = (*mi)._model_index;
|
||||
size_t num_frames = (size_t)get_num_frames(model_index);
|
||||
mj_frames += num_frames * _joints.size();
|
||||
}
|
||||
|
||||
// We do this operation a bit carefully, to guard against integer
|
||||
// overflow.
|
||||
size_t mb_needed = ((mj_frames * 3 / 1024) * sizeof(LMatrix4d)) / 1024;
|
||||
|
||||
return mb_needed;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterData::write
|
||||
// Access: Public, Virtual
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "eggJointData.h"
|
||||
|
||||
#include "eggNode.h"
|
||||
#include "eggData.h"
|
||||
#include "pointerTo.h"
|
||||
@ -33,6 +32,7 @@
|
||||
|
||||
class EggCharacterCollection;
|
||||
class EggSliderData;
|
||||
class EggCharacterDb;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggCharacterData
|
||||
@ -81,6 +81,7 @@ public:
|
||||
INLINE EggJointData *make_new_joint(const string &name, EggJointData *parent);
|
||||
INLINE int get_num_joints() const;
|
||||
INLINE EggJointData *get_joint(int n) const;
|
||||
|
||||
bool do_reparent();
|
||||
void choose_optimal_hierarchy();
|
||||
|
||||
@ -92,6 +93,8 @@ public:
|
||||
INLINE int get_num_components() const;
|
||||
INLINE EggComponentData *get_component(int n) const;
|
||||
|
||||
size_t estimate_db_size() const;
|
||||
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
private:
|
||||
|
47
pandatool/src/eggcharbase/eggCharacterDb.I
Normal file
47
pandatool/src/eggcharbase/eggCharacterDb.I
Normal file
@ -0,0 +1,47 @@
|
||||
// Filename: eggCharacterDb.I
|
||||
// Created by: drose (05Oct06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterDb::Key::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EggCharacterDb::Key::
|
||||
Key(const EggJointPointer *joint, TableType table_type, int frame) :
|
||||
_joint(joint),
|
||||
_table_type(table_type),
|
||||
_frame(frame)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterDb::Key::operator <
|
||||
// Access: Public
|
||||
// Description: Provides an arbitrary unique ordering for all keys.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool EggCharacterDb::Key::
|
||||
operator < (const EggCharacterDb::Key &other) const {
|
||||
if (_joint != other._joint) {
|
||||
return _joint < other._joint;
|
||||
}
|
||||
if (_table_type != other._table_type) {
|
||||
return _table_type < other._table_type;
|
||||
}
|
||||
return _frame < other._frame;
|
||||
}
|
143
pandatool/src/eggcharbase/eggCharacterDb.cxx
Normal file
143
pandatool/src/eggcharbase/eggCharacterDb.cxx
Normal file
@ -0,0 +1,143 @@
|
||||
// Filename: eggCharacterDb.cxx
|
||||
// Created by: drose (05Oct06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggCharacterData.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterDb::Constructor
|
||||
// Access: Public
|
||||
// Description: Constructs a database for storing the interim work
|
||||
// for the indicated EggCharacterData. The parameter
|
||||
// max_ram_mb indicates the maximum amount of RAM (in
|
||||
// MB) that the database should consume; if it the
|
||||
// database would roughly fit within this limit, it will
|
||||
// be stored in RAM; otherwise, it will be written to
|
||||
// disk (if Berkeley DB is available).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggCharacterDb::
|
||||
EggCharacterDb() {
|
||||
/*
|
||||
#ifdef HAVE_BDB
|
||||
_db = NULL;
|
||||
|
||||
_db = new Db(NULL, 0);
|
||||
_db_filename = Filename::temporary("", "eggc_", ".db");
|
||||
|
||||
string os_db_filename = _db_filename.to_os_specific();
|
||||
_db->open(NULL, os_db_filename.c_str(), NULL,
|
||||
DB_BTREE, DB_CREATE | DB_EXCL, 0);
|
||||
|
||||
nout << "Using " << os_db_filename << " for rebuild database.\n";
|
||||
#endif // HAVE_BDB
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterDb::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
EggCharacterDb::
|
||||
~EggCharacterDb() {
|
||||
/*
|
||||
#ifdef HAVE_BDB
|
||||
if (_db != (Db *)NULL){
|
||||
_db->close(0);
|
||||
delete _db;
|
||||
_db = NULL;
|
||||
|
||||
string os_db_filename = _db_filename.to_os_specific();
|
||||
Db rmdb(NULL, 0);
|
||||
rmdb.remove(os_db_filename.c_str(), NULL, 0);
|
||||
}
|
||||
#endif // HAVE_BDB
|
||||
*/
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterDb::get_matrix
|
||||
// Access: Public
|
||||
// Description: Looks up the data for the indicated joint, type, and
|
||||
// frame, and fills it in result (and returns true) if
|
||||
// it is found. Returns false if this data has not been
|
||||
// stored in the database.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggCharacterDb::
|
||||
get_matrix(const EggJointPointer *joint, TableType type,
|
||||
int frame, LMatrix4d &mat) const {
|
||||
Key key(joint, type, frame);
|
||||
|
||||
/*
|
||||
#ifdef HAVE_BDB
|
||||
if (_db != (Db *)NULL){
|
||||
Dbt db_key(&key, sizeof(Key));
|
||||
Dbt db_data(&mat, sizeof(LMatrix4d));
|
||||
db_data.set_ulen(sizeof(LMatrix4d));
|
||||
db_data.set_flags(DB_DBT_USERMEM);
|
||||
|
||||
int result = _db->get(NULL, &db_key, &db_data, 0);
|
||||
if (result == DB_NOTFOUND) {
|
||||
return false;
|
||||
}
|
||||
nassertr(result == 0, false);
|
||||
return true;
|
||||
}
|
||||
#endif // HAVE_BDB
|
||||
*/
|
||||
|
||||
Table::const_iterator ti;
|
||||
ti = _table.find(key);
|
||||
if (ti == _table.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mat = (*ti).second;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggCharacterDb::set_matrix
|
||||
// Access: Public
|
||||
// Description: Stores the matrix for the indicated joint, type, and
|
||||
// frame in the database. It is an error to call this
|
||||
// more than once for any given key combination (not for
|
||||
// any technical reason, but because we don't expect
|
||||
// this to happen).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggCharacterDb::
|
||||
set_matrix(const EggJointPointer *joint, TableType type,
|
||||
int frame, const LMatrix4d &mat) {
|
||||
Key key(joint, type, frame);
|
||||
|
||||
/*
|
||||
#ifdef HAVE_BDB
|
||||
if (_db != (Db *)NULL){
|
||||
Dbt db_key(&key, sizeof(Key));
|
||||
Dbt db_data((void *)&mat, sizeof(LMatrix4d));
|
||||
int result = _db->put(NULL, &db_key, &db_data, DB_NOOVERWRITE);
|
||||
nassertv(result != DB_KEYEXIST);
|
||||
nassertv(result == 0);
|
||||
return;
|
||||
}
|
||||
#endif // HAVE_BDB
|
||||
*/
|
||||
|
||||
bool inserted = _table.insert(Table::value_type(key, mat)).second;
|
||||
nassertv(inserted);
|
||||
}
|
93
pandatool/src/eggcharbase/eggCharacterDb.h
Normal file
93
pandatool/src/eggcharbase/eggCharacterDb.h
Normal file
@ -0,0 +1,93 @@
|
||||
// Filename: eggCharacterDb.h
|
||||
// Created by: drose (05Oct06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef EGGCHARACTERDB_H
|
||||
#define EGGCHARACTERDB_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "pmap.h"
|
||||
|
||||
/*
|
||||
#ifdef HAVE_BDB
|
||||
|
||||
// Apparently, we have to define this to make db_cxx files include the
|
||||
// modern header files.
|
||||
#define HAVE_CXX_STDHEADERS 1
|
||||
#include <db_cxx.h>
|
||||
|
||||
#endif // HAVE_BDB
|
||||
*/
|
||||
|
||||
class EggJointPointer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggCharacterDb
|
||||
// Description : This class is used during joint optimization or
|
||||
// restructuring to store the table of interim joint
|
||||
// computations.
|
||||
//
|
||||
// That is to say, this class provides an temporary data
|
||||
// store for three tables of matrices per each
|
||||
// EggJointPointer per frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EggCharacterDb {
|
||||
public:
|
||||
EggCharacterDb();
|
||||
~EggCharacterDb();
|
||||
|
||||
enum TableType {
|
||||
TT_rebuild_frame,
|
||||
TT_net_frame,
|
||||
TT_net_frame_inv,
|
||||
};
|
||||
|
||||
bool get_matrix(const EggJointPointer *joint, TableType type,
|
||||
int frame, LMatrix4d &mat) const;
|
||||
void set_matrix(const EggJointPointer *joint, TableType type,
|
||||
int frame, const LMatrix4d &mat);
|
||||
|
||||
private:
|
||||
class Key {
|
||||
public:
|
||||
INLINE Key(const EggJointPointer *joint,
|
||||
TableType table_type,
|
||||
int frame);
|
||||
INLINE bool operator < (const Key &other) const;
|
||||
|
||||
private:
|
||||
const EggJointPointer *_joint;
|
||||
TableType _table_type;
|
||||
int _frame;
|
||||
};
|
||||
|
||||
/*
|
||||
#ifdef HAVE_BDB
|
||||
Db *_db;
|
||||
Filename _db_filename;
|
||||
#endif // HAVE_BDB
|
||||
*/
|
||||
|
||||
typedef pmap<Key, LMatrix4d> Table;
|
||||
Table _table;
|
||||
};
|
||||
|
||||
#include "eggCharacterDb.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -74,7 +74,7 @@ get_frame(int model_index, int n) const {
|
||||
// in the indicated model.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LMatrix4d EggJointData::
|
||||
get_net_frame(int model_index, int n) const {
|
||||
get_net_frame(int model_index, int n, EggCharacterDb &db) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
return LMatrix4d::ident_mat();
|
||||
@ -82,23 +82,18 @@ get_net_frame(int model_index, int n) const {
|
||||
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, LMatrix4d::ident_mat());
|
||||
|
||||
if (joint->get_num_net_frames() < n) {
|
||||
// Recursively get the previous frame's net, so we have a place to
|
||||
// stuff this frame's value.
|
||||
get_net_frame(model_index, n - 1);
|
||||
}
|
||||
|
||||
if (joint->get_num_net_frames() == n) {
|
||||
|
||||
LMatrix4d mat;
|
||||
if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame, n, mat)) {
|
||||
// Compute this frame's net, and stuff it in.
|
||||
LMatrix4d mat = get_frame(model_index, n);
|
||||
mat = get_frame(model_index, n);
|
||||
if (_parent != (EggJointData *)NULL) {
|
||||
mat = mat * _parent->get_net_frame(model_index, n);
|
||||
mat = mat * _parent->get_net_frame(model_index, n, db);
|
||||
}
|
||||
joint->add_net_frame(mat);
|
||||
db.set_matrix(joint, EggCharacterDb::TT_net_frame, n, mat);
|
||||
}
|
||||
|
||||
return joint->get_net_frame(n);
|
||||
return mat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -107,7 +102,7 @@ get_net_frame(int model_index, int n) const {
|
||||
// Description: Returns the inverse of get_net_frame().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LMatrix4d EggJointData::
|
||||
get_net_frame_inv(int model_index, int n) const {
|
||||
get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const {
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
return LMatrix4d::ident_mat();
|
||||
@ -116,20 +111,15 @@ get_net_frame_inv(int model_index, int n) const {
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, LMatrix4d::ident_mat());
|
||||
|
||||
if (joint->get_num_net_frame_invs() < n) {
|
||||
// Recursively get the previous frame's net, so we have a place to
|
||||
// stuff this frame's value.
|
||||
get_net_frame_inv(model_index, n - 1);
|
||||
}
|
||||
|
||||
if (joint->get_num_net_frame_invs() == n) {
|
||||
LMatrix4d mat;
|
||||
if (!db.get_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat)) {
|
||||
// Compute this frame's net inverse, and stuff it in.
|
||||
LMatrix4d mat = get_net_frame(model_index, n);
|
||||
LMatrix4d mat = get_net_frame(model_index, n, db);
|
||||
mat.invert_in_place();
|
||||
joint->add_net_frame_inv(mat);
|
||||
db.set_matrix(joint, EggCharacterDb::TT_net_frame_inv, n, mat);
|
||||
}
|
||||
|
||||
return joint->get_net_frame_inv(n);
|
||||
return mat;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -202,7 +192,7 @@ move_vertices_to(EggJointData *new_owner) {
|
||||
// error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int EggJointData::
|
||||
score_reparent_to(EggJointData *new_parent) {
|
||||
score_reparent_to(EggJointData *new_parent, EggCharacterDb &db) {
|
||||
if (!FFTCompressor::is_compression_available()) {
|
||||
// If we don't have compression compiled in, we can't meaningfully
|
||||
// score the joints.
|
||||
@ -232,17 +222,17 @@ score_reparent_to(EggJointData *new_parent) {
|
||||
|
||||
} else if (_parent == (EggJointData *)NULL) {
|
||||
// We are moving from outside the joint hierarchy to within it.
|
||||
transform = new_parent->get_net_frame_inv(model_index, n);
|
||||
transform = new_parent->get_net_frame_inv(model_index, n, db);
|
||||
|
||||
} else if (new_parent == (EggJointData *)NULL) {
|
||||
// We are moving from within the hierarchy to outside it.
|
||||
transform = _parent->get_net_frame(model_index, n);
|
||||
transform = _parent->get_net_frame(model_index, n, db);
|
||||
|
||||
} else {
|
||||
// We are changing parents within the hierarchy.
|
||||
transform =
|
||||
_parent->get_net_frame(model_index, n) *
|
||||
new_parent->get_net_frame_inv(model_index, n);
|
||||
_parent->get_net_frame(model_index, n, db) *
|
||||
new_parent->get_net_frame_inv(model_index, n, db);
|
||||
}
|
||||
|
||||
transform = joint->get_frame(n) * transform;
|
||||
@ -304,14 +294,14 @@ score_reparent_to(EggJointData *new_parent) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::do_rebuild
|
||||
// Function: EggJointData::do_rebuild_all
|
||||
// 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() {
|
||||
do_rebuild_all(EggCharacterDb &db) {
|
||||
bool all_ok = true;
|
||||
|
||||
BackPointers::iterator bpi;
|
||||
@ -320,7 +310,7 @@ do_rebuild() {
|
||||
if (back != (EggBackPointer *)NULL) {
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, false);
|
||||
if (!joint->do_rebuild()) {
|
||||
if (!joint->do_rebuild(db)) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
@ -329,7 +319,7 @@ do_rebuild() {
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
EggJointData *child = (*ci);
|
||||
if (!child->do_rebuild()) {
|
||||
if (!child->do_rebuild_all(db)) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
@ -497,15 +487,6 @@ void EggJointData::
|
||||
do_begin_reparent() {
|
||||
_got_new_parent_depth = false;
|
||||
_children.clear();
|
||||
|
||||
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));
|
||||
joint->begin_rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -568,7 +549,7 @@ do_begin_compute_reparent() {
|
||||
// false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointData::
|
||||
do_compute_reparent(int model_index, int n) {
|
||||
do_compute_reparent(int model_index, int n, EggCharacterDb &db) {
|
||||
if (_computed_reparent) {
|
||||
// We've already done this joint. This is possible because we
|
||||
// have to recursively compute joints upwards, so we might visit
|
||||
@ -597,52 +578,73 @@ do_compute_reparent(int model_index, int n) {
|
||||
LMatrix4d transform;
|
||||
if (_parent == (EggJointData *)NULL) {
|
||||
// We are moving from outside the joint hierarchy to within it.
|
||||
transform = _new_parent->get_new_net_frame_inv(model_index, n);
|
||||
transform = _new_parent->get_new_net_frame_inv(model_index, n, db);
|
||||
|
||||
} else if (_new_parent == (EggJointData *)NULL) {
|
||||
// We are moving from within the hierarchy to outside it.
|
||||
transform = _parent->get_net_frame(model_index, n);
|
||||
transform = _parent->get_net_frame(model_index, n, db);
|
||||
|
||||
} else {
|
||||
// We are changing parents within the hierarchy.
|
||||
transform =
|
||||
_parent->get_net_frame(model_index, n) *
|
||||
_new_parent->get_new_net_frame_inv(model_index, n);
|
||||
_parent->get_net_frame(model_index, n, db) *
|
||||
_new_parent->get_new_net_frame_inv(model_index, n, db);
|
||||
}
|
||||
|
||||
nassertr(n == joint->get_num_rebuild_frames(), false);
|
||||
db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame, n,
|
||||
joint->get_frame(n) * transform);
|
||||
_computed_ok = true;
|
||||
|
||||
_computed_ok = joint->add_rebuild_frame(joint->get_frame(n) * transform);
|
||||
return _computed_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::do_joint_rebuild
|
||||
// Access: Protected
|
||||
// Description: Calls do_rebuild() on the joint for the indicated
|
||||
// model index. Returns true on success, false on
|
||||
// failure (false shouldn't be possible).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointData::
|
||||
do_joint_rebuild(int model_index, EggCharacterDb &db) {
|
||||
bool all_ok = true;
|
||||
|
||||
EggJointPointer *parent_joint = NULL;
|
||||
if (_new_parent != NULL && _new_parent->has_model(model_index)) {
|
||||
DCAST_INTO_R(parent_joint, _new_parent->get_model(model_index), false);
|
||||
}
|
||||
|
||||
if (has_model(model_index)) {
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, get_model(model_index), false);
|
||||
if (!joint->do_rebuild(db)) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointData::do_finish_reparent
|
||||
// Access: Protected
|
||||
// Description: Performs the actual reparenting operation
|
||||
// by removing all of the old children and replacing
|
||||
// them with the set of new children. Returns true on
|
||||
// success, false on failure.
|
||||
// them with the set of new children.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointData::
|
||||
void EggJointData::
|
||||
do_finish_reparent() {
|
||||
bool all_ok = true;
|
||||
|
||||
int num_models = get_num_models();
|
||||
for (int model_index = 0; model_index < num_models; model_index++) {
|
||||
EggJointPointer *parent_joint = NULL;
|
||||
if (_new_parent != NULL && _new_parent->has_model(model_index)) {
|
||||
DCAST_INTO_R(parent_joint, _new_parent->get_model(model_index), false);
|
||||
DCAST_INTO_V(parent_joint, _new_parent->get_model(model_index));
|
||||
}
|
||||
|
||||
if (has_model(model_index)) {
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, get_model(model_index), false);
|
||||
DCAST_INTO_V(joint, get_model(model_index));
|
||||
joint->do_finish_reparent(parent_joint);
|
||||
joint->clear_net_frames();
|
||||
if (!joint->do_rebuild()) {
|
||||
all_ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -650,8 +652,6 @@ do_finish_reparent() {
|
||||
if (_parent != (EggJointData *)NULL) {
|
||||
_parent->_children.push_back(this);
|
||||
}
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -760,11 +760,11 @@ is_new_ancestor(EggJointData *child) const {
|
||||
// useful only when called within do_compute_reparent().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LMatrix4d &EggJointData::
|
||||
get_new_net_frame(int model_index, int n) {
|
||||
get_new_net_frame(int model_index, int n, EggCharacterDb &db) {
|
||||
if (!_got_new_net_frame) {
|
||||
_new_net_frame = get_new_frame(model_index, n);
|
||||
_new_net_frame = get_new_frame(model_index, n, db);
|
||||
if (_new_parent != (EggJointData *)NULL) {
|
||||
_new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n);
|
||||
_new_net_frame = _new_net_frame * _new_parent->get_new_net_frame(model_index, n, db);
|
||||
}
|
||||
_got_new_net_frame = true;
|
||||
}
|
||||
@ -777,11 +777,11 @@ get_new_net_frame(int model_index, int n) {
|
||||
// Description: Returns the inverse of get_new_net_frame().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LMatrix4d &EggJointData::
|
||||
get_new_net_frame_inv(int model_index, int n) {
|
||||
get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db) {
|
||||
if (!_got_new_net_frame_inv) {
|
||||
_new_net_frame_inv.invert_from(get_new_frame(model_index, n));
|
||||
_new_net_frame_inv.invert_from(get_new_frame(model_index, n, db));
|
||||
if (_new_parent != (EggJointData *)NULL) {
|
||||
_new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n) * _new_net_frame_inv;
|
||||
_new_net_frame_inv = _new_parent->get_new_net_frame_inv(model_index, n, db) * _new_net_frame_inv;
|
||||
}
|
||||
_got_new_net_frame_inv = true;
|
||||
}
|
||||
@ -797,8 +797,8 @@ get_new_net_frame_inv(int model_index, int n) {
|
||||
// called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LMatrix4d EggJointData::
|
||||
get_new_frame(int model_index, int n) {
|
||||
do_compute_reparent(model_index, n);
|
||||
get_new_frame(int model_index, int n, EggCharacterDb &db) {
|
||||
do_compute_reparent(model_index, n, db);
|
||||
|
||||
EggBackPointer *back = get_model(model_index);
|
||||
if (back == (EggBackPointer *)NULL) {
|
||||
@ -808,9 +808,12 @@ get_new_frame(int model_index, int n) {
|
||||
EggJointPointer *joint;
|
||||
DCAST_INTO_R(joint, back, LMatrix4d::ident_mat());
|
||||
|
||||
if (joint->get_num_rebuild_frames() > 0) {
|
||||
return joint->get_rebuild_frame(n);
|
||||
} else {
|
||||
LMatrix4d mat;
|
||||
if (!db.get_matrix(joint, EggCharacterDb::TT_rebuild_frame, n, mat)) {
|
||||
// No rebuild frame; return the regular frame.
|
||||
return joint->get_frame(n);
|
||||
}
|
||||
|
||||
// Return the rebuild frame, as computed.
|
||||
return mat;
|
||||
}
|
||||
|
@ -20,12 +20,13 @@
|
||||
#define EGGJOINTDATA_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "eggComponentData.h"
|
||||
#include "eggGroup.h"
|
||||
#include "luse.h"
|
||||
#include "pset.h"
|
||||
|
||||
class EggCharacterDb;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggJointData
|
||||
// Description : This is one node of a hierarchy of EggJointData
|
||||
@ -45,8 +46,8 @@ public:
|
||||
INLINE EggJointData *find_joint(const string &name);
|
||||
|
||||
LMatrix4d get_frame(int model_index, int n) const;
|
||||
LMatrix4d get_net_frame(int model_index, int n) const;
|
||||
LMatrix4d get_net_frame_inv(int model_index, int n) const;
|
||||
LMatrix4d get_net_frame(int model_index, int n, EggCharacterDb &db) const;
|
||||
LMatrix4d get_net_frame_inv(int model_index, int n, EggCharacterDb &db) const;
|
||||
|
||||
INLINE bool has_rest_frame() const;
|
||||
INLINE bool rest_frames_differ() const;
|
||||
@ -55,9 +56,9 @@ public:
|
||||
|
||||
INLINE void reparent_to(EggJointData *new_parent);
|
||||
void move_vertices_to(EggJointData *new_owner);
|
||||
int score_reparent_to(EggJointData *new_parent);
|
||||
int score_reparent_to(EggJointData *new_parent, EggCharacterDb &db);
|
||||
|
||||
bool do_rebuild();
|
||||
bool do_rebuild_all(EggCharacterDb &db);
|
||||
void optimize();
|
||||
void expose(EggGroup::DCSType dcs_type = EggGroup::DC_default);
|
||||
void zero_channels(const string &components);
|
||||
@ -70,8 +71,9 @@ protected:
|
||||
void do_begin_reparent();
|
||||
bool calc_new_parent_depth(pset<EggJointData *> &chain);
|
||||
void do_begin_compute_reparent();
|
||||
bool do_compute_reparent(int model_index, int n);
|
||||
bool do_finish_reparent();
|
||||
bool do_compute_reparent(int model_index, int n, EggCharacterDb &db);
|
||||
bool do_joint_rebuild(int model_index, EggCharacterDb &db);
|
||||
void do_finish_reparent();
|
||||
|
||||
private:
|
||||
EggJointData *make_new_joint(const string &name);
|
||||
@ -79,9 +81,9 @@ private:
|
||||
EggJointData *find_joint_matches(const string &name);
|
||||
|
||||
bool is_new_ancestor(EggJointData *child) const;
|
||||
const LMatrix4d &get_new_net_frame(int model_index, int n);
|
||||
const LMatrix4d &get_new_net_frame_inv(int model_index, int n);
|
||||
LMatrix4d get_new_frame(int model_index, int n);
|
||||
const LMatrix4d &get_new_net_frame(int model_index, int n, EggCharacterDb &db);
|
||||
const LMatrix4d &get_new_net_frame_inv(int model_index, int n, EggCharacterDb &db);
|
||||
LMatrix4d get_new_frame(int model_index, int n, EggCharacterDb &db);
|
||||
|
||||
bool _has_rest_frame;
|
||||
bool _rest_frames_differ;
|
||||
|
@ -140,23 +140,6 @@ move_vertices_to(EggJointPointer *new_joint) {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
@ -171,17 +154,18 @@ add_rebuild_frame(const LMatrix4d &mat) {
|
||||
// acceptable, or false if there is some problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointNodePointer::
|
||||
do_rebuild() {
|
||||
if (_rebuild_frames.empty()) {
|
||||
do_rebuild(EggCharacterDb &db) {
|
||||
LMatrix4d mat;
|
||||
if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) {
|
||||
// No rebuild frame; this is OK.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_rebuild_frames.size() != 1) {
|
||||
return false;
|
||||
}
|
||||
_joint->set_transform3d(mat);
|
||||
|
||||
_joint->set_transform3d(_rebuild_frames[0]);
|
||||
_rebuild_frames.clear();
|
||||
// We shouldn't have a frame 1.
|
||||
nassertr(!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 1, mat), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,7 @@ public:
|
||||
virtual void do_finish_reparent(EggJointPointer *new_parent);
|
||||
virtual void move_vertices_to(EggJointPointer *new_joint);
|
||||
|
||||
virtual bool add_rebuild_frame(const LMatrix4d &mat);
|
||||
virtual bool do_rebuild();
|
||||
virtual bool do_rebuild(EggCharacterDb &db);
|
||||
virtual void expose(EggGroup::DCSType dcs_type);
|
||||
|
||||
virtual bool has_vertices() const;
|
||||
|
@ -16,116 +16,3 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::get_num_rebuild_frames
|
||||
// Access: Public
|
||||
// Description: Returns the number of rebuild frames that have been
|
||||
// added so far.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int EggJointPointer::
|
||||
get_num_rebuild_frames() const {
|
||||
return _rebuild_frames.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::get_rebuild_frame
|
||||
// Access: Public
|
||||
// Description: Returns the nth matrix that has been added to the set
|
||||
// of rebuild frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LMatrix4d &EggJointPointer::
|
||||
get_rebuild_frame(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_rebuild_frames.size(), LMatrix4d::ident_mat());
|
||||
return _rebuild_frames[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::clear_net_frames
|
||||
// Access: Public
|
||||
// Description: Resets the cache of net frames for this joint.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggJointPointer::
|
||||
clear_net_frames() {
|
||||
_net_frames.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::add_net_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Adds a new frame to the set of net frames. This is
|
||||
// used to cache the net transform from the root for
|
||||
// this particular joint.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggJointPointer::
|
||||
add_net_frame(const LMatrix4d &mat) {
|
||||
_net_frames.push_back(mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::get_num_net_frames
|
||||
// Access: Public
|
||||
// Description: Returns the number of net frames that have been
|
||||
// added so far.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int EggJointPointer::
|
||||
get_num_net_frames() const {
|
||||
return _net_frames.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::get_net_frame
|
||||
// Access: Public
|
||||
// Description: Returns the nth matrix that has been added to the set
|
||||
// of net frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LMatrix4d &EggJointPointer::
|
||||
get_net_frame(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_net_frames.size(), LMatrix4d::ident_mat());
|
||||
return _net_frames[n];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::clear_net_frame_invs
|
||||
// Access: Public
|
||||
// Description: Resets the cache of net_inv frames for this joint.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggJointPointer::
|
||||
clear_net_frame_invs() {
|
||||
_net_frame_invs.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::add_net_frame_inv
|
||||
// Access: Public, Virtual
|
||||
// Description: Adds a new frame to the set of net_inv frames. This is
|
||||
// used to cache the inverse net transform from the root
|
||||
// for this particular joint.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EggJointPointer::
|
||||
add_net_frame_inv(const LMatrix4d &mat) {
|
||||
_net_frame_invs.push_back(mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::get_num_net_frame_invs
|
||||
// Access: Public
|
||||
// Description: Returns the number of net_inv frames that have been
|
||||
// added so far.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int EggJointPointer::
|
||||
get_num_net_frame_invs() const {
|
||||
return _net_frame_invs.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EggJointPointer::get_net_frame_inv
|
||||
// Access: Public
|
||||
// Description: Returns the nth matrix that has been added to the set
|
||||
// of net_inv frames.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const LMatrix4d &EggJointPointer::
|
||||
get_net_frame_inv(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_net_frame_invs.size(), LMatrix4d::ident_mat());
|
||||
return _net_frame_invs[n];
|
||||
}
|
||||
|
@ -44,35 +44,6 @@ void EggJointPointer::
|
||||
move_vertices_to(EggJointPointer *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
@ -87,12 +58,8 @@ add_rebuild_frame(const LMatrix4d &mat) {
|
||||
// acceptable, or false if there is some problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggJointPointer::
|
||||
do_rebuild() {
|
||||
if (_rebuild_frames.empty()) {
|
||||
return true;
|
||||
}
|
||||
_rebuild_frames.clear();
|
||||
return false;
|
||||
do_rebuild(EggCharacterDb &db) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -20,11 +20,12 @@
|
||||
#define EGGJOINTPOINTER_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "eggBackPointer.h"
|
||||
#include "eggGroup.h"
|
||||
#include "luse.h"
|
||||
|
||||
class EggCharacterDb;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggJointPointer
|
||||
// Description : This is a base class for EggJointNodePointer and
|
||||
@ -44,21 +45,7 @@ public:
|
||||
virtual void do_finish_reparent(EggJointPointer *new_parent)=0;
|
||||
virtual void move_vertices_to(EggJointPointer *new_joint);
|
||||
|
||||
void begin_rebuild();
|
||||
virtual bool add_rebuild_frame(const LMatrix4d &mat);
|
||||
INLINE int get_num_rebuild_frames() const;
|
||||
INLINE const LMatrix4d &get_rebuild_frame(int n) const;
|
||||
virtual bool do_rebuild();
|
||||
|
||||
INLINE void clear_net_frames();
|
||||
INLINE void add_net_frame(const LMatrix4d &mat);
|
||||
INLINE int get_num_net_frames() const;
|
||||
INLINE const LMatrix4d &get_net_frame(int n) const;
|
||||
|
||||
INLINE void clear_net_frame_invs();
|
||||
INLINE void add_net_frame_inv(const LMatrix4d &mat);
|
||||
INLINE int get_num_net_frame_invs() const;
|
||||
INLINE const LMatrix4d &get_net_frame_inv(int n) const;
|
||||
virtual bool do_rebuild(EggCharacterDb &db);
|
||||
|
||||
virtual void optimize();
|
||||
virtual void expose(EggGroup::DCSType dcs_type);
|
||||
@ -67,12 +54,6 @@ public:
|
||||
|
||||
virtual EggJointPointer *make_new_joint(const string &name)=0;
|
||||
|
||||
protected:
|
||||
typedef pvector<LMatrix4d> RebuildFrames;
|
||||
RebuildFrames _rebuild_frames;
|
||||
RebuildFrames _net_frames;
|
||||
RebuildFrames _net_frame_invs;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
@ -189,8 +189,10 @@ do_finish_reparent(EggJointPointer *new_parent) {
|
||||
// acceptable, or false if there is some problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool EggMatrixTablePointer::
|
||||
do_rebuild() {
|
||||
if (_rebuild_frames.empty()) {
|
||||
do_rebuild(EggCharacterDb &db) {
|
||||
LMatrix4d mat;
|
||||
if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) {
|
||||
// No rebuild frame; this is OK.
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -201,14 +203,19 @@ do_rebuild() {
|
||||
bool all_ok = true;
|
||||
|
||||
_xform->clear_data();
|
||||
RebuildFrames::const_iterator fi;
|
||||
for (fi = _rebuild_frames.begin(); fi != _rebuild_frames.end(); ++fi) {
|
||||
if (!_xform->add_data(*fi)) {
|
||||
all_ok = false;
|
||||
}
|
||||
if (!_xform->add_data(mat)) {
|
||||
all_ok = false;
|
||||
}
|
||||
|
||||
// Assume all frames will be contiguous.
|
||||
int n = 1;
|
||||
while (db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, n, mat)) {
|
||||
if (!_xform->add_data(mat)) {
|
||||
all_ok = false;
|
||||
}
|
||||
++n;
|
||||
}
|
||||
|
||||
_rebuild_frames.clear();
|
||||
return all_ok;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
|
||||
virtual void do_finish_reparent(EggJointPointer *new_parent);
|
||||
|
||||
virtual bool do_rebuild();
|
||||
virtual bool do_rebuild(EggCharacterDb &db);
|
||||
|
||||
virtual void optimize();
|
||||
virtual void zero_channels(const string &components);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "eggBackPointer.cxx"
|
||||
#include "eggCharacterCollection.cxx"
|
||||
#include "eggCharacterData.cxx"
|
||||
#include "eggCharacterDb.cxx"
|
||||
#include "eggCharacterFilter.cxx"
|
||||
#include "eggComponentData.cxx"
|
||||
#include "eggJointData.cxx"
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "eggJointData.h"
|
||||
#include "eggCharacterCollection.h"
|
||||
#include "eggCharacterData.h"
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggJointPointer.h"
|
||||
#include "eggTable.h"
|
||||
#include "compose_matrix.h"
|
||||
@ -127,9 +128,10 @@ run() {
|
||||
keep_names.insert(*si);
|
||||
}
|
||||
|
||||
EggCharacterDb db;
|
||||
EggJointData *root_joint = char_data->get_root_joint();
|
||||
retarget_anim(char_data, root_joint, reference_model, keep_names);
|
||||
root_joint->do_rebuild();
|
||||
retarget_anim(char_data, root_joint, reference_model, keep_names, db);
|
||||
root_joint->do_rebuild_all(db);
|
||||
|
||||
write_eggs();
|
||||
}
|
||||
@ -143,7 +145,8 @@ run() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggRetargetAnim::
|
||||
retarget_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
int reference_model, const pset<string> &keep_names) {
|
||||
int reference_model, const pset<string> &keep_names,
|
||||
EggCharacterDb &db) {
|
||||
if (keep_names.find(joint_data->get_name()) != keep_names.end()) {
|
||||
// Don't retarget this joint; keep the translation and scale and whatever.
|
||||
|
||||
@ -176,11 +179,9 @@ retarget_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
nout << "Could not decompose matrix for " << joint_data->get_name()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if (!joint->add_rebuild_frame(mat)) {
|
||||
nout << "Unable to combine animations.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame,
|
||||
f, mat);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -190,7 +191,7 @@ retarget_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
int num_children = joint_data->get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
EggJointData *next_joint_data = joint_data->get_child(i);
|
||||
retarget_anim(char_data, next_joint_data, reference_model, keep_names);
|
||||
retarget_anim(char_data, next_joint_data, reference_model, keep_names, db);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
class EggCharacterData;
|
||||
class EggJointData;
|
||||
class EggCharacterDb;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EggRetargetAnim
|
||||
@ -43,7 +44,8 @@ public:
|
||||
void run();
|
||||
|
||||
void retarget_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
int reference_model, const pset<string> &keep_names);
|
||||
int reference_model, const pset<string> &keep_names,
|
||||
EggCharacterDb &db);
|
||||
|
||||
Filename _reference_filename;
|
||||
vector_string _keep_joints;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "eggJointData.h"
|
||||
#include "eggCharacterCollection.h"
|
||||
#include "eggCharacterData.h"
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggJointPointer.h"
|
||||
#include "eggTable.h"
|
||||
#include "compose_matrix.h"
|
||||
@ -125,6 +126,8 @@ run() {
|
||||
}
|
||||
|
||||
// Now process each character.
|
||||
EggCharacterDb db;
|
||||
|
||||
int ci;
|
||||
for (ci = 0; ci < num_characters; ci++) {
|
||||
EggCharacterData *char_data = _collection->get_character(ci);
|
||||
@ -163,7 +166,7 @@ run() {
|
||||
int num_children = root_joint->get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
EggJointData *joint_data = root_joint->get_child(i);
|
||||
strip_anim(char_data, joint_data, from_model, from_char, top_joint);
|
||||
strip_anim(char_data, joint_data, from_model, from_char, top_joint, db);
|
||||
}
|
||||
|
||||
// We also need to transform the vertices for any models involved
|
||||
@ -173,7 +176,7 @@ run() {
|
||||
EggNode *node = char_data->get_model_root(m);
|
||||
if (!node->is_of_type(EggTable::get_class_type())) {
|
||||
strip_anim_vertices(node, char_data->get_model_index(m),
|
||||
from_model, top_joint);
|
||||
from_model, top_joint, db);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,7 +184,7 @@ run() {
|
||||
// Now, trigger the actual rebuilding of all the joint data.
|
||||
for (ci = 0; ci < num_characters; ci++) {
|
||||
EggCharacterData *char_data = _collection->get_character(ci);
|
||||
char_data->get_root_joint()->do_rebuild();
|
||||
char_data->get_root_joint()->do_rebuild_all(db);
|
||||
}
|
||||
|
||||
write_eggs();
|
||||
@ -235,11 +238,10 @@ check_transform_channels() {
|
||||
void EggTopstrip::
|
||||
strip_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
int from_model, EggCharacterData *from_char,
|
||||
EggJointData *top_joint) {
|
||||
EggJointData *top_joint, EggCharacterDb &db) {
|
||||
int num_models = joint_data->get_num_models();
|
||||
for (int i = 0; i < num_models; i++) {
|
||||
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()
|
||||
@ -258,23 +260,16 @@ strip_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
DCAST_INTO_V(joint, back);
|
||||
|
||||
// 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);
|
||||
LMatrix4d from = top_joint->get_net_frame(model, f % num_from_frames, db);
|
||||
|
||||
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);
|
||||
}
|
||||
db.set_matrix(joint, EggCharacterDb::TT_rebuild_frame,
|
||||
f, into * from);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,7 +283,7 @@ strip_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EggTopstrip::
|
||||
strip_anim_vertices(EggNode *egg_node, int into_model, int from_model,
|
||||
EggJointData *top_joint) {
|
||||
EggJointData *top_joint, EggCharacterDb &db) {
|
||||
int model = (from_model < 0) ? into_model : from_model;
|
||||
if (!top_joint->has_model(model)) {
|
||||
nout << "Warning: Joint " << top_joint->get_name()
|
||||
@ -296,7 +291,7 @@ strip_anim_vertices(EggNode *egg_node, int into_model, int from_model,
|
||||
return;
|
||||
}
|
||||
|
||||
LMatrix4d from = top_joint->get_net_frame(model, 0);
|
||||
LMatrix4d from = top_joint->get_net_frame(model, 0, db);
|
||||
adjust_transform(from);
|
||||
|
||||
egg_node->transform_vertices_only(from);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "pvector.h"
|
||||
|
||||
class EggCharacterData;
|
||||
class EggCharacterDb;
|
||||
class EggJointData;
|
||||
class EggJointPointer;
|
||||
|
||||
@ -47,9 +48,10 @@ public:
|
||||
|
||||
void strip_anim(EggCharacterData *char_data, EggJointData *joint_data,
|
||||
int from_model, EggCharacterData *from_char,
|
||||
EggJointData *top_joint);
|
||||
EggJointData *top_joint, EggCharacterDb &db);
|
||||
void strip_anim_vertices(EggNode *egg_node, int into_model,
|
||||
int from_model, EggJointData *top_joint);
|
||||
int from_model, EggJointData *top_joint,
|
||||
EggCharacterDb &db);
|
||||
|
||||
void adjust_transform(LMatrix4d &mat) const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user