Designing better structures for animation tool

D

Darren

X-No-Archive

Hi all,

Can anyone help me with structuring the data in a small tool I have to
build? I'm trying to work out if there's a design pattern or data
structure that would remove some of the dependencies.

I am designing an animation tool.

A /Character/ is easily represented by a tree, each node of which
delegates to a vector. A skeleton or stickman can therefore be
described.

Any number of /Poses/ (or Keyframes) can be defined, each of which is
an angle for each joint in the Character. A Pose can therefore be
stored using a tree, each node of which delegates to an Integer, which
is the angle for that joint.

Here we have the first problem: each Pose (there won't be less than 50
Poses) requires storing a tree of the same structure as the Character.
If the Character's structure changes, every Pose needs to be explicitly
notified of this change.

Any number of /Animations/ may be defined. These are a list of Poses
(the same Pose may be used in any number of Animations).

Here we have my second problem - do I index or reference the Poses?
Either way, if a Pose is deleted, every Animation will have to be
individually notified of the deletion, so that the integrity of the
Pose list in the Animation is kept.

In addition, each Animation has an /Interpolation/ for each pair of
Poses in the list. This may be a set of Beziers, one for each joint in
the Character. These can be stored in a tree, each node of which
delegates to a Bezier object which describes the motion curve for that
joint, but this is the same as my first problem: each Interpolation
requires storing a tree of the same structure as the character.


I have looked at organising this data differently: one method would be
for each node in a Character's tree to delegate to a Joint object, each
of which contains a list of angles, one for each Pose in the system -
but this scatters the discreet notion of a 'Pose' into an "index into
many joints' Poses list".


If it's a choice between the two techniques, I've tried the latter and
I'm tempted to try the former, thinking that keeping a set of trees
following the same structure is the nicer of the two solutions.


I guess the ideal would be if the tree structures used by the Pose and
Animation objects somehow implicitly reflect the Character's tree, but
I'm not sure if this is possible - any ideas on this or other ways to
improve this design?


Many thanks,
Darren Grant
 
V

Victor Bazarov

X-No-Archive
Darren said:
Can anyone help me with structuring the data in a small tool I have to
build? I'm trying to work out if there's a design pattern or data
structure that would remove some of the dependencies.
[..]

I didn't find a C++ _language_ question in your post, sorry. You might
be much better off asking your OOD question in 'comp.object' or in any
of 'comp.games.development.*' newsgroups.

V
 
C

Chris Theis

Darren said:
X-No-Archive

Hi all,

Can anyone help me with structuring the data in a small tool I have to
build? I'm trying to work out if there's a design pattern or data
structure that would remove some of the dependencies.

I am designing an animation tool.

A /Character/ is easily represented by a tree, each node of which
delegates to a vector. A skeleton or stickman can therefore be
described.

Any number of /Poses/ (or Keyframes) can be defined, each of which is
an angle for each joint in the Character. A Pose can therefore be
stored using a tree, each node of which delegates to an Integer, which
is the angle for that joint.

Here we have the first problem: each Pose (there won't be less than 50
Poses) requires storing a tree of the same structure as the Character.
If the Character's structure changes, every Pose needs to be explicitly
notified of this change.

Any number of /Animations/ may be defined. These are a list of Poses
(the same Pose may be used in any number of Animations).

Here we have my second problem - do I index or reference the Poses?
Either way, if a Pose is deleted, every Animation will have to be
individually notified of the deletion, so that the integrity of the
Pose list in the Animation is kept.

In addition, each Animation has an /Interpolation/ for each pair of
Poses in the list. This may be a set of Beziers, one for each joint in
the Character. These can be stored in a tree, each node of which
delegates to a Bezier object which describes the motion curve for that
joint, but this is the same as my first problem: each Interpolation
requires storing a tree of the same structure as the character.


I have looked at organising this data differently: one method would be
for each node in a Character's tree to delegate to a Joint object, each
of which contains a list of angles, one for each Pose in the system -
but this scatters the discreet notion of a 'Pose' into an "index into
many joints' Poses list".


If it's a choice between the two techniques, I've tried the latter and
I'm tempted to try the former, thinking that keeping a set of trees
following the same structure is the nicer of the two solutions.


I guess the ideal would be if the tree structures used by the Pose and
Animation objects somehow implicitly reflect the Character's tree, but
I'm not sure if this is possible - any ideas on this or other ways to
improve this design?

This is actually an OO design question and not specifically related to C++.
However, some ideas came to my mind:

