[SOLVED]How to skinning a model with pure Java code?

Hi, all.
I’m learn jMonkeyEngine 3.0 source code. I have some problems learning skeleton animation.

So far I have done these work:
(1) Create a Node with three Geometry(using Box mesh)
(2) Create a Skeleton with three Bones
(3) Create an Animation with three BoneTracks, each track bind to one Bone
(4) Create an AnimControl and bind it to the Node mentioned in (1)

The skeleton and AnimControl works fine but Geometry just can’t move with bones.

Now I need to do the last step:

(5) Skinnig the model.

I read the wik page about Polygon Meshes, but confused with the Type.BoneIndex and Type.BoneWeight. I don’t understand how it works, how to bind the geometry to each bone. How to do the skinning. I never learn about skeleton animation before. :sweat:

Here is the source:

Also I write a simple test application.

1 Like

I think you need to assign weights ot the vertices, but I’m not sure how.

BoneIndex is a number of bone in skeleton, defines bones that influence vertex, contains up to 4 values per vertex if I remember correct (need to take a closer look at mesh loaders to clarify details of how it works).

BoneWeight is used to define “power” of every bone influencing vertex, useful mainly when one vertex is influenced by many bones but have to be set anyway. (again, have to look at some existing working code to clarify details)

Both buffers should have at least one value per vertex. (for me it looks like you have set it in a right way)

And I think you need skeleton control as well, not only skeleton itself and animation control.

Just wanted to say: great topic and nice code ideas!
Now I would like to work on something like this too (e.g. create a game like “Spore” in jME).
:+1:

SkeletonControl !!
I should have noticed it!

It there examples about how to use it?

Try to look into how blenderimporter does it (it’s under the jmonkey github)

1 Like

You are right.
I’m now reading the code of MeshLoader. :grinning:

1 Like

OK, now it moves!

My source code has updated, below is how I made it:
(1) set BoneIndex and BoneWeight Buffer to the mesh.
BoneIndex uses ByteBuffer, IndexCount = VertexCount * 4.
BoneWeight uses FloatBuffer, WeightCount = VertexCount * 4.

Box box = new Box(0.1f, 0.1f, 0.1f);
box.setBuffer(Type.BoneIndex, 4, createBoneIndex((byte)0));
box.setBuffer(Type.BoneWeight, 4, createBoneWeight());
box.setMaxNumWeights(4);

(2) Invoke mesh.generateBindPose(true)

box.generateBindPose(true);

(3) Create SkeletonControl and add it to Node

// Create SkeletonControl and add it to Node
SkeletonControl sc = new SkeletonControl(ac.getSkeleton());
node.addControl(sc);

cheers :relaxed:

The problem now is that: Why the Boxes didn’t moves fit the Bones?

Some other questions:
Why I have to use 4 bone indices per vertex? Why not 3, 2, 1?
Invoke mesh.generateBindPose(true) makes software animation. How to make hardware animation?

2 Likes

Try to bind boxes to nodes from bones if everything you want are separate geometries glued to bones. (using getAttachmentsNode from SkeletonControl and without any skinning)

Or you’ll have to properly arrange your objects in space and recalculate vertex coordinates (something like in world coordinates your objects should have zero offset relatively to each other and skeleton, keeping any offset only in vertex coordinates, ideally it should be single geometry containing all elements).

I tried the first way with your advise, it works fine. I’m tring the second way

(1) delete the skinning code

(2) bind boxes to nodes from bones

Whats the point in using bones when you’re effectively just using the attachment node and moving spatials with it? Just move the spatials then. Bones are for moving vertices within a mesh.

There is almost no point in it for real application, but I think it’s valuable experience for learning.

1 Like

Oh, I think you under-estimate the value of this…
Of course I would try to use the skinning code and not the attachment nodes.
Imagine that you create a “Spore” creature at runtime.
I’ve been making sketches for this since several months ago and might event give it a try now.

Using the attachment nodes - on the bones:
Might be of value if you animate the bones from a source (e.g. kinect camera).
Might make a stone-monster like in the movie Galaxy Quest with this (consisting of floating rocks).

3 Likes

Yes it realy helpful when learning animations. :smiley:
And I think I can use the attachment nodes to implements 3ds max keyframe animation.

1 Like

I write a method to recalculate vertex coordiantes. Simple add a vector3f to each node.

for each box, I use this method to recalculate.

Now it works like this.

At least it moves just like the BoneAnimation. But it seems all the vertex coordnates are 3 times bigger. Maybe I calculate something wrong? :chimpanzee_lobotized:

Source on github updated.
@see CraeteAnimation

Besides, I add new classes to test the first way prog said.
@see CreateAnimation2

1 Like

You should recalculate any scaling as well. And sync starting positions of vertices with starting positions of bones.

Oh, wait, I’m not sure you have to mark every vertex as influenced 4 times with the same bone on full power.
Try giving 1 weight only to first entry per bone. Like this:

    for(int i=0; i<24*4; i+=4) {
        boneWeight[i] = 1;
        boneWeight[i+1] = 0;
        boneWeight[i+2] = 0;
        boneWeight[i+3] = 0;
    }

Yes, you are right. I just find this bug. :chimpanzee_closedlaugh:

Thank you, the animation works perfect for me now.

2 Likes

Thank you monkeys! I learned so much about skeleton animation. :grin:
It’s 2:16 AM in China, I think I can have a good sleep now.

Problem solved.

1 Like

Another application I can think of could be creating characters procedurally with different clothes, armor, helmet, capes, whatever, and then batching it all to have one geometry instead of 20.

Thanks Yan! I’ll try it sometime.