*** empty log message ***

This commit is contained in:
David Rose 2001-02-27 04:24:16 +00:00
parent c5a1d30385
commit aa42fdae2f
33 changed files with 800 additions and 58 deletions

View File

@ -653,6 +653,25 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::r_transform_vertices
// Access: Protected, Virtual
// Description: This is called from within the egg code by
// transform_vertices_only()(). It applies a
// transformation matrix to the current node in some
// sensible way (if the current node is a vertex pool
// with vertices), then continues down the tree.
////////////////////////////////////////////////////////////////////
void EggGroupNode::
r_transform_vertices(const LMatrix4d &mat) {
Children::iterator ci;
for (ci = _children.begin();
ci != _children.end();
++ci) {
(*ci)->r_transform_vertices(mat);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggGroupNode::r_mark_coordsys
// Access: Protected, Virtual

View File

@ -111,6 +111,7 @@ protected:
virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
CoordinateSystem to_cs);
virtual void r_transform_vertices(const LMatrix4d &mat);
virtual void r_mark_coordsys(CoordinateSystem cs);
virtual void r_flatten_transforms();
virtual void r_apply_texmats(EggTextureCollection &textures);

View File

@ -213,6 +213,19 @@ transform(const LMatrix4d &mat) {
r_transform(mat, inv, CS_default);
}
////////////////////////////////////////////////////////////////////
// Function: EggNode::transform_vertices_only
// Access: Public
// Description: Applies the indicated transformation only to vertices
// that appear in global space within vertex pools at
// this node and below. Joints and other transforms are
// not affected, nor are local vertices.
////////////////////////////////////////////////////////////////////
INLINE void EggNode::
transform_vertices_only(const LMatrix4d &mat) {
r_transform_vertices(mat);
}
////////////////////////////////////////////////////////////////////
// Function: EggNode::flatten_transforms
// Access: Public

View File

@ -232,6 +232,19 @@ void EggNode::
r_transform(const LMatrix4d &, const LMatrix4d &, CoordinateSystem) {
}
////////////////////////////////////////////////////////////////////
// Function: EggNode::r_transform_vertices
// Access: Protected, Virtual
// Description: This is called from within the egg code by
// transform_vertices_only()(). It applies a
// transformation matrix to the current node in some
// sensible way (if the current node is a vertex pool
// with vertices), then continues down the tree.
////////////////////////////////////////////////////////////////////
void EggNode::
r_transform_vertices(const LMatrix4d &) {
}
////////////////////////////////////////////////////////////////////
// Function: EggNode::r_mark_coordsys
// Access: Protected, Virtual

View File

@ -45,6 +45,7 @@ public:
INLINE const LMatrix4d &get_vertex_to_node() const;
INLINE void transform(const LMatrix4d &mat);
INLINE void transform_vertices_only(const LMatrix4d &mat);
INLINE void flatten_transforms();
void apply_texmats();
@ -75,6 +76,7 @@ protected:
virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
CoordinateSystem to_cs);
virtual void r_transform_vertices(const LMatrix4d &mat);
virtual void r_mark_coordsys(CoordinateSystem cs);
virtual void r_flatten_transforms();
virtual void r_apply_texmats(EggTextureCollection &textures);

View File

@ -404,3 +404,17 @@ void EggVertexPool::
r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) {
transform(mat);
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::r_transform_vertices
// Access: Protected, Virtual
// Description: This is called from within the egg code by
// transform_vertices_only()(). It applies a
// transformation matrix to the current node in some
// sensible way (if the current node is a vertex pool
// with vertices), then continues down the tree.
////////////////////////////////////////////////////////////////////
void EggVertexPool::
r_transform_vertices(const LMatrix4d &mat) {
transform(mat);
}

View File

@ -104,6 +104,7 @@ public:
protected:
virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
CoordinateSystem to_cs);
virtual void r_transform_vertices(const LMatrix4d &mat);
private:
UniqueVertices _unique_vertices;

View File

