On quaternion rotation problem

I need to rotate my model,
Every time I press the w key the model turns to the direction of the camera.

 private Vector3f viewDirUP = new Vector3f(0,0,1);
targetQua.set((simpleApp.getRootNode().getChild("model")).getWorldRotation()).nlerp(cam.getRotation(), 0.1f);
           viewDirection.set(targetQua.mult(viewDirUP));
           viewDirection.setY(0);

I don’t know much about the concept of quaternions,So I don’t know if I’m doing the right thing.

Because minie CharacterControl was used,So the end result is going to be a vector.
The above code completes the interpolation rotation conversion to vectors,
I don’t know if I have any mathematical problems with this piece of code,The results look good.

I hit the “s” key, The character model should face the camera,
I got an error when I multiplied targetQua by viewDirUP.negate() and you can see the result in the video

It’s obvious that the model should be facing the camera when the back button S is pressed instead of spinning around(Here I guess I must have used the wrong parameters to cause this,But I’m not sure what).
But I found a function in javadoc Quaternion.opposite(), And then I changed the code for the S key

 private Vector3f viewDirUP = new Vector3f(0,0,1);
targetQua.set((simpleApp.getRootNode().getChild("model")).getWorldRotation().opposite()).nlerp(cam.getRotation(), 0.1f);
           viewDirection.set(targetQua.mult(viewDirUP.negate()));
           viewDirection.setY(0);

So now the S bond works pretty well,But I don’t know why…

Here’s the problem:

  • I want to know how to turn left and right?

  • And hopefully, to correct my thinking

Turn what, exactly? If you want to rotate your character’s view direction, that is done with mult or multLocal.

character.setViewDirection(
    new Quaternion(angleToRotate, Vector3f.UNIT_Y)
        .mult(character.getViewDirection()));
1 Like
           targetQua.set((simpleApp.getRootNode().getChild("model")).getWorldRotation().opposite()).nlerp(cam.getRotation(), 0.1f);
           //simpleApp.getRootNode().getChild("model").setLocalRotation(targetQua);
           viewDirection.set(targetQua.mult(viewDirUP.negate()));
           viewDirection.setY(0);

I found that I added.opposite() and then converted to v3 f as normal.This will make the backward normal instead of jitter

I would like to ask you how should I rotate the model from side to side?

targetQua.set((simpleApp.getRootNode().getChild("model")).getWorldRotation()).nlerp(cam.getRotation().fromAngleAxis(90* FastMath.DEG_TO_RAD, Vector3f.UNIT_Y), 0.1f);

.fromAngleAxis(90* FastMath.DEG_TO_RAD, Vector3f.UNIT_Y)

This is how I try,But it didn’t seem to work

I think this is what you’re looking for.

Quaternion rotation = spatial.getLocalRotation();
Vector3f direction = camera.getLocation().subtractLocal(spatial.getWorldTranslation());
direction.setY(0f).normalizeLocal();
Quaternion target = new Quaternion().lookAt(direction, Vector3f.UNIT_Y);
rotation.nlerp(target, .1f);
spatial.setLocalRotation(rotation);

Bonus: the model will face the camera regardless of the camera’s direction.

The reason your code does not work as expected is because fromAngleAxis sets the quaternion. So in essence, you are completely overwriting the camera rotation and replacing it with 90 degrees around the y axis. So I would expect targetQua to always turn to the same direction.

2 Likes

Thank you for your reply.

This reply made me understand what I should do.

Can you tell me how you finally converted quaternions into vectors?

1 Like

Where does this parameter come from?

Uh uh… What I really want to say is how do I turn this into a vector3f

rotationWhat do I multiply by to get the vector?

Multiply the vector by the quaternion.

Vector3f vec1 = ...
Quaternion quaternion = ...
Vector3f vec2 = quaternion.mult(vec1);
Quaternion   rotation = spatial.getLocalRotation();
Vector3f direction = camera.getLocation().subtractLocal(spatial.getWorldTranslation());
direction.setY(0f).normalizeLocal();
Quaternion target = new Quaternion().lookAt(direction, Vector3f.UNIT_Y);
rotation.nlerp(target, .1f);


rotation.mult(?????);


vec1=direction?

I seem to be asking a strange question , but I think you should be able to understand what I mean :sweat_smile:

I want to turn “rotation” into a vector3f.
rotation.mult(???);

Quaternions are based off the z axis, so multiply with Vector3f.UNIT_Z.

Edit: sorry, didn’t realize that was what you were confused about.

1 Like

In jMonkeyEngine, the default “look” direction or “facing” is the Z axis. Vector3f.UNIT_Z.

So any default quaternion (new Quaternion()) is considered to be “looking” down UNIT_Z until changed.

Camera looks down its local Z axis, spatials look down their local Z axis, etc…

3 Likes
 @Override
    public void update(float tpf) {
        camDir.set(cam.getDirection().mult(1f));
        camLeft.set(cam.getLeft().mult(1f));
        walkDirection.set(0, 0, 0);
        
        camDir.setY(0).normalizeLocal();
        camLeft.setY(0).normalizeLocal();
        //System.err.println(camDir.y+","+camLeft.y);
        //viewDirection.set(camDir);
        // 计算运动方向

        boolean changed = false;
        if(up){

        walkDirection.addLocal(camDir);
        
        Quaternion rotation = simpleApp.getRootNode().getChild("model").getLocalRotation().clone();
        Vector3f direction = camDir;//.subtractLocal(simpleApp.getRootNode().getChild("model").getWorldTranslation())
        targetQua.lookAt(direction, Vector3f.UNIT_Y);
        rotation.nlerp(targetQua, 0.5f);
        viewDirection.set(rotation.mult(Vector3f.UNIT_Z));

            
         
        System.err.println(viewDirection);
        changed = true;
        } 
        if(down){

        changed = true;
        }else if(left){

          changed = true;
        }else if(right){
             changed = true;
        }else if(changed){
        }

     player.setViewDirection(viewDirection);
     
    }

I hope you can tell me why viewDirection.set(rotation.mult(Vector3f.UNIT_Z)); Have no effect(Maybe not without effect).

set rotation.nlerp(targetQua, 0.5f); Obviously the blue box is facing the wrong way

If I set rotation.nlerp(targetQua, 1f); Then everything will be fine but there will be no interpolation

This means that the rotation will only be correct if there is no interpolation.

I don’t understand why this is and what other key elements I am missing?

This code works as intended for me. There is probably something wrong in the code I can’t see that is causing the behavior you’re seeing.

1 Like