How can I move the character's real position along with its animation

Hi

I wanted to make the mesh move along with the animation, so that at the end of the animation the position of the mesh will be where I see it, not at 000 or at its beginning position.



I managed to make the mesh follow the animation, but as in video there are some issue which I am not so sure why.

http://www.youtube.com/watch?v=6jImSWUzvMc



if I let the blend time like default (which I think is 0)
then the mesh will fly forward/backward depend on which key I press then slowly change to real animation.
if I let the blend time be 0.01f like in second half of video then the animation is like what I desire but then I get some glitch/flick
are there anyway to get rid of that flick ? what could be the reason and how can I solve it ?


here is my whole code, I can also upload the packed jar file + blender file, but I dont know how to upload attachment here in this new forum.
[java]
package position;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.animation.LoopMode;
import com.jme3.animation.Skeleton;
import com.jme3.app.SimpleApplication;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;

public class main extends SimpleApplication implements AnimEventListener,ActionListener{
Spatial mesh,position,positionCenter;
Node positionNode=new Node("positionNode");
AnimControl animcontrol;
AnimChannel animChannel;
Skeleton skeleton;

boolean left,right,move,continous;
@Override
public void simpleInitApp() {
flyCam.setEnabled(false);
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-10f, -70f, -10).normalizeLocal());
rootNode.addLight(sun);
cam.setLocation(new Vector3f(0, 50, 150));
cam.lookAt(new Vector3f(0, 0, 0), Vector3f.UNIT_Y);
initKeys();

//create Materials and ISO box
Material blue = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
blue.setColor("m_Color", ColorRGBA.Blue);
Material red = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
red.setColor("m_Color", ColorRGBA.Red);
Material lightgray = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
lightgray.setColor("m_Color", ColorRGBA.LightGray);
Material orange = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
orange.setColor("m_Color", ColorRGBA.Orange);
Material green = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");
green.setColor("m_Color", ColorRGBA.Green);
Box b = new Box(Vector3f.ZERO, 1, 1, 1);

positionCenter = new Geometry("positionCenter", b); positionCenter.setMaterial(red);
position = new Geometry("position", b); position.setMaterial(green);

//create positionNode
positionNode.attachChild(positionCenter);
positionNode.attachChild(position);

mesh=assetManager.loadModel("position/Cylinder.mesh.xml");
mesh.lookAt(new Vector3f(1,0,0), Vector3f.UNIT_Y);
positionNode.lookAt(new Vector3f(1,0,0), Vector3f.UNIT_Y);
animcontrol=(AnimControl) mesh.getControl(0);
animcontrol.addListener(this);
animChannel=animcontrol.createChannel();
skeleton=animcontrol.getSkeleton();
rootNode.attachChild(mesh);
rootNode.attachChild(positionNode);


}
private void initKeys() {
inputManager.addMapping("left", new KeyTrigger(keyInput.KEY_LEFT));
inputManager.addMapping("right", new KeyTrigger(keyInput.KEY_RIGHT));
inputManager.addListener(this, new String[]{"left","right"});
}
@Override
public void simpleUpdate(float tpf) {
combo();
if (move) {
positionCenter.setLocalTranslation(skeleton.getBone("master").getModelSpacePosition());
position.setLocalTranslation(positionCenter.getLocalTranslation().add(skeleton.getBone("position").getModelSpacePosition()));
mesh.setLocalTranslation(position.getWorldTranslation());
}
// cam.lookAt(mesh.getWorldTranslation(), Vector3f.UNIT_Y);
}

@Override
public void onAnimChange(AnimControl arg0, AnimChannel arg1, String arg2) { }

@Override
public void onAnimCycleDone(AnimControl control, AnimChannel channel, String name) {
continous=true;
patch();
}
protected void patch(){
positionNode.detachChild(position);
positionNode.setLocalTranslation(mesh.getWorldTranslation());
positionNode.attachChild(position);
position.setLocalTranslation(Vector3f.ZERO);
move=false;
}
public void combo(){
if (left) {
if (continous) {
continous=false;
animChannel.setAnim("back",0.01f); animChannel.setLoopMode(LoopMode.DontLoop); //animChannel.setSpeed(2);
move=true;
}
}
else if (right) {
if (continous) {
continous=false;
animChannel.setAnim("for",0.01f); animChannel.setLoopMode(LoopMode.DontLoop);// animChannel.setSpeed(2);
move=true;
}
}
}
@Override
public void onAction(String name, boolean keyPressed, float arg2) {
if (name.equals("left")) {
if (keyPressed) { left=true; continous=true;}else{ left=false; }
}
else if (name.equals("right")) {
if (keyPressed) { right=true; continous=true;}else{ right=false; }
}
}
public static void main(String[] args) {
main app = new main(); app.setShowSettings(false); app.start();
}

}

