|
Alex Bogartz, Sr. Member
Posted: 07 December 2011 06:55 PM Total Posts: 216
I’m very confused by this, but maybe someone can help?
I have an MD5 animation with a series of bones. What I’d like to do is track something along with a particular bone. In this case, I’d like to track a sphere along with the bone called “hand_R”, which is the right hand, to simulate a throwing of a ball before I add the sphere to the physics world.
In the mesh class, I see:
mesh.animationState.skeleton.joints. Joints is an array of SkeletonJoint
In SkeletonJoint.as, I can see my joint by name, but it only has the name and the inverseBindPose, not a position. So, knowing the position of my model, which joint I want to use, etc, how in the world do I get from that a Vector3D that will be its position in the scene?
Any help would be greatly appreciated!
|
Alex Bogartz, Sr. Member
Posted: 07 December 2011 08:48 PM Total Posts: 216
[ # 1 ]
I found some possible leads so I thought I’d share it here.
You can get the index of the joint in question by making the skeleton property public in SkeletonAnimationState.as
public function get skeleton():Skeleton { return _skeleton; }
Then you can get the index from the onLoadComplete function:
var skeleton:Skeleton = SkeletonAnimationState(characterMesh.animationState).skeleton; handIndex = skeleton.jointIndexFromName("hand_R");
Then I’m trying to offset the ball to track the hand. This is where I’m not getting meaningful numbers.
if(characterMesh){ if (!ball) { ball = new Sphere(null,20); ball.material = new ColorMaterial(0xFF0000); } if (SkeletonAnimationState(characterMesh.animationState).globalPose.jointPoses.length > 0) { var trans:Matrix3D = SkeletonAnimationState(characterMesh.animationState).globalPose.jointPoses[handIndex].toMatrix3D(); var pos:Vector3D = trans.position; ball.position = new Vector3D(characterMesh.position.x+pos.x,characterMesh.position.y+pos.y,characterMesh.position.z+pos.z);// toMatrix3D();
} }
So, pos is returning some really small numbers. Not big enough to track the actual position of the hands. Does this make sense to anyone?
|
theMightyAtom, Sr. Member
Posted: 08 December 2011 07:31 PM Total Posts: 669
[ # 2 ]
|
Alex Bogartz, Sr. Member
Posted: 08 December 2011 09:47 PM Total Posts: 216
[ # 3 ]
Thanks! I’ve been looking at your tutorial, but I’m running into a snag.
I have my mesh loaded, but I can’t seem to add any submesh to it as per your example.
ballHolder = new Loader3D(); ballHolder.addEventListener(LoaderEvent.RESOURCE_COMPLETE, addBallColor); characterMesh.addChild(ballHolder); ballHolder.load(new URLRequest("assets/models/ball.obj"),null, "ball") //even tried just adding a sphere to the mesh //characterMesh.addChild(new Sphere(redMaterial, 5000)); characterMesh.scale(300);
So even just adding a sphere to the mesh won’t make it appear. I made a ball in Blender as an obj, but that won’t appear either. Are you sure calling “addChild” to an imported mesh will work? Is there something I’m missing?
|
Alex Bogartz, Sr. Member
Posted: 08 December 2011 10:48 PM Total Posts: 216
[ # 4 ]
Ok, solved this!
Here’s what I did wrong in case anyone else runs into the issue. See how I’m scaling my MD5 character? When you add an object to a mesh, it scales that object up as well. So my sphere (ball) was being scaled so large it wasn’t displaying. The solution was a single line:
sphere.scale(0.0033);
That should be 1/whatever the scale is.
So my new code is something like:
ballHolder = new ObjectContainer3D(); var sphere:Sphere=new Sphere(greenMaterial, 50,64) ballHolder.addChild(sphere) var scale:Number = 300; var reverseScale:Number = 1 / scale; sphere.scale(reverseScale); characterMesh.addChild(ballHolder) characterMesh.scale(scale);
Now, the next issue is that my hand bone is actually around the wrist, so I need to add another bone to sit in the right place to look like he’s holding it instead of wearing it like a bracelet. But it’s almost there. Many thanks!
|
aivanoff, Newbie
Posted: 28 October 2014 02:25 PM Total Posts: 3
[ # 5 ]
Hello everybody!
I am trying to adapt the code above to version 4.1:
var am:SkeletonAnimator = (meshes.animator as SkeletonAnimator); var idx:int = am.skeleton.jointIndexFromName("rhand");
ball.transform = (am.activeState as SkeletonClipState)
.currentPose.jointPoses[idx].toMatrix3D();
But the ball just moved a little from it’s origin in 0,0,0 and doesn’t follow the animation. What am I doing wrong?
|
SirGordon, Newbie
Posted: 28 October 2014 04:01 PM Total Posts: 29
[ # 6 ]
Hi!
Away has changed since that time, and I’m wondering how can i get world position of a joint today.
I do it like this:
ball.transform = skeletonAnimator.globalPose.jointPoses[boneIndex].toMatrix3D();
If the ball is a child of the mesh, bone of which it’s trying to follow, it works, but that’s not my case.
This method does not take into account Mesh transformations: scale, rotations and position.
How can i get final world position of a bone?
Or even bone position in it’s parent container.
|
SirGordon, Newbie
Posted: 28 October 2014 05:51 PM Total Posts: 29
[ # 7 ]
aivanoff - 28 October 2014 02:25 PM Hello everybody!
I am trying to adapt the code above to version 4.1:
var am:SkeletonAnimator = (meshes.animator as SkeletonAnimator); var idx:int = am.skeleton.jointIndexFromName("rhand");
ball.transform = (am.activeState as SkeletonClipState)
.currentPose.jointPoses[idx].toMatrix3D();
But the ball just moved a little from it’s origin in 0,0,0 and doesn’t follow the animation. What am I doing wrong?
Hi!
Consider applying scale to your position according to scale of your mesh.
For example if your mesh is scaled to 20, try ball.position.scaleBy(20);
|
aivanoff, Newbie
Posted: 29 October 2014 08:25 AM Total Posts: 3
[ # 8 ]
SirGordon - 28 October 2014 05:51 PM
Consider applying scale to your position according to scale of your mesh.
Thank you for your answer SirGordon.
model.scaleX == model.scaleY == model.scaleZ == 1
The ball is not moving at all, although right hand of the model is moving. It just shifted after applying my code from its origin. Definitely the problem in not in the scaling.
The ball is a child of model, but it is not a problem to make the ball a sibling of a model.
Is there any way to find a position of bone during animation?
|
SirGordon, Newbie
Posted: 29 October 2014 08:50 AM Total Posts: 29
[ # 9 ]
aivanoff, it’s completely working in my case.
If your ball is a child of your mesh, then this should be 100% working:
onEnterFrame{ ball.position = mesh.animator.globalPose.jointPoses[boneIndex].translation; }
are you sure you are using the right boneIndex you need?
|
aivanoff, Newbie
Posted: 29 October 2014 12:44 PM Total Posts: 3
[ # 10 ]
I appreciate your help. Thanx a lot.
SirGordon - 29 October 2014 08:50 AM aivanoff, it’s completely working in my case.
If your ball is a child of your mesh, then this should be 100% working:
Found! it works for me if I add condition:
onEnterFrame{ if (am.globalPose.jointPoses.length > 0) ball.position = mesh.animator.globalPose.joinPoses[boneIndex].translation; }
At least for the first onEnterFrame the mesh.animator.globalPose is empty
But i am sure i run animation as soon as mesh is loaded and added to scene (on RESOURCE_COMPLETE). I doubt the checking of the lenght is right. What should I check here?
|
SirGordon, Newbie
Posted: 29 October 2014 12:46 PM Total Posts: 29
[ # 11 ]
i’ve ran into the same issue and i’m checking the length too. It works anyway =)
|