@ -6,6 +6,7 @@
egg:c panda:m
#define SOURCES \
config_eggcharbase.cxx config_eggcharbase.h \
eggBackPointer.cxx eggBackPointer.h \
eggCharacterCollection.cxx eggCharacterCollection.h \
eggCharacterCollection.I \
@ -14,6 +15,7 @@
eggComponentData.cxx eggComponentData.h eggComponentData.I \
eggJointData.cxx eggJointData.h eggJointData.I \
eggJointPointer.cxx eggJointPointer.h \
eggJointNodePointer.cxx eggJointNodePointer.h \
eggMatrixTablePointer.cxx eggMatrixTablePointer.h \
eggSliderData.cxx eggSliderData.h eggSliderData.I \
eggVertexPointer.cxx eggVertexPointer.h
@ -25,6 +27,7 @@
eggComponentData.I eggComponentData.h \
eggJointData.h eggJointData.I \
eggJointPointer.h \
eggJointNodePointer.h \
eggMatrixTablePointer.h \
eggSliderData.I eggSliderData.h \
eggVertexPointer.h

View File

@ -0,0 +1,43 @@
// Filename: config_eggcharbase.cxx
// Created by: drose (26Feb01)
//
////////////////////////////////////////////////////////////////////
#include "config_eggcharbase.h"
#include "eggBackPointer.h"
#include "eggJointNodePointer.h"
#include "eggJointPointer.h"
#include "eggMatrixTablePointer.h"
#include "eggVertexPointer.h"
#include <dconfig.h>
Configure(config_eggcharbase);
NotifyCategoryDef(eggcharbase, "");
ConfigureFn(config_eggcharbase) {
init_libeggcharbase();
}
////////////////////////////////////////////////////////////////////
// Function: init_libeggcharbase
// Description: Initializes the library. This must be called at
// least once before any of the functions or classes in
// this library can be used. Normally it will be
// called by the static initializers and need not be
// called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
void
init_libeggcharbase() {
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
EggBackPointer::init_type();
EggJointNodePointer::init_type();
EggJointPointer::init_type();
EggMatrixTablePointer::init_type();
EggVertexPointer::init_type();
}

View File

@ -0,0 +1,16 @@
// Filename: config_eggcharbase.h
// Created by: drose (26Feb01)
//
////////////////////////////////////////////////////////////////////
#ifndef CONFIG_EGGCHARBASE_H
#define CONFIG_EGGCHARBASE_H
#include <pandabase.h>
#include <notifyCategoryProxy.h>
NotifyCategoryDecl(eggcharbase, EXPCL_MISC, EXPTP_MISC);
extern void init_libeggcharbase();
#endif

View File

@ -26,6 +26,44 @@ get_egg(int i) const {
return _eggs[i]._egg;
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterCollection::get_first_model_index
// Access: Public
// Description: Returns the first model index associated with the
// indicated egg file. An egg file may contain multiple
// models, which will be consecutive integers beginning
// at get_first_model_index() and continuing for
// get_num_models().
//
// Each "model" corresponds to a single character model,
// or one LOD of a multiple-LOD model, or a single
// animation bundle.
////////////////////////////////////////////////////////////////////
INLINE int EggCharacterCollection::
get_first_model_index(int egg_index) const {
nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0);
return _eggs[egg_index]._first_model_index;
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterCollection::get_num_models
// Access: Public
// Description: Returns the number of different models found in the
// indicated egg file. An egg file may contain multiple
// models, which will be consecutive integers beginning
// at get_first_model_index() and continuing for
// get_num_models().
//
// Each "model" corresponds to a single character model,
// or one LOD of a multiple-LOD model, or a single
// animation bundle.
////////////////////////////////////////////////////////////////////
INLINE int EggCharacterCollection::
get_num_models(int egg_index) const {
nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0);
return _eggs[egg_index]._models.size();
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterCollection::get_num_characters
// Access: Public

View File

@ -49,25 +49,28 @@ EggCharacterCollection::
// Access: Public
// Description: Adds a new egg file to the list of models and
// animation files for this particular character.
// Returns true if the file is successfully added, or
// false if there is some problem (for instance, it does
// not contain a character model or animation table).
//
// Returns the new egg_index if the file is successfully
// added, or -1 if there is some problem (for instance,
// it does not contain a character model or animation
// table).
//
// If the joint hierarchy does not match the existing
// joint hierarchy, a best match is attempted.
////////////////////////////////////////////////////////////////////
bool EggCharacterCollection::
int EggCharacterCollection::
add_egg(EggData *egg) {
_top_egg_nodes.clear();
if (!scan_hierarchy(egg)) {
return false;
return -1;
}
int egg_index = _eggs.size();
_eggs.push_back(EggInfo());
EggInfo &egg_info = _eggs.back();
egg_info._egg = egg;
egg_info._first_model_index = 0;
// Now, for each model, add an entry in the egg_info and match the
// joint hierarchy to the known joints.
@ -84,7 +87,13 @@ add_egg(EggData *egg) {
EggNodeList &egg_nodes = (*ti).second;
int model_index = _next_model_index++;
if (egg_info._models.empty()) {
egg_info._first_model_index = model_index;
}
egg_info._models.push_back(model_root);
char_data->add_model(model_index, model_root);
match_egg_nodes(char_data, root_joint, egg_nodes,
egg_index, model_index);
@ -93,7 +102,7 @@ add_egg(EggData *egg) {
}
}
return true;
return egg_index;
}
////////////////////////////////////////////////////////////////////

View File

@ -28,10 +28,12 @@ public:
EggCharacterCollection();
virtual ~EggCharacterCollection();
bool add_egg(EggData *egg);
int add_egg(EggData *egg);
INLINE int get_num_eggs() const;
INLINE EggData *get_egg(int i) const;
INLINE int get_first_model_index(int egg_index) const;
INLINE int get_num_models(int egg_index) const;
INLINE int get_num_characters() const;
INLINE EggCharacterData *get_character(int i) const;
@ -51,6 +53,7 @@ public:
PT(EggData) _egg;
typedef vector<PT(EggNode)> Models;
Models _models;
int _first_model_index;
};
typedef vector<EggInfo> Eggs;