[/java]

I think the model mesh should not move with the walk cycle, you should move the model continuously instead.

@Kirill and @Normen Maybe we should update the mesh localTranslation with the position of the root bone?

1 Like

Is the bone considered inside Graphics it helps animate, or in same level as it is.



If its inside, then I would expect that I must move Graphics object (and that root bone does not move).

And because it is in the same coordinate system as vertices of mesh, so local scale does not apply on it, i think you meant it to be “inside”.

Yep each bone has a position that is the relative position to its parent bone.

For the root bone, this position is the position of the bone in the model space (relative to the model’s center).

But the root bone is the parent of every bones so if you move it all the model moves.

So from the position of the root bone in world space you can easily find the position of the model in world space. (or local space from its parent node)

nehon said:
@Kirill and @Normen Maybe we should update the mesh localTranslation with the position of the root bone?

To me that defies all logic.. Bone location is relative to model location. Period.

Well, yes but the root bone is a bit particular, because its position in model space is constant over time.

Very often it’s used as a handle to move the character around.

We will need a way to update animated character position, because it would be silly to create all animation with no translation of the character and then have to move it in the code so that the animation looks good.



however i agree that the walk cycle is different in that matter, but some animation require the character to be translated

nehon said:
but some animation require the character to be translated


not necessarily true, you can create "roaming" animations and then convert them back to treadmill type animations but it can be a time consuming pain in the arse to do correctly by hand ....especially if you do "special" stuff...........I remember with 3ds-max's biped had a function that allowed you to make physical movement animations you could then switch to a "threadmill mode"...but I think that was linked to the foot-step system though

Yes but its the mesh moving, not the spatial.

mcbeth said:
but it can be a time consuming pain in the arse to do correctly by hand ....

Yeah and that can be a lot more painful by code

normen said:
Yes but its the mesh moving, not the spatial.

Yeah but, the mesh is not attached to the geometry by a hierarchical link, like node are linked between them, in the concept the geometry is the mesh or else we would just attach a mesh to a Node..., so what I would found logical is that the position of a geometry is where you expect it to be : where you see it.

Two concrete examples :
- If you use an animation that moves the mesh, and use a chase cam, the chase cam looses track of the mesh because it stares at the worldTranslation of the attached Spatial.

- The ragdoll...when it falls or is blown away by a bomb control (for example :D)....the chase cam looses track of it. And by the way, the character can be anywhere in the scene because his movements can be unpredictable when it involve physics (even if bullet seems to be deterministic). I guess you can retrieve its position in the physic space, but that's seems a bit convoluted.

It would not work with physics for example. I expect an AnimControl to only modify the mesh…

nehon:

what would happen, if geometry (for simplicity attached to rootNode) has local scale eg. (0.5, 1, 2) and I move root bone from (0,0,0) to (1,1,1).

Alpedar said:
nehon:
what would happen, if geometry (for simplicity attached to rootNode) has local scale eg. (0.5, 1, 2) and I move root bone from (0,0,0) to (1,1,1).

well..it would be moved to (1,1,1)

@Xieu90 we talk about that a lot yesterday evening with Normen, and we are thinking of making some changes on animControl.
Some kind of flag that would allow it to update the position of the spatial when user decide to set it to true.
But this not clearly defined yet, so i guess for now you should make your walking cycle stay in place like some moon walk,and make your character go forward/backward in JME via code.

@nehon

I saw you guys talk a lot about that and it became quite hot too ^^

first, here is the packed jar file http://xieu90.webs.com/position.jar and blender file of model http://xieu90.webs.com/position.blend



But this not clearly defined yet, so i guess for now you should make your walking cycle stay in place like some moon walk,and make your character go forward/backward in JME via code. like in this video? → http://www.youtube.com/watch?v=M8H0WOppaDo



I managed to make it some months ago.

that one is quite easy to make and good too, but only if my character goes in straight lines → good for games like this ugly bomber ant^^

what if I move like this ~? coding that line will be impossible for me, even if possible I wont have the desire to make it

long ago Momoko_Fan told me about using bone, a position bone if I remember well, unluckily I cant find that thread any more since the new forum came out.



Some kind of flag that would allow it to update the position of the spatial when user decide to set it to true. That is a nice idea and I think I have it too. if you comment the code file in packed jar from line 79-83 then the mesh wont move just do the moonwalk. did you mean something like that ?



I think it would be a bit better if user can define to which bone’s position should the spatial be.

http://www.youtube.com/watch?v=1lu61s4ufbM



the red cube is the master bone = rootbone (in blender)

the green one is the position bone , child of master (in blender)

and my mesh’s world position is set to the green’s world position

Pseudo-code:

[java]if(upButtonDown){

spatial.move(0,0,10*tpf);

}[/java]

1 Like