how to use JointPose

Software: Away3D 4.x

milien, Newbie
Posted: 19 July 2012 10:03 AM   Total Posts: 11

how to use JointPose?

I want to control the bone move and rotation.

   

Richard Olsson, Administrator
Posted: 19 July 2012 11:29 AM   Total Posts: 1192   [ # 1 ]

The most reliable way would be to create a class that implements ISkeletonAnimationNode and apply whatever you logic you want in there to modify the poses of the joints (within a SkeletonPose instance.)

You can then create an animation state with that joint as the root joint, and “play” that state through an animator. To do that, add the state to an animation set and add the state to that. Create your animator referencing that set, and play the state by invoking the play() method, passing in it’s name.

If you need to update just a single joint and let the rest of the skeleton be controlled, for example, by a pre-recorded animation sequence (using a “clip node”)  you can create a node that just changes that one joint pose and then blend the two using a SkeletonDifferenceNode. Set the two inputs of that node to the clip node and your bespoke node respectively, and then use the difference-node as the root for your animation state.

 

   

milien, Newbie
Posted: 19 July 2012 11:50 AM   Total Posts: 11   [ # 2 ]

if I want to make a doll, and I can move its hands and legs.

how to do?

 

   

Richard Olsson, Administrator
Posted: 19 July 2012 11:54 AM   Total Posts: 1192   [ # 3 ]

I’m not entirely sure on what level you are asking this question. Do you want to know how to control a skeleton in Away3D, or do you want to know how to have something (anything) follow the mouse in 3D space?

If you want to control a skeleton using the Away3D animation system, you need to do what I’m describing above. It sounds like you only need to control it yourself, without need for pre-recorded animation, and in that case you don’t need any of the blend nodes I referred to above.

All you need to do is create a class that implement ISkeletonAnimationNode and calculates the position and orientation of your skeleton based on whatever logic you want, e.g. mouse position.

Then add that node as the root node for a new SkeletonAnimationState, add that state to a SkeletonAnimationSet, and play the state (by name) from that set using a SkeletonAnimator.

 

   

milien, Newbie
Posted: 19 July 2012 12:50 PM   Total Posts: 11   [ # 4 ]
import org.papervision3d.view.BasicView;
import org.papervision3d.objects.parsers.DAE;

var 
view:BasicView = new BasicView(00true);
var 
boneTest:DAE = new DAE();

boneTest.load('xxxxx.DAE');
boneTest.scale 10;
boneTest.yaw(45);
boneTest.roll(45);

stage.addChild(view);

view.scene.addChild(boneTest);
view.viewport.addEventListener(Event.ENTER_FRAMErun);

function 
run(e:Event):void
{
boneTest
.getChildByName("COLLADA_Scene").getChildByName("Bone01").getChildByName("Bone02").yaw(2);
view.startRendering();

in papervision3d, I can control bone like above.  But I don’t know how to do it in Away3D.  It not use getChildByName, how to get the “Bone01”?

 

   

Richard Olsson, Administrator
Posted: 19 July 2012 01:03 PM   Total Posts: 1192   [ # 5 ]

The animation system in Away3D is a lot more sophisticated (and therefor a little bit more complex) than that. First of all, the skeleton and it’s posed are separated, so that the skeleton can be used for several meshes that at any given point in time have separate poses.

Second, the animators, which are the classes that modify the geometry (through AS3 or by creating a shader that does it on the GPU) needs to be fed the pose by querying the active “state” for a SkeletonPose instance.

The state in turn returns it from it’s root node, and the node architecture is there to allow blending poses together.

Since you don’t require blending, all you need to do is create a new node type, as I’ve explained above, and in it’s getSkeletonPose() method return a SkeletonPose instance with all the joint poses updated to reflect the pose you want the skeleton to be in. Use the translation and orientation properties on all of the JointPose instances to position each joint.

To get it by name, use the jointPoseFromName() method on SkeletonPose.

 

   

milien, Newbie
Posted: 19 July 2012 01:14 PM   Total Posts: 11   [ # 6 ]

Thank you. I am trying.

 

   

Richard Olsson, Administrator
Posted: 19 July 2012 01:16 PM   Total Posts: 1192   [ # 7 ]

Great! Let us know how it goes!

 

   

milien, Newbie
Posted: 20 July 2012 11:44 AM   Total Posts: 11   [ # 8 ]

Hi,Richard

I don’t know how to translate the type of value from Loader3D to Skeleton?

These code is modified from the Sample of a vase “gettingStartedWithAway3D”.

The commentaries are wrong. Can you tell me how to modify it?

package
{
 import away3d
.containers.View3D;
 
import away3d.events.LoaderEvent;
 
import away3d.loaders.Loader3D;
 
import away3d.loaders.parsers.*;
 
import away3d.controllers.*;
 
import away3d.cameras.*;
 
import away3d.animators.data.*;
 
import away3d.animators.nodes.*;
 
import away3d.library.*;
 
 
import flash.display.Sprite;
 
import flash.events.Event;
 
import flash.net.URLRequest;
 
 
[SWF(width="960"height="540")]
 
public class guge extends Sprite
 {
  
private var _view View3D;
  private var 
_loader Loader3D;
  private var 
_ISkeletonAnimationNode:ISkeletonAnimationNode;
  private var 
_BoneMeshSkeletonPose;
  private var 
_Bone001Skeleton;
  private var 
_Bone002JointPose;
  

  public function 
guge()
  
{
   _view 
= new View3D();
   
_view.backgroundColor 0x666666;
   
_view.antiAlias 4;
   
_view.camera.100;
   
   
this.addChild(_view);
   
this.addEventListener(Event.ENTER_FRAMEonEnterFrame);
   
   
Parsers.enableAllBundled();
   
   
_loader = new Loader3D();
   
_loader.addEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_loader.addEventListener(LoaderEvent.LOAD_ERRORonLoadError);
   
_loader.load( new URLRequest('../2guge.md5mesh') );  // this mesh has two bones: Bone001, Bone002
   
   // here is error
   //_BoneMesh = _loader as SkeletonPose;
   //_Bone001 = _ISkeletonAnimationNode.getSkeletonPose(_BoneMesh);
   //_Bone002 = _Bone001.jointPoseFromName("Bone002");
   //_Bone002.rotationX = 15;
   
  
}
  
  
  
private function onResourceComplete(ev LoaderEvent) : void
  {
   _loader
.removeEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_loader.removeEventListener(LoaderEvent.LOAD_ERRORonLoadError);
   
_view.scene.addChild(_loader);
   
  
}
  
  
  
private function onLoadError(ev LoaderEvent) : void
  {
   trace
('Could not find'ev.url);
   
_loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_loader.removeEventListener(LoaderEvent.LOAD_ERRORonLoadError);
   
_loader null;
  
}
  
  
  
private function onEnterFrame(ev Event) : void
  {
   _loader
.rotationY stage.mouseX stage.stageWidth/2;
   
_view.camera.* (stage.mouseY stage.stageHeight/2);
   
_view.camera.lookAt(_loader.position);
   
_view.render();
  
}
 }

 

   

Richard Olsson, Administrator
Posted: 20 July 2012 11:55 AM   Total Posts: 1192   [ # 9 ]

Listen for the SKELETON_COMPLETE event and get the skeleton through that. That will give you the first type of representation of a skeleton, i.e. the skeleton itself in it’s bind pose. That’s not the one you want to modify.

The poses themselves should be created by you (or, when you’re dealing with pre-recorded video, by the parser that interprets that data.) So after you have retrieved the skeleton, create a SkeletonPose and add two joint poses (that will map to the two joints in your skeleton.)

Then look at the Intermediate_MD5Animation for how to set up animation using animators, animation sets and animation states. You will have to create the state yourself, using a root node that you also have to create yourself, and in that node you should put your logic for modifying the joint pose instances.

 

   

milien, Newbie
Posted: 21 July 2012 08:37 AM   Total Posts: 11   [ # 10 ]

Hi, Richard , thank you for your help very much.

I meet another problem.

why I changed the JointPose’s orientation and translation, but it isn’t changed in the view?

look at the comment code

package
{
 import away3d
.containers.View3D;
 
import away3d.events.LoaderEvent;
 
import away3d.events.AssetEvent;
 
import away3d.loaders.Loader3D;
 
import away3d.loaders.parsers.*;
 
import away3d.controllers.*;
 
import away3d.cameras.*;
 
import away3d.animators.data.*;
 
import away3d.animators.nodes.*;
 
import away3d.library.*;
 
import away3d.core.math.*;
 
import away3d.debug.Trident;
 
 
import flash.display.Sprite;
 
import flash.events.Event;
 
import flash.net.URLRequest;
 
import away3d.animators.SkeletonAnimationState;
 
import away3d.containers.Scene3D;
 
 
[SWF(width="960"height="540")]
 
public class guge extends Sprite
 {
  
private var _view View3D;
  private var 
_loader Loader3D;
  private var 
_BoneMeshSkeletonPose;
  private var 
_Bone001Skeleton;
  private var 
_Bone002JointPose;

  
  public function 
guge()
  
{
   _view 
= new View3D();
   
_view.backgroundColor 0x666666;
   
_view.antiAlias 4;
   
_view.camera.100;
   
this.addChild(_view);
   
this.addEventListener(Event.ENTER_FRAMEonEnterFrame);
   
   
Parsers.enableAllBundled();
   
   
_loader = new Loader3D();
   
_loader.addEventListener(AssetEvent.ASSET_COMPLETEonAssetComplete);
   
_loader.addEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_loader.addEventListener(LoaderEvent.LOAD_ERRORonLoadError);
   
_loader.load( new URLRequest('../2guge.awd') );  // this mesh has two bones: Bone001, Bone002
  
}
  
  
private function onAssetComplete(event:AssetEvent):void
  {
   
if (event.asset.assetType == "skeletonPose"{
    _BoneMesh 
event.asset as SkeletonPose;
    
_Bone002 _BoneMesh.jointPoses[0];
    
trace(_Bone002.orientation);
    
trace(_Bone002.translation);
    
//_Bone002.orientation.multiply(_Bone002.orientation,new Quaternion(0,0.1,0,1));
    //_Bone002.translation.y += 100;
    
trace(_Bone002.orientation);
    
trace(_Bone002.translation);
   
}
   
  }
  
  
  
private function onResourceComplete(ev LoaderEvent) : void
  {
   _loader
.removeEventListener(AssetEvent.ASSET_COMPLETEonAssetComplete);
   
_loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_loader.removeEventListener(LoaderEvent.LOAD_ERRORonLoadError);
   var 
_axis = new Trident(40,true);
   
_loader.addChild(_axis);
   
_view.scene.addChild(_loader);
  
}
  
  
  
private function onLoadError(ev LoaderEvent) : void
  {
   trace
('Could not find'ev.url);
   
_loader.removeEventListener(AssetEvent.ASSET_COMPLETEonAssetComplete);
   
_loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETEonResourceComplete);
   
_loader.removeEventListener(LoaderEvent.LOAD_ERRORonLoadError);
   
_loader null;
  
}
  
  
  
private function onEnterFrame(ev Event) : void
  {
   _loader
.rotationY stage.mouseX stage.stageWidth/2;
   
_view.camera.* (stage.mouseY stage.stageHeight/2);
   
_view.camera.lookAt(_loader.position);
   
_view.render();
  
}
 }

 

   

Richard Olsson, Administrator
Posted: 21 July 2012 09:54 AM   Total Posts: 1192   [ # 11 ]

Do you want to use pre-recorded animation or not? It sounded like you only need to use procedural animation (e.g. mouse-controlled) but in your code above you seem to be loading skeleton poses. That would only ever happen if the file you are loading contains pre-recorded animation.

Do this:

1) Load a skeleton and mesh (that is bound to the skeleton) from whatever file you have.

2) When the skeleton comes in, create a skeleton pose with one JointPose for each joint in the skeleton.

3) Build your own ISkeletonAnimationNode implementation that modifies poses according to whatever logic you want. Pass in the SkeletonPose to that. Modify/update and return it in your implementation of the ISkeletonAnimationNode.getSkeletonPose() method.

4) Create a SkeletonAnimationState, passing in the instance of your custom node to it as the root node.

5) Set up a skeleton animator and animation set similarly to how it’s done in Intermediate_MD5Animation.

6) Add your SkeletonAnimationState (with your custom node as the root) to the animation set and give it a name.

7) Tell the animator to play the state, by invoking play() and passing in the name you just gave it.

Those are the basic steps to creating a custom way to control a skeleton. Skeleton poses are always controlled by the nodes in a SkeletonAnimationState, and although there are several useful node, when you want completely custom logic, you have to implement your own node type.

 

   

milien, Newbie
Posted: 21 July 2012 10:37 AM   Total Posts: 11   [ # 12 ]

I use one frame to test to make a custom moving jointpose, because it is more easier.

As the jointpose does not move any more, so I have not added mouse-controlled.

I have known the procedure of play animation. thanks for your teaching.

here is my mesh file 2guge.zip

Now the problem is that the jointpose doesn’t move by changing “orientation”.  Can you write a sample code for me?  any rotating joint is OK, just let me understand how to rotate.

 

File Attachments
2guge.zip  (File Size: 22KB - Downloads: 244)
   

Richard Olsson, Administrator
Posted: 21 July 2012 10:42 AM   Total Posts: 1192   [ # 13 ]

It is important that you understand that just rotating a joint pose (as if it was any object in the scene) will not update the skeleton, nor any meshes that are bound to it. The animator is responsible for doing that, so you have to make sure that you use an animator to play your state (and thus your custom node type). The node type will tell the animator how the skeleton should be posed, but it’s the animator that actually updates the skeleton and the geometry of the mesh.

So, have you done all the steps above, including creating your own custom ISkeletonAnimationNode class, adding it to a state, and playing that state through an animator?

 

   

milien, Newbie
Posted: 29 July 2012 04:17 PM   Total Posts: 11   [ # 14 ]

how do I build my own ISkeletonAnimationNode?

I try to write some codes,but the flash player is blank. Please help me.

var _NodeISkeletonAnimationNode;
if (
event.asset.assetType == "skeleton")
{
 _Bone001 
event.asset as Skeleton;
 
_Node.getSkeletonPose(_Bone001);

 

   

Richard Olsson, Administrator
Posted: 29 July 2012 08:20 PM   Total Posts: 1192   [ # 15 ]

When I said build your own skeleton node, I meant you create a class that implements the ISkeletonAnimationNode interface. Implement the getSkeletonPose() method and return a skeleton pose that you compute in whatever way you want.

Look for example at the SkeletonClipNode and try to reproduce what it does (implement the interface, create the getSkeletonPose() method et c) but using your own logic.

 

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X