Skeletal
system
Upon research of current Kinematic
systems, I have found that other than common sense joint manipulation, no one
really knows what they're doing. There
are some algorithms for Inverse Kinematics, but they all have their flaws,
making them unusable to properly, let alone quickly, emulate human behavior.
I plan on using a tree/branching
structure to implement a bone system which will hopefully be easy to map
textures and meshes too. I have no
experience in this field, so I expect many flaws.
The bone
system will be joint based.
There will
be one starting, or base joint per skeleton which will serve as the root of the
system.
-This base
joint cannot be rotated.
-For humans
and other animals, it should be something like the hip or a joint on the spinal
column.
-For animals
like snakes or eels, the base joint should be the tail tip, or head. -For something like a plant, the base joint
should be the piece of the plant that intersects the ground.
-I recommend
these places because the skeletal entity can be easily visualized and rotated
in the coordinate system using this base joint.
Joint Data
-each joint
will contain the number of joints that it is attached to
-joints do
not have to be a single link
-joints will
have a joint rotation normal, which will represent the direction that the
joints attached to it go if they have a 0 for horizontal and vertical rotation
information
-the joint
will not carry information about the joints that are attached to it, but an
array that contains them.
Joints will
contain their own information about thier attachment rotation.
-i.e. the
elbow joint will contain it's horizontal and vertical rotation with respect to
the shoulder joint
-joints will
also contain rotational restrictions.
This will be used in an Inverse Kinematics system, and will prevent
impossible contortions.
-joints will
contain their distance away from their parent joint, this minimizes the amount
of data that we have to carry around and should make everything more efficient.
Drawing
-amazingly,
drawing should be recursive:
Joint::Draw
{
PushMatrix(); //return for the next child on this level
rotate the system for this.horizrot and
this.vertrot; //the system's origin should be at the parent joint normal
here...
translate the system the distance of this
joint;
actually draw this joint;
rotate the system for this.rotnormal; //do
this before drawing the children, who need the system in this rotation to draw
properly.
loop(children)
child::draw;
//when no children are left, or none to
begin with
glPopMatrix(); //return state for the next
child at this level
return;
}
-rotation
will be done using two variables, a horizontal rotation (using the y axis) and
a vertical rotation(using the x axis).
I used this type of rotation in my particle system for bilboarding and
it worked very well. With a very
minimal amount of overhead.
-some
rotating has to be done before the children are drawn to put the coord system
at the joint rotation normal for that parent joint...
-the base
joint has a rotation of zero, in fact, base joint is a subclass of joint, so
the draw function will just be overridden and changed accordingly
Let's look
at an example:
A Flower
consisting of 5 joints:
joint1
//base joint, move the coord system to the place where the flower intersects
the ground then call draw on the flower
numchildren
= 1;
children[1]
= {joint2};
//rotationnorm
= 0; //this is always straight up in the position of the system at the time of
the draw. Does this need to be changed?
joint2
//first link
numchildren
= 3; //has two leaves here and another joint above
children[3]={joint3,
joint4, joint5};
rotationnorm=(0,1,0);
//straight up, the syntax might have to be changed, depending on what's easier
in OpenGL
horzrot = 0;
//direction of the joint
vertrot = 0;
defaulthorzrot
= 0; //these will set the system back to its resting position
defaultvertrot
= 0;
distance= 5;
//arbitrary
horzmax= 90;
//this is dependant on how we define the joint, if you twist a flower stalk, it
can't go more than a quarter turn.
horzmin =
-90;
vertmax =
90;
vertmin =
-90;
//the above
are pretty good range of motions for a flower, they're believable at least for
this demonstration. With these values,
we can't have the flower spinning around on the ground using IK, which would be
impossible.
-the rest of
the joints work similarly, except the leaf horzrot and vertrot will point them
towards the side of the flower instead of straight up, something like
horzrot=90 or -90 and vertrot=70. These
will be the defaults too.
-the max and
min rotations are based on the rotated joint, so if the default is 90 above,
the real min and max would be 0 and 180 respectively.
Hopefully
this is a good enough start to begin coding.
I've tried to make it as intuitive as possible because millions of years
of evolution has probably already worked out the best way of doing Inverse and
Forward Kinematics.
I'm also
looking to extend this into mesh deformation.
If we just use polygons and draw them around the points to simulate a
body, it would work, but it would look crappy, kind of like the bodies in
FF7. Hell, like the bodies in tons of
games. If, however, we use a mesh and
make its points dependent on the rotations and positions of specific joints,
some amount of deformation will take care of itself. This would work especially well for textures, like textured skin
for instance, if you used a texture of clothing or maybe a tatooed arm instead
of using all those polygons, the texture would stay in the same place that it
should be relative to the way that the joints are positioned. This would work really well in the above
flower example, where the joints would consist of rings of verticies that would
map to a specific vertex on the ring above.
Unfortuantely, I don't know how to implement this yet.
Milestones:
implement
the joint system using GL_POINTS and GL_LINES.
This should give a nice little stick man.
Try and make
him move around with Forward Kinematics, it shouldn't look too good, but see if
it *can* look somewhat 'real'
give the
stick man some bulk with various polygons.
At least a head. For the polygon
and vertex mapping, the recursive draw method that I described above might not
work because the polygons will get split up.
It might be a good idea to have a get position function that will return
the joints coords and it's up vector.
That way a polygon mesh can draw itself in one shot as long as it knows
which vertecies are assigned to which joint.
Seems pretty advanced.
Try to give
the stick man some real shape with a polygon mesh that knows its own relation
to the joint system. Take the simple
flower example again. The ring that
makes up the bottom of the flower, knows that it is 1 unit away from the base
joint starting in the direction of (1,0,0) and continuing in a circle for 6
points. At the second joint, the ring
should be tilted at an axis equal to the current rotation of the joint. that way, one side of the polygon stretches
and the other side shrinks.
Scripting? Yea right, this project is out of control,
you can't stop it, you can only hope to contain it.
SEE YOU
AGAIN SPACE COWBOY...