I am restoring my project using Gradle Ran into some problems with bullet physics and view Direction

@Override
    public void update(float tpf) {
        camDir.set(cam.getDirection().mult(1f));
        camLeft.set(cam.getLeft().mult(1f));
        walkDirection.set(0, 0, 0);
       
        camDir.y = 0;
        camLeft.y = 0;
        //System.err.println(camDir.y+","+camLeft.y);
        //viewDirection.set(camDir);
        // 计算运动方向
        boolean changed = false;
        if(up){
            viewDirection.addLocal(camDir);
            walkDirection.addLocal(camDir);
            //player.setViewDirection(camDir);
             changed = true;
        //model.setLocalScale(camDir);
        }else if(down){
           viewDirection.addLocal(camDir.negate());
           walkDirection.addLocal(camDir.negate());
           //player.setViewDirection(camDir.negate());
        changed = true;
        }else if(left){
            viewDirection.addLocal(camLeft);
            walkDirection.addLocal(camLeft);
            //player.setViewDirection(camLeft);
          changed = true;
        }else if(right){
            viewDirection.addLocal(camLeft.negate());
            walkDirection.addLocal(camLeft.negate());
            //player.setViewDirection(camLeft.negate());
             changed = true;
        }else if(changed){
            //viewDirection.y = 0.0f;// 将行走速度的方向限制在水平面上。
            //viewDirection.normalizeLocal();// 向量标准化
            viewDirection.mult(50f);// 改变速率
            //walkDirection.y = 0;// 将行走速度的方向限制在水平面上。
            walkDirection.normalizeLocal();// 向量标准化
            walkDirection.multLocal(0.53f);// 改变速率
        }
        
        player.setWalkDirection(walkDirection);
        player.setViewDirection(viewDirection);
   
    }

I use viewDirection to control the character orientation,
But the character turns slowly while moving,

As you can see from the video, the model turns very slowly,
I guess I used the setViewDirection method incorrectly but I read the documentation and I didn’t see what the problem was, right

viewDirection.mult(50f);// 改变速率

Using this function to control the rotation rate, maybe my is wrong…

I thought maybe I could use some interpolation to control the turn instead of using setViewDirection

99% sure that view direction is an actual direction and so must be length 1.

Yours is probably some really strange value given how you are constructing it so you might try normalizing it at the end. Or just set it to a normalized version of walkDirection since it seems like you want them to point the same way.

Edit: and note that I don’t know if that’s the real issue… but it’s definitely an issue and so you might as well fix it to see if it solves the reported problem.

2 Likes
//player.setViewDirection(camDir);
//player.setViewDirection(camDir.negate());
//player.setViewDirection(camLeft);
//player.setViewDirection(camLeft.negate());

I just uncomment and run it to say how do I want the character to move,
And you can see from the video that I want the character to move forward and backward and left and right based on the vector of the current camera.

Your reply reminds me that maybe there is no interpolation in ViewDirection itself (at least I didn’t find it in the documentation) ,
Is there a wrapped interpolation formula in jme?

Is there a wrapped interpolation formula in jme?

jme3-core provides 2 methods for interpolating vectors:

When interpolating direction vectors, always normalize the result afterward.

1 Like

Thank you for reminding me.
I didn’t find this function while browsing the documentation.
Thank you very much for your help

1 Like

However, interpolating a vector may do some weird things when one direction is 180 degrees from the other.

For 2D directions like this, it is quite common to keep the angle and derive the direction vector from that. Interpolating one angle to another one is relatively straight forward (still have to deal with 0/360 wrapping but the math is straight forward otherwise).

…and it’s pretty easy to go from angle (in radians) back to direction.

2 Likes

image

5月 15, 2023 9:38:29 上午 com.jme3.app.LegacyApplication handleError
严重: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalArgumentException: direction must not be zero.
	at jme3utilities.Validate.nonZero(Validate.java:800)
	at com.jme3.bullet.control.CharacterControl.setViewDirection(CharacterControl.java:204)
	at movement.MinieMovementControl.update(MinieMovementControl.java:151)
	at com.jme3.app.state.AppStateManager.update(AppStateManager.java:371)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:258)
	at com.jme3.system.lwjgl.LwjglWindow.runLoop(LwjglWindow.java:622)
	at com.jme3.system.lwjgl.LwjglWindow.run(LwjglWindow.java:711)
	at java.base/java.lang.Thread.run(Thread.java:833)

This is the problem with my 180 degree rotation.
I tried many times,A 180 degree rotation might cause the direction to return to zero.


When I press D key, I don’t know why the number suddenly goes to 0.
right Under normal conditions, it should be (-0.62929547, 0,-0.7771661),Instead of zero

    @Override
    public void update(float tpf) {
        camDir.set(cam.getDirection().mult(1f));
        camLeft.set(cam.getLeft().mult(1f));
        walkDirection.set(0, 0, 0);
       
        camDir.y = 0;
        camLeft.y = 0;
        //System.err.println(camDir.y+","+camLeft.y);
        //viewDirection.set(camDir);
        // 计算运动方向
        
        boolean changed = false;
        if(up){

     
            //viewDirection.addLocal(camDir);
            walkDirection.addLocal(camDir);
            
            viewDirection.interpolateLocal(viewDirection, camDir, 0.5f);
            //viewDirection.addLocal(camDir);
             //player.setWalkDirection(walkDirection);
            changed = true;
        //model.setLocalScale(camDir);
        }else if(down){
           //viewDirection.addLocal(camDir.negate());
           walkDirection.addLocal(camDir.negate());
         viewDirection.interpolateLocal(viewDirection, camDir.negate(), 0.5f);
           // player.setViewDirection(camDir.negate());
        changed = true;
        }else if(left){
            //viewDirection.addLocal(camLeft);
            walkDirection.addLocal(camLeft);
            viewDirection.interpolateLocal(viewDirection, camLeft, 0.5f);
            //player.setViewDirection(camLeft);
          changed = true;
        }else if(right){
            //viewDirection.addLocal(camLeft.negate());
            walkDirection.addLocal(camLeft.negate());
            viewDirection.interpolateLocal(viewDirection, camLeft.negate(), 0.5f);
            //player.setViewDirection(camLeft.negate());
             changed = true;
        }else if(changed){
            //viewDirection.y = 0.0f;// 将行走速度的方向限制在水平面上。
            //viewDirection.normalizeLocal();// 向量标准化
           //viewDirection.mult(500f);// 改变速率
            //walkDirection.y = 0;// 将行走速度的方向限制在水平面上。
           //walkDirection.normalizeLocal();// 向量标准化
            //walkDirection.multLocal(0.53f);// 改变速率
        }
        
        player.setWalkDirection(walkDirection);

      System.err.println(viewDirection);
      player.setViewDirection(viewDirection);
    }

I checked my code but couldn’t find a place to make it zero

For example, interpolating halfway between (1, 0, 0) and (-1, 0, 0) == (0, 0, 0)

…that’s one big problem with interpolating directions instead of angles.

The other is that linear interpolation will not smoothly interpolate the angle so there will be some speed up and slow down at odd times in the arc.

1 Like

I found some articles and read some tutorials.

It seems that I need to use quaternions to solve the problem.

targetQua.slerp((simpleApp.getRootNode().getChild("model")).getLocalTransform().getRotation(), cam.getRotation(), tpf);

viewDirection.set(targetQua.mult(viewDirection));

I take the current rotation state of the character and the rotation state of the camera (because the rotation state of the camera is the final rotation state) and interpolate.
I don’t know what I missed.

I used the code above and the end result looks something like this.