[Off topic from here on]

Each character has a collection of possible poses. If you declare these
poses not in absolute numbers but in relative numbers you can easily handle
transitions and furthermore, this allows for a vast number of inherently
available poses influenced by the original pose of the character. The
relation between poses and character etc. could be done using an observer
design pattern. Looking this up in Google you'll find plenty of information.
The same holds true for the relation of animations and poses. In case you do
not keep copies of the available poses but just reference them (I'd even do
this via the characters because they must be in the animation and implicitly
carry the poses with them) you have no problem with on-line modifications.
Regarding the interpolation objects I'd add them as members to the snimation
objects and they can store a reference to the start & end pose. Hence, any
modification will automatically have an effect on all participants.

HTH
Chris
 
D

Darren

X-No-Archive

Hi Chris,

Thanks for the reply. Actually the whole tool caters just for the
animation of one character.

When you say 'declare the poses in relative numbers', do you mean the
angles of each joint? I just realised I made a mistake in my original
description - the skeleton is described by a tree of Lengths (ints) -
not vectors, so there's no 'original pose' to model the Poses on.

Imagine an 'Edit view', where an artist will model the skeleton with a
scratchpad-esque form where the joints may be freely rotated and
reshaped. Poses are done after this, in the 'Pose view', by dragging
the joints around, for example into a couple of 'Walk' poses.

Finally in the 'Animate view' poses will be dragged from the 'Poses
palette' into an 'Animation graph', for instance the 4 walk Poses will
be dragged into the correct order to form a walk animation. A 'Start
walking' animation may end with the same Pose that the 'Walking'
animation starts with (allowing 'Start walking' to segue into
'Walking').

Good idea to use the observer - but given that there is only one
Character in the system, I'm thinking it's probably overkill.

The Interpolations themselves do not need to know of the Poses they
interpolate between - they simply control the speed of each joint's
interpolation between two keyframes during rendering.


So, I've got the four classes:

Character
Tree of Integer: static sSkeleton
(each nodes delegates to Integer Length)

Pose
Tree of Integer: mKeyFrame
(same structure as Character.sSkeleton[1],
each node delegates to Integer Angle)

Animation
List of Pose : mPoses (integrity needs to be checked
for integrity after deleting a Pose[2])
List of Interp: mInterps (or stored as { Pose, Interp } pairs)

Interp
Tree of Bezier : mTree (same structure as Character.sSkeleton[1])


My original problem can be seen more easily here, labelled [1] and [2].


Regards,
Darren
 
C

Chris Theis

Darren said:
X-No-Archive

Hi Chris,

Thanks for the reply. Actually the whole tool caters just for the
animation of one character.

When you say 'declare the poses in relative numbers', do you mean the
angles of each joint? I just realised I made a mistake in my original
description - the skeleton is described by a tree of Lengths (ints) -
not vectors, so there's no 'original pose' to model the Poses on.

Imagine an 'Edit view', where an artist will model the skeleton with a
scratchpad-esque form where the joints may be freely rotated and
reshaped. Poses are done after this, in the 'Pose view', by dragging
the joints around, for example into a couple of 'Walk' poses.

Finally in the 'Animate view' poses will be dragged from the 'Poses
palette' into an 'Animation graph', for instance the 4 walk Poses will
be dragged into the correct order to form a walk animation. A 'Start
walking' animation may end with the same Pose that the 'Walking'
animation starts with (allowing 'Start walking' to segue into
'Walking').

Good idea to use the observer - but given that there is only one
Character in the system, I'm thinking it's probably overkill.

The Interpolations themselves do not need to know of the Poses they
interpolate between - they simply control the speed of each joint's
interpolation between two keyframes during rendering.


So, I've got the four classes:

Character
Tree of Integer: static sSkeleton
(each nodes delegates to Integer Length)

Pose
Tree of Integer: mKeyFrame
(same structure as Character.sSkeleton[1],
each node delegates to Integer Angle)

Animation
List of Pose : mPoses (integrity needs to be checked
for integrity after deleting a Pose[2])
List of Interp: mInterps (or stored as { Pose, Interp } pairs)

Interp
Tree of Bezier : mTree (same structure as Character.sSkeleton[1])


My original problem can be seen more easily here, labelled [1] and [2].


Regards,
Darren

Hi Darren,

