egg-optchar -defpose

This commit is contained in:
David Rose
2008-12-23 20:41:31 +00:00
parent 72cf05b6b1
commit 31d75582a3
37 changed files with 1913 additions and 1599 deletions

View File

@@ -90,10 +90,10 @@ PRC_DESC("Set this true to interpolate character animations between frames, "
ConfigVariableBool restore_initial_pose
("restore-initial-pose", true,
PRC_DESC("When this is true, stopping all animations on an Actor causes it "
"to return to its initial, unanimated pose. When false, it retains "
"whatever its last-computed pose was (which may or may not be "
"the unanimated pose)."));
PRC_DESC("When this is true, setting all control effects on an Actor to 0 "
"causes it to return to its default, unanimated pose. When "
"false, it retains whatever its last-computed pose was "
"(which may or may not be the default pose)."));
ConfigureFn(config_chan) {

View File

@@ -38,7 +38,7 @@ INLINE MovingPart<SwitchType>::
MovingPart(const MovingPart<SwitchType> &copy) :
MovingPartBase(copy),
_value(copy._value),
_initial_value(copy._initial_value)
_default_value(copy._default_value)
{
}
@@ -50,10 +50,10 @@ MovingPart(const MovingPart<SwitchType> &copy) :
template<class SwitchType>
INLINE MovingPart<SwitchType>::
MovingPart(PartGroup *parent, const string &name,
const ValueType &initial_value) :
const ValueType &default_value) :
MovingPartBase(parent, name),
_value(initial_value),
_initial_value(initial_value)
_value(default_value),
_default_value(default_value)
{
}
@@ -84,7 +84,7 @@ get_value_type() const {
////////////////////////////////////////////////////////////////////
// Function: MovingPart::make_initial_channel
// Function: MovingPart::make_default_channel
// Access: Public, Virtual
// Description: Creates and returns a new AnimChannel that is not
// part of any hierarchy, but that returns the default
@@ -92,8 +92,8 @@ get_value_type() const {
////////////////////////////////////////////////////////////////////
template<class SwitchType>
AnimChannelBase *MovingPart<SwitchType>::
make_initial_channel() const {
return new AnimChannelFixed<SwitchType>(get_name(), _initial_value);
make_default_channel() const {
return new AnimChannelFixed<SwitchType>(get_name(), _default_value);
}
////////////////////////////////////////////////////////////////////
@@ -119,7 +119,7 @@ void MovingPart<SwitchType>::
write_datagram(BamWriter *manager, Datagram &me) {
MovingPartBase::write_datagram(manager, me);
SwitchType::write_datagram(me, _value);
SwitchType::write_datagram(me, _initial_value);
SwitchType::write_datagram(me, _default_value);
}
////////////////////////////////////////////////////////////////////
@@ -135,7 +135,7 @@ void MovingPart<SwitchType>::
fillin(DatagramIterator &scan, BamReader *manager) {
MovingPartBase::fillin(scan, manager);
SwitchType::read_datagram(scan, _value);
SwitchType::read_datagram(scan, _initial_value);
SwitchType::read_datagram(scan, _default_value);
}

View File

@@ -37,14 +37,14 @@ protected:
public:
INLINE MovingPart(PartGroup *parent, const string &name,
const ValueType &_initial_value);
const ValueType &default_value);
virtual TypeHandle get_value_type() const;
virtual AnimChannelBase *make_initial_channel() const;
virtual AnimChannelBase *make_default_channel() const;
virtual void output_value(ostream &out) const;
ValueType _value;
ValueType _initial_value;
ValueType _default_value;
public:
INLINE virtual void write_datagram(BamWriter* manager, Datagram &me);
@@ -65,8 +65,8 @@ PUBLISHED:
INLINE ValueType get_value() const {
return _value;
}
INLINE ValueType get_initial_value() const {
return _initial_value;
INLINE ValueType get_default_value() const {
return _default_value;
}
public:
static void init_type() {

View File

@@ -282,7 +282,7 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
// If we're binding to the NULL anim, it means actually to create
// a default AnimChannel that just returns the part's initial
// value.
_channels[channel_index] = make_initial_channel();
_channels[channel_index] = make_default_channel();
} else {
_channels[channel_index] = DCAST(AnimChannelBase, anim);
}

View File

@@ -44,7 +44,7 @@ PUBLISHED:
public:
virtual TypeHandle get_value_type() const=0;
virtual AnimChannelBase *make_initial_channel() const=0;
virtual AnimChannelBase *make_default_channel() const=0;
PUBLISHED:
virtual bool clear_forced_channel();

View File

@@ -32,8 +32,8 @@ MovingPartMatrix(const MovingPartMatrix &copy) :
////////////////////////////////////////////////////////////////////
INLINE MovingPartMatrix::
MovingPartMatrix(PartGroup *parent, const string &name,
const LMatrix4f &initial_value)
: MovingPart<ACMatrixSwitchType>(parent, name, initial_value) {
const LMatrix4f &default_value)
: MovingPart<ACMatrixSwitchType>(parent, name, default_value) {
}
////////////////////////////////////////////////////////////////////

View File

@@ -40,16 +40,16 @@ MovingPartMatrix::
////////////////////////////////////////////////////////////////////
// Function: MovingPartMatrix::make_initial_channel
// Function: MovingPartMatrix::make_default_channel
// Access: Public, Virtual
// Description: Creates and returns a new AnimChannel that is not
// part of any hierarchy, but that returns the default
// value associated with this part.
////////////////////////////////////////////////////////////////////
AnimChannelBase *MovingPartMatrix::
make_initial_channel() const {
make_default_channel() const {
LVecBase3f pos, hpr, scale, shear;
decompose_matrix(_initial_value, pos, hpr, scale, shear);
decompose_matrix(_default_value, pos, hpr, scale, shear);
return new AnimChannelMatrixFixed(get_name(), pos, hpr, scale);
}
@@ -76,7 +76,7 @@ get_blend_value(const PartBundle *root) {
if (cdata->_blend.empty()) {
// No channel is bound; supply the default value.
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else if (_effective_control != (AnimControl *)NULL &&
@@ -126,7 +126,7 @@ get_blend_value(const PartBundle *root) {
if (net_effect == 0.0f) {
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else {
_value = net_value / net_effect;
@@ -194,7 +194,7 @@ get_blend_value(const PartBundle *root) {
if (net_effect == 0.0f) {
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else {
@@ -273,7 +273,7 @@ get_blend_value(const PartBundle *root) {
if (net_effect == 0.0f) {
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else {
@@ -352,7 +352,7 @@ get_blend_value(const PartBundle *root) {
if (net_effect == 0.0f) {
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else {

View File

@@ -35,11 +35,10 @@ protected:
public:
INLINE MovingPartMatrix(PartGroup *parent, const string &name,
const LMatrix4f &initial_value =
LMatrix4f::ident_mat());
const LMatrix4f &default_value);
virtual ~MovingPartMatrix();
virtual AnimChannelBase *make_initial_channel() const;
virtual AnimChannelBase *make_default_channel() const;
virtual void get_blend_value(const PartBundle *root);
virtual bool apply_freeze_matrix(const LVecBase3f &pos, const LVecBase3f &hpr, const LVecBase3f &scale);

View File

@@ -32,8 +32,8 @@ MovingPartScalar(const MovingPartScalar &copy) :
////////////////////////////////////////////////////////////////////
INLINE MovingPartScalar::
MovingPartScalar(PartGroup *parent, const string &name,
const float &initial_value)
: MovingPart<ACScalarSwitchType>(parent, name, initial_value) {
const float &default_value)
: MovingPart<ACScalarSwitchType>(parent, name, default_value) {
}
////////////////////////////////////////////////////////////////////

View File

@@ -59,7 +59,7 @@ get_blend_value(const PartBundle *root) {
if (cdata->_blend.empty()) {
// No channel is bound; supply the default value.
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else if (_effective_control != (AnimControl *)NULL &&
@@ -105,7 +105,7 @@ get_blend_value(const PartBundle *root) {
if (net == 0.0f) {
if (restore_initial_pose) {
_value = _initial_value;
_value = _default_value;
}
} else {

View File

@@ -34,7 +34,7 @@ protected:
public:
INLINE MovingPartScalar(PartGroup *parent, const string &name,
const float &initial_value = 0);
const float &default_value = 0);
virtual ~MovingPartScalar();
virtual void get_blend_value(const PartBundle *root);

View File

@@ -198,8 +198,8 @@ apply_transform(const TransformState *transform) {
// Description: Sets the control effect of all AnimControls to zero
// (but does not "stop" the AnimControls). The
// character will no longer be affected by any
// animation, and will return to its original Jesus
// pose.
// animation, and will return to its default
// pose (unless restore-initial-pose is false).
//
// The AnimControls which are no longer associated will
// not be using any CPU cycles, but they may still be in
@@ -217,6 +217,7 @@ clear_control_effects() {
cdataw->_blend.clear();
cdataw->_net_blend = 0.0f;
cdataw->_anim_changed = true;
determine_effective_channels(cdata);
}
}
@@ -806,6 +807,7 @@ clear_and_stop_intersecting(AnimControl *control, CData *cdata) {
cdata->_net_blend = new_net_blend;
cdata->_blend.swap(new_blend);
cdata->_anim_changed = true;
determine_effective_channels(cdata);
}
}

View File

@@ -57,8 +57,8 @@ CharacterJoint(const CharacterJoint &copy) :
CharacterJoint::
CharacterJoint(Character *character,
PartBundle *root, PartGroup *parent, const string &name,
const LMatrix4f &initial_value) :
MovingPartMatrix(parent, name, initial_value),
const LMatrix4f &default_value) :
MovingPartMatrix(parent, name, default_value),
_character(character)
{
Thread *current_thread = Thread::get_current_thread();

View File

@@ -38,7 +38,7 @@ protected:
PUBLISHED:
CharacterJoint(Character *character,
PartBundle *root, PartGroup *parent, const string &name,
const LMatrix4f &initial_value);
const LMatrix4f &default_value);
virtual ~CharacterJoint();
public:

View File

@@ -47,6 +47,7 @@ JointVertexTransform(CharacterJoint *joint) :
{
// Tell the joint that we need to be informed when it moves.
_joint->_vertex_transforms.insert(this);
mark_modified(Thread::get_current_thread());
}
////////////////////////////////////////////////////////////////////
@@ -219,4 +220,5 @@ fillin(DatagramIterator &scan, BamReader *manager) {
manager->read_pointer(scan);
_matrix_stale = true;
mark_modified(Thread::get_current_thread());
}

View File

@@ -1508,6 +1508,26 @@ GROUPING ENTRIES
may define either a 2-d or a 3-d transform when it appears within
the body of a <Texture>. See <Texture>, above.
<DefaultPose> { transform-definition }
This defines an optional default pose transform, which might be a
different transform from that defined by the <Transform> entry,
above. This makes sense only for a <Joint>. See the <Joint>
description, below.
The default pose transform defines the transform the joint will
maintain in the absence of any animation being applied. This is
different from the <Transform> entry, which defines the coordinate
space the joint must have in order to keep its vertices in their
(global space) position as given in the egg file. If this is
different from the <Transform> entry, the joint's vertices will
*not* be in their egg file position at initial load. If there is
no <DefaultPose> entry for a particular joint, the implicit
default-pose transform is the same as the <Transform> entry.
Normally, the <DefaultPose> entry, if any, is created by the
egg-optchar -defpose option. Most other software has little
reason to specify an explicit <DefaultPose>.
<VertexRef> { indices <Ref> { pool-name } }
@@ -1768,8 +1788,9 @@ ANIMATION STRUCTURE
It is not necessary for every joint to have vertices at all. Every
joint should include a transform entry, however, which defines the
initial, resting transform of the joint. If a transform is omitted,
the identity transform is assumed.
initial, resting transform of the joint (but see also <DefaultPose>,
above). If a transform is omitted, the identity transform is
assumed.
Some of the vertex definitions may include morph entries, as
described in MORPH DESCRIPTION ENTRIES, above. These are meaningful

View File

@@ -904,6 +904,61 @@ clear_tag(const string &key) {
_tag_data.erase(key);
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::get_default_pose
// Access: Published
// Description: Returns a read-only accessor to the initial pose
// transform. This is the <DefaultPose> entry for a
// Joint, and defines only the initial transform pose
// for the unanimated joint; it has nothing to do with
// the group's <Transform> entry, which defines the
// (eventual) space of the group's vertices.
////////////////////////////////////////////////////////////////////
INLINE const EggTransform &EggGroup::
get_default_pose() const {
return _default_pose;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::modify_default_pose
// Access: Published
// Description: Returns a writable accessor to the initial pose
// transform. This is the <DefaultPose> entry for a
// Joint, and defines only the initial transform pose
// for the unanimated joint; it has nothing to do with
// the group's <Transform> entry, which defines the
// (eventual) space of the group's vertices.
////////////////////////////////////////////////////////////////////
INLINE EggTransform &EggGroup::
modify_default_pose() {
return _default_pose;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::set_default_pose
// Access: Published
// Description: Replaces the initial pose transform. This is the
// <DefaultPose> entry for a Joint, and defines only the
// initial transform pose for the unanimated joint; it
// has nothing to do with the group's <Transform> entry,
// which defines the (eventual) space of the group's
// vertices.
////////////////////////////////////////////////////////////////////
INLINE void EggGroup::
set_default_pose(const EggTransform &transform) {
_default_pose = transform;
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::clear_default_pose
// Access: Published
// Description: Removes the initial pose transform. See
// set_default_pose().
////////////////////////////////////////////////////////////////////
INLINE void EggGroup::
clear_default_pose() {
_default_pose.clear_transform();
}
////////////////////////////////////////////////////////////////////
// Function: EggGroup::tag_begin

View File

@@ -74,8 +74,8 @@ operator = (const EggGroup &copy) {
_blend_operand_a = copy._blend_operand_a;
_blend_operand_b = copy._blend_operand_b;
_blend_color = copy._blend_color;
_tag_data = copy._tag_data;
_default_pose = copy._default_pose;
unref_all_vertices();
_vref = copy._vref;
@@ -219,7 +219,11 @@ write(ostream &out, int indent_level) const {
write_switch_flags(out, indent_level + 2);
if (has_transform()) {
EggTransform::write(out, indent_level + 2);
EggTransform::write(out, indent_level + 2, "<Transform>");
}
if (get_group_type() == GT_joint && _default_pose.has_transform()) {
_default_pose.write(out, indent_level + 2, "<DefaultPose>");
}
write_object_types(out, indent_level + 2);
@@ -1251,6 +1255,12 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
internal_set_transform(inv1 * get_transform3d() * mat);
if (_default_pose.has_transform()) {
LMatrix4d t = _default_pose.get_transform3d();
_default_pose.clear_transform();
_default_pose.add_matrix4(inv1 * t * mat);
}
EggGroupNode::r_transform(mat1, inv1, to_cs);
} else {
EggGroupNode::r_transform(mat, inv, to_cs);

View File

@@ -262,6 +262,11 @@ PUBLISHED:
INLINE bool has_tag(const string &key) const;
INLINE void clear_tag(const string &key);
INLINE const EggTransform &get_default_pose() const;
INLINE EggTransform &modify_default_pose();
INLINE void set_default_pose(const EggTransform &transform);
INLINE void clear_default_pose();
public:
INLINE TagData::const_iterator tag_begin() const;
INLINE TagData::const_iterator tag_end() const;
@@ -360,6 +365,12 @@ private:
double _fps;
PT(EggSwitchCondition) _lod;
TagData _tag_data;
// This is the <DefaultPose> entry for a <Joint>. It is not the
// <Transform> entry (that is stored via inheritance, in the
// EggTransform class we inherit from).
EggTransform _default_pose;
VertexRef _vref;
typedef pvector< PT(EggGroup) > GroupRefs;

View File

@@ -290,7 +290,7 @@ write(ostream &out, int indent_level) const {
EggRenderMode::write(out, indent_level + 2);
if (has_transform()) {
EggTransform::write(out, indent_level + 2);
EggTransform::write(out, indent_level + 2, "<Transform>");
}
indent(out, indent_level) << "}\n";

View File

@@ -230,8 +230,8 @@ add_uniform_scale(double scale) {
// format.
////////////////////////////////////////////////////////////////////
void EggTransform::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << "<Transform> {\n";
write(ostream &out, int indent_level, const string &label) const {
indent(out, indent_level) << label << " {\n";
int num_components = get_num_components();
for (int i = 0; i < num_components; i++) {

View File

@@ -17,6 +17,7 @@
#include "pandabase.h"
#include "luse.h"
#include "eggObject.h"
////////////////////////////////////////////////////////////////////
// Class : EggTransform
@@ -85,7 +86,8 @@ PUBLISHED:
INLINE const LMatrix3d &get_component_mat3(int n) const;
INLINE const LMatrix4d &get_component_mat4(int n) const;
void write(ostream &out, int indent_level) const;
void write(ostream &out, int indent_level,
const string &label) const;
protected:
void internal_clear_transform();

File diff suppressed because it is too large Load Diff

View File

@@ -435,21 +435,13 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
accept();
return EXTERNAL_FILE;
}
"<FLT_HEADER>" {
accept();
return FLIGHT;
}
"<GROUP>" {
accept();
return GROUP;
}
"<HIP>" {
"<DEFAULTPOSE>" {
accept();
return HIP;
}
"<IN>" {
accept();
return INTANGENT;
return DEFAULTPOSE;
}
"<JOINT>" {
accept();

File diff suppressed because it is too large Load Diff

View File

@@ -24,69 +24,67 @@
#define DTREF 280
#define DYNAMICVERTEXPOOL 281
#define EXTERNAL_FILE 282
#define FLIGHT 283
#define GROUP 284
#define HIP 285
#define INTANGENT 286
#define JOINT 287
#define KNOTS 288
#define INCLUDE 289
#define INSTANCE 290
#define LINE 291
#define LOOP 292
#define MATERIAL 293
#define MATRIX3 294
#define MATRIX4 295
#define MODEL 296
#define MREF 297
#define NORMAL 298
#define NURBSCURVE 299
#define NURBSSURFACE 300
#define OBJECTTYPE 301
#define ORDER 302
#define OUTTANGENT 303
#define POINTLIGHT 304
#define POLYGON 305
#define REF 306
#define RGBA 307
#define ROTATE 308
#define ROTX 309
#define ROTY 310
#define ROTZ 311
#define SANIM 312
#define SCALAR 313
#define SCALE 314
#define SEQUENCE 315
#define SHADING 316
#define SWITCH 317
#define SWITCHCONDITION 318
#define TABLE 319
#define TABLE_V 320
#define TAG 321
#define TANGENT 322
#define TEXLIST 323
#define TEXTURE 324
#define TLENGTHS 325
#define TRANSFORM 326
#define TRANSLATE 327
#define TREF 328
#define TRIANGLEFAN 329
#define TRIANGLESTRIP 330
#define TRIM 331
#define TXT 332
#define UKNOTS 333
#define UV 334
#define VKNOTS 335
#define VERTEX 336
#define VERTEXANIM 337
#define VERTEXPOOL 338
#define VERTEXREF 339
#define XFMANIM 340
#define XFMSANIM 341
#define START_EGG 342
#define START_GROUP_BODY 343
#define START_TEXTURE_BODY 344
#define START_PRIMITIVE_BODY 345
#define GROUP 283
#define DEFAULTPOSE 284
#define JOINT 285
#define KNOTS 286
#define INCLUDE 287
#define INSTANCE 288
#define LINE 289
#define LOOP 290
#define MATERIAL 291
#define MATRIX3 292
#define MATRIX4 293
#define MODEL 294
#define MREF 295
#define NORMAL 296
#define NURBSCURVE 297
#define NURBSSURFACE 298
#define OBJECTTYPE 299
#define ORDER 300
#define OUTTANGENT 301
#define POINTLIGHT 302
#define POLYGON 303
#define REF 304
#define RGBA 305
#define ROTATE 306
#define ROTX 307
#define ROTY 308
#define ROTZ 309
#define SANIM 310
#define SCALAR 311
#define SCALE 312
#define SEQUENCE 313
#define SHADING 314
#define SWITCH 315
#define SWITCHCONDITION 316
#define TABLE 317
#define TABLE_V 318
#define TAG 319
#define TANGENT 320
#define TEXLIST 321
#define TEXTURE 322
#define TLENGTHS 323
#define TRANSFORM 324
#define TRANSLATE 325
#define TREF 326
#define TRIANGLEFAN 327
#define TRIANGLESTRIP 328
#define TRIM 329
#define TXT 330
#define UKNOTS 331
#define UV 332
#define VKNOTS 333
#define VERTEX 334
#define VERTEXANIM 335
#define VERTEXPOOL 336
#define VERTEXREF 337
#define XFMANIM 338
#define XFMSANIM 339
#define START_EGG 340
#define START_GROUP_BODY 341
#define START_TEXTURE_BODY 342
#define START_PRIMITIVE_BODY 343
extern YYSTYPE eggyylval;

View File

@@ -33,6 +33,7 @@
#include "eggExternalReference.h"
#include "eggData.h"
#include "eggAnimPreload.h"
#include "eggTransform.h"
#include "pt_EggTexture.h"
#include "pt_EggMaterial.h"
@@ -61,6 +62,9 @@
typedef pvector< PT(EggObject) > EggStack;
static EggStack egg_stack;
// This is used just when parsing a <Transform> or <DefaultPose> entry.
static EggTransform *egg_top_transform;
// There's one "top-level" egg node, which is where we should parent
// things (e.g. implicit textures) encountered in the egg file that
// don't have an explicit place in the tree. If this is NULL, such
@@ -160,7 +164,7 @@ egg_cleanup_parser() {
%token COORDSYSTEM CV DART
%token DNORMAL DRGBA DUV DXYZ DCS DISTANCE DTREF
%token DYNAMICVERTEXPOOL EXTERNAL_FILE
%token FLIGHT GROUP HIP INTANGENT
%token GROUP DEFAULTPOSE
%token JOINT KNOTS INCLUDE
%token INSTANCE LINE LOOP MATERIAL MATRIX3 MATRIX4 MODEL MREF NORMAL
%token NURBSCURVE NURBSSURFACE OBJECTTYPE ORDER
@@ -1432,6 +1436,7 @@ group_body:
group->set_texlist_flag(value!=0);
}
| group_body transform
| group_body default_pose
| group_body group_vertex_ref
| group_body switchcondition
| group_body REF '{' group_name '}'
@@ -1512,7 +1517,28 @@ collide_flags:
transform:
TRANSFORM
{
egg_stack.back()->as_transform()->clear_transform();
egg_top_transform = egg_stack.back()->as_transform();
egg_top_transform->clear_transform();
}
'{' transform_body '}'
;
/*
* default_pose
*
* enter: TOS is an EggGroup
* exit: default_pose matrix has been set.
*
*/
default_pose:
DEFAULTPOSE
{
EggGroup *group = DCAST(EggGroup, egg_stack.back());
if (group->get_group_type() != EggGroup::GT_joint) {
eggyywarning("Unexpected <DefaultPose> outside of <Joint>");
}
egg_top_transform = &group->modify_default_pose();
egg_top_transform->clear_transform();
}
'{' transform_body '}'
;
@@ -1521,7 +1547,7 @@ transform:
/*
* transform_body
*
* enter: TOS is some kind of EggTransform.
* enter: egg_top_transform has been assigned.
* exit: transform has been filled in.
*
*/
@@ -1544,70 +1570,70 @@ transform_body:
translate2d:
TRANSLATE '{' real real '}'
{
egg_stack.back()->as_transform()->add_translate2d(LVector2d($3, $4));
egg_top_transform->add_translate2d(LVector2d($3, $4));
}
;
translate3d:
TRANSLATE '{' real real real '}'
{
egg_stack.back()->as_transform()->add_translate3d(LVector3d($3, $4, $5));
egg_top_transform->add_translate3d(LVector3d($3, $4, $5));
}
;
rotate2d:
ROTATE '{' real '}'
{
egg_stack.back()->as_transform()->add_rotate2d($3);
egg_top_transform->add_rotate2d($3);
}
;
rotx:
ROTX '{' real '}'
{
egg_stack.back()->as_transform()->add_rotx($3);
egg_top_transform->add_rotx($3);
}
;
roty:
ROTY '{' real '}'
{
egg_stack.back()->as_transform()->add_roty($3);
egg_top_transform->add_roty($3);
}
;
rotz:
ROTZ '{' real '}'
{
egg_stack.back()->as_transform()->add_rotz($3);
egg_top_transform->add_rotz($3);
}
;
rotate3d:
ROTATE '{' real real real real '}'
{
egg_stack.back()->as_transform()->add_rotate3d($3, LVector3d($4, $5, $6));
egg_top_transform->add_rotate3d($3, LVector3d($4, $5, $6));
}
;
scale2d:
SCALE '{' real real '}'
{
egg_stack.back()->as_transform()->add_scale2d(LVecBase2d($3, $4));
egg_top_transform->add_scale2d(LVecBase2d($3, $4));
}
;
scale3d:
SCALE '{' real real real '}'
{
egg_stack.back()->as_transform()->add_scale3d(LVecBase3d($3, $4, $5));
egg_top_transform->add_scale3d(LVecBase3d($3, $4, $5));
}
;
uniform_scale:
SCALE '{' real '}'
{
egg_stack.back()->as_transform()->add_uniform_scale($3);
egg_top_transform->add_uniform_scale($3);
}
;
@@ -1621,7 +1647,7 @@ matrix3_body:
real real real
real real real
{
egg_stack.back()->as_transform()->add_matrix3
egg_top_transform->add_matrix3
(LMatrix3d($1, $2, $3,
$4, $5, $6,
$7, $8, $9));
@@ -1639,7 +1665,7 @@ matrix4_body:
real real real real
real real real real
{
egg_stack.back()->as_transform()->add_matrix4
egg_top_transform->add_matrix4
(LMatrix4d($1, $2, $3, $4,
$5, $6, $7, $8,
$9, $10, $11, $12,

View File

@@ -224,17 +224,21 @@ egg_to_slider(const string &name) {
CharacterJointBundle *CharacterMaker::
make_bundle() {
build_joint_hierarchy(_egg_root, _skeleton_root, -1);
make_geometry(_egg_root);
_bundle->sort_descendants();
parent_joint_nodes(_skeleton_root);
// Now call update() one more time, to ensure that all of the joints
// have their correct transform (since we might have modified the
// default transform after construction).
_bundle->force_update();
return _bundle;
}
////////////////////////////////////////////////////////////////////
// Function: CharacterMaker::build_hierarchy
// Function: CharacterMaker::build_joint_hierarchy
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
@@ -271,6 +275,9 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part, int index) {
// We need to get the transform of the joint, and then convert
// it to single-precision.
LMatrix4d matd;
// First, we get the original, initial transform from the
// <Transform> entry.
if (egg_group->has_transform()) {
matd = egg_group->get_transform3d();
} else {
@@ -285,6 +292,16 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part, int index) {
index = _parts.size();
_parts.push_back(joint);
// Now that we have computed _net_transform (which we need to
// convert the vertices), update the default transform from the
// <DefaultPose> entry.
if (egg_group->get_default_pose().has_transform()) {
matd = egg_group->get_default_pose().get_transform3d();
matf = LCAST(float, matd);
joint->_default_value = matf;
joint->_value = matf;
}
if (egg_group->has_dcs_type()) {
// If the joint requested an explicit DCS, create a node for
// it.

View File

@@ -189,6 +189,7 @@ write(ostream &out, int indent_level) const {
mat.write(out, indent_level + 4);
}
LMatrix4f blend;
update_blend(current_thread);
get_blend(blend, current_thread);
indent(out, indent_level)
<< "Blended result =\n";

View File

@@ -112,6 +112,16 @@ EggOptchar() {
"objects parented to this node will not inherit its animation.",
&EggOptchar::dispatch_flag_groups, NULL, &_flag_groups);
add_option
("defpose", "anim.egg,frame", 0,
"Specify the model's default pose. The pose is taken "
"from the indicated frame of the named animation file (which must "
"also be named separately on the command line). The "
"pose will be held by the model in "
"the absence of any animation, and need not be the same "
"pose in which the model was originally skinned.",
&EggOptchar::dispatch_string, NULL, &_defpose);
add_option
("preload", "", 0,
"Add an <AnimPreload> entry for each animation to the model file(s). "
@@ -273,6 +283,13 @@ run() {
do_preload();
}
// Finally, set the default poses. It's important not to do this
// until after we have adjusted all of the transforms for the
// various joints.
if (!_defpose.empty()) {
do_defpose();
}
write_eggs();
}
}
@@ -1421,6 +1438,83 @@ do_preload() {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggOptchar::do_defpose
// Access: Private
// Description: Sets the initial pose for the character(s).
////////////////////////////////////////////////////////////////////
void EggOptchar::
do_defpose() {
// Split out the defpose parameter.
Filename egg_filename;
size_t comma = _defpose.find(',');
egg_filename = _defpose.substr(0, comma);
string frame_str;
if (comma != string::npos) {
frame_str = _defpose.substr(comma + 1);
}
frame_str = trim(frame_str);
int frame = 0;
if (!frame_str.empty()) {
if (!string_to_int(frame_str, frame)) {
nout << "Invalid integer in -defpose: " << frame_str << "\n";
return;
}
}
// Now find the named animation file in our egg list.
int egg_index = -1;
int num_eggs = _collection->get_num_eggs();
int i;
// First, look for an exact match.
for (i = 0; i < num_eggs && egg_index == -1; ++i) {
if (_collection->get_egg(i)->get_egg_filename() == egg_filename) {
egg_index = i;
}
}
// Then, look for an inexact match.
string egg_basename = egg_filename.get_basename_wo_extension();
for (i = 0; i < num_eggs && egg_index == -1; ++i) {
if (_collection->get_egg(i)->get_egg_filename().get_basename_wo_extension() == egg_basename) {
egg_index = i;
}
}
if (egg_index == -1) {
// No joy.
nout << "Egg file " << egg_filename << " named in -defpose, but does not appear on command line.\n";
return;
}
EggData *egg_data = _collection->get_egg(egg_index);
if (_collection->get_num_models(egg_index) == 0) {
nout << "Egg file " << egg_filename << " does not include any model or animation.\n";
return;
}
// Now get the first model (or animation) named by this egg file.
int mi = _collection->get_first_model_index(egg_index);
EggCharacterData *ch = _collection->get_character_by_model_index(mi);
EggJointData *root_joint = ch->get_root_joint();
int anim_index = -1;
for (i = 0; i < ch->get_num_models() && anim_index == -1; ++i) {
if (ch->get_egg_data(i) == egg_data) {
anim_index = i;
}
}
// This couldn't possibly fail, since we already checked this above.
nassertv(anim_index != -1);
// Now we can recursively apply the default pose to the hierarchy.
ch->get_root_joint()->apply_default_pose(anim_index, frame);
}
int main(int argc, char *argv[]) {
// A call to pystub() to force libpystub.so to be linked in.
pystub();

View File

@@ -78,6 +78,7 @@ private:
void do_flag_groups(EggGroupNode *egg_group);
void rename_primitives(EggGroupNode *egg_group, const string &name);
void do_preload();
void do_defpose();
bool _list_hierarchy;
bool _list_hierarchy_v;
@@ -118,6 +119,8 @@ private:
typedef pvector<FlagGroupsEntry> FlagGroups;
FlagGroups _flag_groups;
string _defpose;
bool _optimal_hierarchy;
double _vref_quantum;
};

View File

@@ -411,6 +411,37 @@ quantize_channels(const string &components, double quantum) {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::apply_default_pose
// Access: Public
// Description: Applies the pose from the indicated frame of the
// indicated source model_index as the initial pose for
// this joint, and does this recursively on all joints
// below.
////////////////////////////////////////////////////////////////////
void EggJointData::
apply_default_pose(int source_model, int frame) {
if (has_model(source_model)) {
EggJointPointer *source_joint;
DCAST_INTO_V(source_joint, _back_pointers[source_model]);
BackPointers::iterator bpi;
for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
EggBackPointer *back = (*bpi);
if (back != (EggBackPointer *)NULL) {
EggJointPointer *joint;
DCAST_INTO_V(joint, back);
joint->apply_default_pose(source_joint, frame);
}
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
EggJointData *child = (*ci);
child->apply_default_pose(source_model, frame);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointData::add_back_pointer
// Access: Public, Virtual

View File

@@ -59,6 +59,7 @@ public:
void expose(EggGroup::DCSType dcs_type = EggGroup::DC_default);
void zero_channels(const string &components);
void quantize_channels(const string &components, double quantum);
void apply_default_pose(int source_model, int frame);
virtual void add_back_pointer(int model_index, EggObject *egg_object);
virtual void write(ostream &out, int indent_level = 0) const;

View File

@@ -178,6 +178,27 @@ expose(EggGroup::DCSType dcs_type) {
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointNodePointer::apply_default_pose
// Access: Public, Virtual
// Description: Applies the pose from the indicated frame of the
// indicated source joint as the initial pose for
// this joint.
////////////////////////////////////////////////////////////////////
void EggJointNodePointer::
apply_default_pose(EggJointPointer *source_joint, int frame) {
if (_joint != (EggGroup *)NULL) {
LMatrix4d pose;
if (frame >= 0 && frame < source_joint->get_num_frames()) {
pose = source_joint->get_frame(frame);
} else {
pose = get_frame(0);
}
_joint->clear_default_pose();
_joint->modify_default_pose().add_matrix4(pose);
}
}
////////////////////////////////////////////////////////////////////
// Function: EggJointNodePointer::has_vertices
// Access: Public, Virtual

View File

@@ -39,6 +39,7 @@ public:
virtual bool do_rebuild(EggCharacterDb &db);
virtual void expose(EggGroup::DCSType dcs_type);
virtual void apply_default_pose(EggJointPointer *source_joint, int frame);
virtual bool has_vertices() const;

View File

@@ -98,3 +98,14 @@ zero_channels(const string &) {
void EggJointPointer::
quantize_channels(const string &, double) {
}
////////////////////////////////////////////////////////////////////
// Function: EggJointPointer::apply_default_pose
// Access: Public, Virtual
// Description: Applies the pose from the indicated frame of the
// indicated source joint as the initial pose for
// this joint.
////////////////////////////////////////////////////////////////////
void EggJointPointer::
apply_default_pose(EggJointPointer *source_joint, int frame) {
}

View File

@@ -47,6 +47,7 @@ public:
virtual void expose(EggGroup::DCSType dcs_type);
virtual void zero_channels(const string &components);
virtual void quantize_channels(const string &components, double quantum);
virtual void apply_default_pose(EggJointPointer *source_joint, int frame);
virtual EggJointPointer *make_new_joint(const string &name)=0;