I want to abuse the CameraMovementState for moving a CharacterControl: as such, instead of moving the Camera, I want to move a Vector3f walkDirection which in turn get processed somewhere else. So I changed this
Yeah, of course not. A camera has a position and a rotation (among about a dozen other things). A vector3f is just a vector3f… three float values. When you call cam.setRotation() you aren’t really “rotating around a Quaternion” you are setting the camera’s rotation that is used to build the camera view matrix.
I’ve made progress and (almost) everything works, but there is something I can’t understand: moving/strafing works and is fluid, but looking around works but is really choppy.
This is my code:
@Override
public void update( float tpf ) {
walkDirection.set(0, 0, 0);
// 'integrate' camera position based on the current move, strafe,
// and elevation speeds.
if( forward != 0 || side != 0 || elevation != 0 ) {
Vector3f loc = camera.getLocation();
Quaternion rot = camera.getRotation();
Vector3f move = rot.mult(Vector3f.UNIT_Z).multLocal((float)(forward * speed * tpf));
walkDirection.addLocal(camera.getDirection().multLocal((float)(forward * speed )));
walkDirection.addLocal(camera.getLeft().multLocal((float)(side * speed )));
Vector3f strafe = rot.mult(Vector3f.UNIT_X).multLocal((float)(side * speed * tpf));
// Note: this camera moves 'elevation' along the camera's current up
// vector because I find it more intuitive in free flight.
Vector3f elev = rot.mult(Vector3f.UNIT_Y).multLocal((float)(elevation * speed * tpf));
loc = loc.add(move).add(strafe).add(elev);
}
if (gameLogicAppState!=null){
gameLogicAppState.player.setWalkDirection(walkDirection);
camera.setLocation(gameLogicAppState.player.getPhysicsLocation());
gameLogicAppState.player.setPhysicsLocation(gameLogicAppState.player.getPhysicsLocation());
gameLogicAppState.pPlayer.getSpatial().setLocalTranslation(camera.getLocation());
}
}
/**
* Implementation of the AnalogFunctionListener interface.
*/
@Override
public void valueActive( FunctionId func, double value, double tpf ) {
// Setup rotations and movements speeds based on current
// axes states.
if( func == CameraMovementFunctions.F_Y_LOOK ) {
pitch += -value * tpf * turnSpeed;
if( pitch < minPitch )
pitch = minPitch;
if( pitch > maxPitch )
pitch = maxPitch;
} else if( func == CameraMovementFunctions.F_X_LOOK ) {
yaw += -value * tpf * turnSpeed;
if( yaw < 0 )
yaw += Math.PI * 2;
if( yaw > Math.PI * 2 )
yaw -= Math.PI * 2;
} else if( func == CameraMovementFunctions.F_MOVE ) {
this.forward = value;
return;
} else if( func == CameraMovementFunctions.F_STRAFE ) {
this.side = -value;
return;
} else if( func == CameraMovementFunctions.F_ELEVATE ) {
this.elevation = value;
return;
} else {
return;
}
updateFacing();
}
protected void updateFacing() {
cameraFacing.fromAngles( (float)pitch, (float)yaw, 0 );
camera.setRotation(cameraFacing);
}
We’re pretty sure that when I refactor this that you will explicitly have to choose your initial app states… even if it’s by using a standard constant or something. It will avoid these issues of “magic gone wrong”.