if you only have one character the observer might indeed be an overkill.
However, I don't quite understand the way you model the character just
by lengths. A skeleton/pose would normally be described by a number of
entities. These entities themselves are described by an object matrix
(the usual 4x4 matrices used in computer graphics) that contains the
information of the position and the rotation of the entity. All
positions and rotations are of course relative to the origin of the
character.

The character naturally would naturally contain a container of available
poses and these in turn contain a collection of the entities making up
this pose.

e.g.:

class CCharacter {
vector<CPoses*> m_Poses;
CMatrix m_Position; // global pos of the character
}

class CEntity {
int Length; // add further skeleton data...
CMatrix m_ObjMatrix; // position of this entity within the
// skeleton
};

class CPoses {
vector<CEntity> m_PoseData;
};

class CKeyFrame {
CPose* m_pStartPose;
CPose* m_pEndPose;
CInterpolator m_Interpolator;
};

class CAnimation {
vector<CKeyFrame> m_AnimData;
};


To keep the integrity of your system in case you will allow to really
remove poses from the character you'd either have to check in CKeyFrame
if the pointer to the poses are still valid, or have the poses keep a
list of all keyframes they are used in.

HTH
Chris
 
D

Darren

Hi Chris,

There's no external model file - the character is modelled by a tree
structure, eg

torso
/ \
l.arm r.arm
/ \
l.forearm r.forearm

or whatever. Each of these has a length.

Additionally there are Poses which give each joint or limb a rotation.

A solution I'm starting to use is on a cross-posting;
http://groups-beta.google.com/group...185fa448975/a133c56fe2770441#a133c56fe2770441

Cheers,
Darren

Chris said:
Darren said:
Hi Chris,

Thanks for the reply. Actually the whole tool caters just for the
animation of one character.

When you say 'declare the poses in relative numbers', do you mean the
angles of each joint? I just realised I made a mistake in my original
description - the skeleton is described by a tree of Lengths (ints) -
not vectors, so there's no 'original pose' to model the Poses on.

Imagine an 'Edit view', where an artist will model the skeleton with a
scratchpad-esque form where the joints may be freely rotated and
reshaped. Poses are done after this, in the 'Pose view', by dragging
the joints around, for example into a couple of 'Walk' poses.

Finally in the 'Animate view' poses will be dragged from the 'Poses
palette' into an 'Animation graph', for instance the 4 walk Poses will
be dragged into the correct order to form a walk animation. A 'Start
walking' animation may end with the same Pose that the 'Walking'
animation starts with (allowing 'Start walking' to segue into
'Walking').

Good idea to use the observer - but given that there is only one
Character in the system, I'm thinking it's probably overkill.

The Interpolations themselves do not need to know of the Poses they
interpolate between - they simply control the speed of each joint's
interpolation between two keyframes during rendering.


So, I've got the four classes:

Character
Tree of Integer: static sSkeleton
(each nodes delegates to Integer Length)

Pose
Tree of Integer: mKeyFrame
(same structure as Character.sSkeleton[1],
each node delegates to Integer Angle)

Animation
List of Pose : mPoses (integrity needs to be checked
for integrity after deleting a Pose[2])
List of Interp: mInterps (or stored as { Pose, Interp } pairs)

Interp
Tree of Bezier : mTree (same structure as Character.sSkeleton[1])


My original problem can be seen more easily here, labelled [1] and [2].


Regards,
Darren

Hi Darren,

if you only have one character the observer might indeed be an overkill.
However, I don't quite understand the way you model the character just
by lengths. A skeleton/pose would normally be described by a number of
entities. These entities themselves are described by an object matrix
(the usual 4x4 matrices used in computer graphics) that contains the
information of the position and the rotation of the entity. All
positions and rotations are of course relative to the origin of the
character.

The character naturally would naturally contain a container of available
poses and these in turn contain a collection of the entities making up
this pose.

e.g.:

class CCharacter {
vector<CPoses*> m_Poses;
CMatrix m_Position; // global pos of the character
}

class CEntity {
int Length; // add further skeleton data...
CMatrix m_ObjMatrix; // position of this entity within the
// skeleton
};

class CPoses {
vector<CEntity> m_PoseData;
};

class CKeyFrame {
CPose* m_pStartPose;
CPose* m_pEndPose;
CInterpolator m_Interpolator;
};

class CAnimation {
vector<CKeyFrame> m_AnimData;
};


To keep the integrity of your system in case you will allow to really
remove poses from the character you'd either have to check in CKeyFrame
if the pointer to the poses are still valid, or have the poses keep a
list of all keyframes they are used in.

HTH
Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top