View File

@ -4,6 +4,49 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::get_num_models
// Access: Public
// Description: Returns the total number of models associated with
// this character.
////////////////////////////////////////////////////////////////////
INLINE int EggCharacterData::
get_num_models() const {
return _models.size();
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::get_model_index
// Access: Public
// Description: Returns the model_index of the nth model associated
// with this character. This model_index may be used to
// ask questions about the particular model from the
// EggCharacterCollection object, or from the individual
// EggJointData and EggSliderData objects.
////////////////////////////////////////////////////////////////////
INLINE int EggCharacterData::
get_model_index(int n) const {
nassertr(n >= 0 && n < (int)_models.size(), 0);
return _models[n]._model_index;
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::get_model_root
// Access: Public
// Description: Returns the model_root of the nth model associated
// with this character.
//
// This is the node at which the character, animation
// bundle, or LOD officially began within its particular
// egg file.
////////////////////////////////////////////////////////////////////
INLINE EggNode *EggCharacterData::
get_model_root(int n) const {
nassertr(n >= 0 && n < (int)_models.size(), (EggNode *)NULL);
return _models[n]._model_root;
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::get_root_joint
// Access: Public
@ -18,3 +61,14 @@ INLINE EggJointData *EggCharacterData::
get_root_joint() const {
return _root_joint;
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::find_joint
// Access: Public
// Description: Returns the first joint found with the indicated
// name, or NULL if no joint has that name.
////////////////////////////////////////////////////////////////////
INLINE EggJointData *EggCharacterData::
find_joint(const string &name) const {
return _root_joint->find_joint(name);
}

View File

@ -37,6 +37,21 @@ EggCharacterData::
}
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::add_model
// Access: Public
// Description: Indicates that the given model_index (with the
// indicated model_root) is associated with this
// character.
////////////////////////////////////////////////////////////////////
void EggCharacterData::
add_model(int model_index, EggNode *model_root) {
Model m;
m._model_index = model_index;
m._model_root = model_root;
_models.push_back(m);
}
////////////////////////////////////////////////////////////////////
// Function: EggCharacterData::make_slider
// Access: Public

View File

@ -8,12 +8,15 @@
#include <pandatoolbase.h>
#include "eggJointData.h"
#include <eggNode.h>
#include <pointerTo.h>
#include <namable.h>
#include <map>
class EggCharacterCollection;
class EggJointData;
class EggSliderData;
////////////////////////////////////////////////////////////////////
@ -45,13 +48,27 @@ public:
EggCharacterData(EggCharacterCollection *collection);
virtual ~EggCharacterData();
void add_model(int model_index, EggNode *model_root);
INLINE int get_num_models() const;
INLINE int get_model_index(int n) const;
INLINE EggNode *get_model_root(int n) const;
INLINE EggJointData *get_root_joint() const;
INLINE EggJointData *find_joint(const string &name) const;
EggSliderData *make_slider(const string &name);
virtual void write(ostream &out, int indent_level = 0) const;
protected:
class Model {
public:
int _model_index;
PT(EggNode) _model_root;
};
typedef vector<Model> Models;
Models _models;
EggCharacterCollection *_collection;
EggJointData *_root_joint;

View File

@ -49,15 +49,13 @@ post_command_line() {
for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
EggData *data = (*ei);
if (!_collection->add_egg(data)) {
if (_collection->add_egg(data) < 0) {
nout << data->get_egg_filename().get_basename()
<< " does not contain a character model or animation channel.\n";
return false;
}
}
_collection->write(cerr);
return true;
}

View File

@ -5,29 +5,29 @@
////////////////////////////////////////////////////////////////////
// Function: EggComponentData::get_num_back_pointers
// Function: EggComponentData::get_num_models
// Access: Public
// Description: Returns the maximum number of back pointers this
// component may have. The component may store a back
// pointer for models indexed 0 .. num_back_pointers -
// 1. You must call has_back_pointer() on each model
// pointer for models indexed 0 .. num_models -
// 1. You must call has_model() on each model
// index to confirm whether a particular model in that
// range has a back pointer.
////////////////////////////////////////////////////////////////////
INLINE int EggComponentData::
get_num_back_pointers() const {
get_num_models() const {
return _back_pointers.size();
}
////////////////////////////////////////////////////////////////////
// Function: EggComponentData::has_back_pointer
// Function: EggComponentData::has_model
// Access: Public
// Description: Returns true if the component has a back pointer to
// an egg file somewhere for the indicated model, false
// otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool EggComponentData::
has_back_pointer(int model_index) const {
has_model(int model_index) const {
if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
return _back_pointers[model_index] != (EggBackPointer *)NULL;
}
@ -35,13 +35,13 @@ has_back_pointer(int model_index) const {
}
////////////////////////////////////////////////////////////////////
// Function: EggComponentData::get_back_pointer
// Function: EggComponentData::get_model
// Access: Public
// Description: Returns the back pointer to an egg file for the
// indicated model if it exists, or NULL if it does not.
////////////////////////////////////////////////////////////////////
INLINE EggBackPointer *EggComponentData::
get_back_pointer(int model_index) const {
get_model(int model_index) const {
if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
return _back_pointers[model_index];
}

View File

@ -68,13 +68,13 @@ matches_name(const string &name) const {
}
////////////////////////////////////////////////////////////////////
// Function: EggComponentData::set_back_pointer
// Function: EggComponentData::set_model
// Access: Public
// Description: Sets the back_pointer associated with the given
// model_index.
////////////////////////////////////////////////////////////////////
void EggComponentData::
set_back_pointer(int model_index, EggBackPointer *back) {
set_model(int model_index, EggBackPointer *back) {
while ((int)_back_pointers.size() <= model_index) {
_back_pointers.push_back((EggBackPointer *)NULL);
}

View File

@ -35,10 +35,10 @@ public:
virtual void add_back_pointer(int model_index, EggObject *egg_object)=0;
virtual void write(ostream &out, int indent_level = 0) const=0;
INLINE int get_num_back_pointers() const;
INLINE bool has_back_pointer(int model_index) const;
INLINE EggBackPointer *get_back_pointer(int model_index) const;
void set_back_pointer(int model_index, EggBackPointer *back);
INLINE int get_num_models() const;
INLINE bool has_model(int model_index) const;
INLINE EggBackPointer *get_model(int model_index) const;
void set_model(int model_index, EggBackPointer *back);
protected:

View File

@ -4,7 +4,7 @@
////////////////////////////////////////////////////////////////////
#include "eggJointData.h"
#include "eggJointPointer.h"
#include "eggJointNodePointer.h"
#include "eggMatrixTablePointer.h"
#include <eggGroup.h>
@ -24,6 +24,29 @@ EggJointData(EggCharacterCollection *collection,
{
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::find_joint
// Access: Public
// Description: Returns the first descendent joint found with the
// indicated name, or NULL if no joint has that name.
////////////////////////////////////////////////////////////////////
INLINE EggJointData *EggJointData::
find_joint(const string &name) {
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggJointData *child = (*ci);
if (child->get_name() == name) {
return child;
}
EggJointData *result = child->find_joint(name);
if (result != (EggJointData *)NULL) {
return result;
}
}
return (EggJointData *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::add_back_pointer
// Access: Public, Virtual
@ -34,13 +57,13 @@ void EggJointData::
add_back_pointer(int model_index, EggObject *egg_object) {
if (egg_object->is_of_type(EggGroup::get_class_type())) {
// It must be a <Joint>.
EggJointPointer *joint = new EggJointPointer(egg_object);
set_back_pointer(model_index, joint);
EggJointNodePointer *joint = new EggJointNodePointer(egg_object);
set_model(model_index, joint);
} else if (egg_object->is_of_type(EggTable::get_class_type())) {
// It's a <Table> with an "xform" child beneath it.
EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object);
set_back_pointer(model_index, xform);
set_model(model_index, xform);
} else {
nout << "Invalid object added to joint for back pointer.\n";
@ -57,9 +80,9 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "Joint " << get_name()
<< " (models:";
int num_back_pointers = get_num_back_pointers();
for (int model_index = 0; model_index < num_back_pointers; model_index++) {
if (has_back_pointer(model_index)) {
int num_models = get_num_models();
for (int model_index = 0; model_index < num_models; model_index++) {
if (has_model(model_index)) {
out << " " << model_index;
}
}

View File

@ -25,6 +25,7 @@ public:
INLINE int get_num_children() const;
INLINE EggJointData *get_child(int n) const;
EggJointData *find_joint(const string &name);
virtual void add_back_pointer(int model_index, EggObject *egg_object);
virtual void write(ostream &out, int indent_level = 0) const;

View File

@ -0,0 +1,81 @@
// Filename: eggJointNodePointer.cxx
// Created by: drose (26Feb01)
//
////////////////////////////////////////////////////////////////////
#include "eggJointNodePointer.h"
#include <eggObject.h>
#include <eggGroup.h>
#include <pointerTo.h>
TypeHandle EggJointNodePointer::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: EggJointNodePointer::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
EggJointNodePointer::
EggJointNodePointer(EggObject *object) {
_joint = DCAST(EggGroup, object);
if (_joint != (EggGroup *)NULL) {
// Quietly insist that the joint has a transform, for neatness. If
// it does not, give it the identity transform.
if (!_joint->has_transform()) {
_joint->set_transform(LMatrix4d::ident_mat());
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointNodePointer::get_num_frames
// Access: Public, Virtual
// Description: Returns the number of frames of animation for this
// particular joint.
//
// In the case of a EggJointNodePointer, which just
// stores a pointer to a <Joint> entry for a character
// model (not an animation table), there is always
// exactly one frame: the rest pose.
////////////////////////////////////////////////////////////////////
int EggJointNodePointer::
get_num_frames() const {
return 1;
}
////////////////////////////////////////////////////////////////////
// Function: EggJointNodePointer::get_frame
// Access: Public, Virtual
// Description: Returns the transform matrix corresponding to this
// joint position in the nth frame.
//
// In the case of a EggJointNodePointer, which just
// stores a pointer to a <Joint> entry for a character
// model (not an animation table), there is always
// exactly one frame: the rest pose.
////////////////////////////////////////////////////////////////////
LMatrix4d EggJointNodePointer::
get_frame(int n) const {
nassertr(n == 0, LMatrix4d::ident_mat());
return _joint->get_transform();
}
////////////////////////////////////////////////////////////////////
// Function: EggJointNodePointer::set_frame
// Access: Public, Virtual
// Description: Sets the transform matrix corresponding to this
// joint position in the nth frame.
//
// In the case of a EggJointNodePointer, which just
// stores a pointer to a <Joint> entry for a character
// model (not an animation table), there is always
// exactly one frame: the rest pose.
////////////////////////////////////////////////////////////////////
void EggJointNodePointer::
set_frame(int n, const LMatrix4d &mat) {
nassertv(n == 0);
_joint->set_transform(mat);
}

View File

@ -0,0 +1,51 @@
// Filename: eggJointNodePointer.h
// Created by: drose (26Feb01)
//
////////////////////////////////////////////////////////////////////
#ifndef EGGJOINTNODEPOINTER_H
#define EGGJOINTNODEPOINTER_H
#include <pandatoolbase.h>
#include "eggJointPointer.h"
#include <eggGroup.h>
#include <pointerTo.h>
////////////////////////////////////////////////////////////////////
// Class : EggJointNodePointer
// Description : This stores a pointer back to a <Joint> node.
////////////////////////////////////////////////////////////////////
class EggJointNodePointer : public EggJointPointer {
public:
EggJointNodePointer(EggObject *object);
virtual int get_num_frames() const;
virtual LMatrix4d get_frame(int n) const;
virtual void set_frame(int n, const LMatrix4d &mat);
private:
PT(EggGroup) _joint;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
EggJointPointer::init_type();
register_type(_type_handle, "EggJointNodePointer",
EggJointPointer::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#endif

View File

@ -8,12 +8,15 @@
TypeHandle EggJointPointer::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: EggJointPointer::Constructor
// Access: Public
// Description:
// Function: EggJointPointer::add_frame
// Access: Public, Virtual
// Description: Appends a new frame onto the end of the data, if
// possible; returns true if not possible, or false
// otherwise (e.g. for a static joint).
////////////////////////////////////////////////////////////////////
EggJointPointer::
EggJointPointer(EggObject *object) {
_joint = DCAST(EggGroup, object);
bool EggJointPointer::
add_frame(const LMatrix4d &) {
return false;
}

View File

@ -10,19 +10,23 @@
#include "eggBackPointer.h"
#include <eggGroup.h>
#include <pointerTo.h>
#include <luse.h>
////////////////////////////////////////////////////////////////////
// Class : EggJointPointer
// Description : This stores a pointer back to a <Joint> node.
// Description : This is a base class for EggJointNodePointer and
// EggMatrixTablePointer. It stores a back pointer to
// either a <Joint> entry or an xform <Table> data, and
// thus presents an interface that returns 1-n matrices,
// one for each frame. (<Joint> entries, for model
// files, appear the same as one-frame animations.)
////////////////////////////////////////////////////////////////////
class EggJointPointer : public EggBackPointer {
public:
EggJointPointer(EggObject *object);
private:
PT(EggGroup) _joint;
virtual int get_num_frames() const=0;
virtual LMatrix4d get_frame(int n) const=0;
virtual void set_frame(int n, const LMatrix4d &mat)=0;
virtual bool add_frame(const LMatrix4d &mat);
public:
static TypeHandle get_class_type() {

View File

@ -43,3 +43,57 @@ EggMatrixTablePointer(EggObject *object) {
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMatrixTablePointer::get_num_frames
// Access: Public, Virtual
// Description: Returns the number of frames of animation for this
// particular joint.
////////////////////////////////////////////////////////////////////
int EggMatrixTablePointer::
get_num_frames() const {
if (_xform == (EggXfmSAnim *)NULL) {
return 0;
} else {
return _xform->get_num_rows();
}
}
////////////////////////////////////////////////////////////////////
// Function: EggMatrixTablePointer::get_frame
// Access: Public, Virtual
// Description: Returns the transform matrix corresponding to this
// joint position in the nth frame.
////////////////////////////////////////////////////////////////////
LMatrix4d EggMatrixTablePointer::
get_frame(int n) const {
nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat());
LMatrix4d mat;
_xform->get_value(n, mat);
return mat;
}
////////////////////////////////////////////////////////////////////
// Function: EggMatrixTablePointer::set_frame
// Access: Public, Virtual
// Description: Sets the transform matrix corresponding to this
// joint position in the nth frame.
////////////////////////////////////////////////////////////////////
void EggMatrixTablePointer::
set_frame(int n, const LMatrix4d &mat) {
nassertv(n >= 0 && n < get_num_frames());
// Do something here.
}
////////////////////////////////////////////////////////////////////
// Function: EggMatrixTablePointer::add_frame
// Access: Public, Virtual
// Description: Appends a new frame onto the end of the data, if
// possible; returns true if not possible, or false
// otherwise (e.g. for a static joint).
////////////////////////////////////////////////////////////////////
bool EggMatrixTablePointer::
add_frame(const LMatrix4d &mat) {
// Do something here.
return true;
}

View File

@ -8,7 +8,7 @@
#include <pandatoolbase.h>
#include "eggBackPointer.h"
#include "eggJointPointer.h"
#include <eggTable.h>
#include <eggXfmSAnim.h>
@ -21,10 +21,15 @@
// corresponding to the animation data from a single
// bundle for this joint.
////////////////////////////////////////////////////////////////////
class EggMatrixTablePointer : public EggBackPointer {
class EggMatrixTablePointer : public EggJointPointer {
public:
EggMatrixTablePointer(EggObject *object);
virtual int get_num_frames() const;
virtual LMatrix4d get_frame(int n) const;
virtual void set_frame(int n, const LMatrix4d &mat);
virtual bool add_frame(const LMatrix4d &mat);
private:
PT(EggTable) _table;
PT(EggXfmSAnim) _xform;
@ -34,9 +39,9 @@ public:
return _type_handle;
}
static void init_type() {
EggBackPointer::init_type();
EggJointPointer::init_type();
register_type(_type_handle, "EggMatrixTablePointer",
EggBackPointer::get_class_type());
EggJointPointer::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -33,26 +33,26 @@ void EggSliderData::
add_back_pointer(int model_index, EggObject *egg_object) {
if (egg_object->is_of_type(EggPrimitive::get_class_type())) {
// A primitive!
EggBackPointer *back = get_back_pointer(model_index);
EggBackPointer *back = get_model(model_index);
if (back == (EggBackPointer *)NULL) {
back = new EggVertexPointer;
set_back_pointer(model_index, back);
set_model(model_index, back);
}
} else if (egg_object->is_of_type(EggVertex::get_class_type())) {
// A vertex!
EggBackPointer *back = get_back_pointer(model_index);
EggBackPointer *back = get_model(model_index);
if (back == (EggBackPointer *)NULL) {
back = new EggVertexPointer;
set_back_pointer(model_index, back);
set_model(model_index, back);
}
} else if (egg_object->is_of_type(EggSAnimData::get_class_type())) {
// A slider animation table! Woo hoo!
EggBackPointer *back = get_back_pointer(model_index);
EggBackPointer *back = get_model(model_index);
if (back == (EggBackPointer *)NULL) {
back = new EggVertexPointer;
set_back_pointer(model_index, back);
set_model(model_index, back);
}
} else {
@ -70,9 +70,9 @@ write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< "Slider " << get_name()
<< " (models:";
int num_back_pointers = get_num_back_pointers();
for (int model_index = 0; model_index < num_back_pointers; model_index++) {
if (has_back_pointer(model_index)) {
int num_models = get_num_models();
for (int model_index = 0; model_index < num_models; model_index++) {
if (has_model(model_index)) {
out << " " << model_index;
}
}

View File

@ -5,6 +5,12 @@
#include "eggTopstrip.h"
#include <eggJointData.h>
#include <eggCharacterCollection.h>
#include <eggCharacterData.h>
#include <eggJointPointer.h>
#include <eggTable.h>
////////////////////////////////////////////////////////////////////
// Function: EggTopstrip::Constructor
// Access: Public
@ -20,6 +26,42 @@ EggTopstrip() {
"This is a particularly useful thing to do to generate character "
"models that can stack one on top of the other in a sensible way.");
add_option
("t", "name", 0,
"Specify the name of the 'top' joint, from which to draw the "
"animation channels which will be applied to the entire animation.",
&EggTopstrip::dispatch_string, NULL, &_top_joint_name);
add_option
("i", "", 0,
"Invert the matrix before applying. This causes a subtractive "
"effect. This is the default unless -r is specified.",
&EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform);
add_option
("n", "", 0,
"Do not invert the matrix before applying. This causes an "
"additive effect.",
&EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform);
add_option
("s", "[ijkphrxyz]", 0,
"Specify the components of the transform that are to be applied. Use "
"any combination of the nine token letters: i, j, k represent the "
"three scale axes; h, p, r represent rotation; and x, y, z represent "
"translation. The default is everything: -s ijkphrxyz.",
&EggTopstrip::dispatch_string, NULL, &_transform_channels);
add_option
("r", "file.egg", 0,
"Read the animation channel from the indicated egg file. If this "
"is not specified, the first egg file named on the command line is "
"used.",
&EggTopstrip::dispatch_filename, NULL, &_channel_filename);
_invert_transform = true;
_transform_channels = "ijkphrxyz";
}
////////////////////////////////////////////////////////////////////
@ -29,6 +71,169 @@ EggTopstrip() {
////////////////////////////////////////////////////////////////////
void EggTopstrip::
run() {
nassertv(_collection != (EggCharacterCollection *)NULL);
nassertv(_collection->get_num_eggs() > 0);
// 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.
int from_model = -1;
if (!_channel_filename.empty()) {
// Read in the extra egg file that we use for extracting the
// channels out.
PT(EggData) channel_egg = read_egg(_channel_filename);
if (channel_egg == (EggData *)NULL) {
nout << "Cannot read " << _channel_filename << "\n";
exit(1);
}
int channel_egg_index = _collection->add_egg(channel_egg);
if (channel_egg_index < 0) {
nout << _channel_filename
<< " does not contain a character model or animation channel.\n";
exit(1);
}
from_model = _collection->get_first_model_index(channel_egg_index);
if (!_got_invert_transform) {
// With -r, the default is not to invert the transform.
_invert_transform = false;
}
}
// Now process each character.
for (int i = 0; i < num_characters; i++) {
EggCharacterData *char_data = _collection->get_character(i);
EggJointData *root_joint = char_data->get_root_joint();
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";
exit(1);
}
top_joint = root_joint->get_child(0);
} else {
top_joint = char_data->find_joint(_top_joint_name);
if (top_joint == (EggJointData *)NULL) {
nout << "Character " << char_data->get_name()
<< " has no joint named " << _top_joint_name << "\n";
exit(1);
}
}
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(joint_data, from_model, top_joint);
}
// We also need to transform the vertices for any models involved
// here.
int num_models = char_data->get_num_models();
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);
}
}
}
write_eggs();
}
////////////////////////////////////////////////////////////////////
// Function: EggTopstrip::strip_anim
// Access: Public
// Description: Applies the channels from joint _top_joint
// in model from_model to the joint referenced by
// joint_data.
////////////////////////////////////////////////////////////////////
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) {
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);
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggTopstrip::strip_anim_vertices
// Access: Public
// Description: Applies the channels from joint _top_joint
// in model from_model to the vertices at egg_node.
////////////////////////////////////////////////////////////////////
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);
}
EggJointPointer *from_joint;
DCAST_INTO_V(from_joint, from_back);
LMatrix4d strip = from_joint->get_frame(0);
if (_invert_transform) {
strip.invert_in_place();
}
cerr << "Applying " << strip << " to vertices.\n";
egg_node->transform_vertices_only(strip);
}

View File

@ -9,6 +9,12 @@
#include <pandatoolbase.h>
#include <eggCharacterFilter.h>
#include <luse.h>
#include <vector>
class EggJointData;
class EggJointPointer;
////////////////////////////////////////////////////////////////////
// Class : EggTopstrip
@ -23,6 +29,18 @@ public:
EggTopstrip();
void run();
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);
string _top_joint_name;
bool _got_invert_transform;
bool _invert_transform;
string _transform_channels;
Filename _channel_filename;
};
#endif

View File

@ -567,6 +567,42 @@ dispatch_none(const string &, const string &, void *) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ProgramBase::dispatch_true
// Access: Protected, Static
// Description: Standard dispatch function for an option that takes
// no parameters, and when it is present sets a bool
// variable to the 'true' value. This is another way to
// handle a boolean flag. See also dispatch_none() and
// dispatch_false().
//
// The data pointer is to a bool variable.
////////////////////////////////////////////////////////////////////
bool ProgramBase::
dispatch_true(const string &, const string &, void *var) {
bool *bp = (bool *)var;
(*bp) = true;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ProgramBase::dispatch_false
// Access: Protected, Static
// Description: Standard dispatch function for an option that takes
// no parameters, and when it is present sets a bool
// variable to the 'false' value. This is another way to
// handle a boolean flag. See also dispatch_none() and
// dispatch_true().
//
// The data pointer is to a bool variable.
////////////////////////////////////////////////////////////////////
bool ProgramBase::
dispatch_false(const string &, const string &, void *var) {
bool *bp = (bool *)var;
(*bp) = false;
return true;
}
////////////////////////////////////////////////////////////////////
// Function: ProgramBase::dispatch_count
// Access: Protected, Static

View File

@ -66,6 +66,8 @@ protected:
bool remove_option(const string &option);
static bool dispatch_none(const string &opt, const string &arg, void *);
static bool dispatch_true(const string &opt, const string &arg, void *var);
static bool dispatch_false(const string &opt, const string &arg, void *var);
static bool dispatch_count(const string &opt, const string &arg, void *var);
static bool dispatch_int(const string &opt, const string &arg, void *var);
static bool dispatch_int_pair(const string &opt, const string &arg, void *var);