245 lines
9.6 KiB
Java
245 lines
9.6 KiB
Java
package electrosphere.controls;
|
|
|
|
import org.joml.Quaternionf;
|
|
import org.joml.Vector3d;
|
|
import org.joml.Vector3f;
|
|
|
|
import electrosphere.client.entity.camera.CameraEntityUtils;
|
|
import electrosphere.client.entity.crosshair.Crosshair;
|
|
import electrosphere.collision.CollisionEngine;
|
|
import electrosphere.engine.Globals;
|
|
import electrosphere.entity.Entity;
|
|
import electrosphere.entity.EntityUtils;
|
|
import electrosphere.net.parser.net.message.EntityMessage;
|
|
import electrosphere.renderer.ui.events.MouseEvent;
|
|
import electrosphere.util.math.SpatialMathUtils;
|
|
|
|
/**
|
|
* Handler for camera-related events and controls
|
|
*/
|
|
public class CameraHandler {
|
|
|
|
//The first person camera perspective
|
|
public static final int CAMERA_PERSPECTIVE_FIRST = 1;
|
|
//The third person camera perspective
|
|
public static final int CAMERA_PERSPECTIVE_THIRD = 3;
|
|
|
|
//the horizontal mouse sensitivity
|
|
float mouseSensitivityHorizontal = .1f;
|
|
//the vertical mouse sensitivity
|
|
float mouseSensitivityVertical = .08f;
|
|
//the speed of the freecam
|
|
float cameraSpeed;
|
|
//the current yaw
|
|
float yaw = 150;
|
|
//the current pitch
|
|
float pitch = 50;
|
|
//the camera's rotation vector
|
|
Vector3f cameraRotationVector = new Vector3f();
|
|
//the radial offset of the camera
|
|
Vector3f radialOffset = new Vector3f(0,1,0);
|
|
//if set to true, the camera will track the player's entity
|
|
boolean trackPlayerEntity = true;
|
|
|
|
//sets whether the camera handler should update the player's camera or not
|
|
boolean update = true;
|
|
|
|
/**
|
|
* Handles a mouse event
|
|
* @param event The mouse event
|
|
*/
|
|
public void handleMouseEvent(MouseEvent event){
|
|
|
|
if(Globals.controlHandler != null && !Globals.controlHandler.isMouseVisible()){
|
|
yaw = yaw + event.getDeltaX() * mouseSensitivityHorizontal;
|
|
pitch = pitch + event.getDeltaY() * mouseSensitivityVertical;
|
|
|
|
if (pitch >= 89.9f) {
|
|
pitch = 89.9f;
|
|
}
|
|
if (pitch <= -89.9f) {
|
|
pitch = -89.9f;
|
|
}
|
|
}
|
|
|
|
this.updateGlobalCamera();
|
|
}
|
|
|
|
/**
|
|
* Updates the radial offset
|
|
* @param offset the radial offset
|
|
*/
|
|
public void updateRadialOffset(Vector3f offset){
|
|
radialOffset = offset;
|
|
}
|
|
|
|
/**
|
|
* Updates the global camera
|
|
*/
|
|
public void updateGlobalCamera(){
|
|
Globals.profiler.beginCpuSample("updateGlobalCamera");
|
|
if(update){
|
|
if(Globals.playerCamera != null){
|
|
cameraSpeed = 2.5f * (float)Globals.timekeeper.getMostRecentRawFrametime();
|
|
|
|
if(Crosshair.getCrosshairActive()){
|
|
|
|
// if(Globals.playerCharacter != null){
|
|
// Vector3d charPos = EntityUtils.getPosition(Globals.playerCharacter);
|
|
// CameraEntityUtils.setCameraCenter(Globals.playerCamera, new Vector3f((float)charPos.x,(float)charPos.y,(float)charPos.z));
|
|
// }
|
|
|
|
Vector3d characterPos = EntityUtils.getPosition(Globals.playerEntity);
|
|
Vector3d targetPos = Crosshair.getTargetPosition();
|
|
Vector3d diffed = new Vector3d(targetPos).sub(characterPos).mul(-1).normalize();
|
|
cameraRotationVector.set((float)diffed.x, 0.5f, (float)diffed.z).normalize();
|
|
|
|
yaw = (float)Math.toDegrees(Math.atan2(diffed.z, diffed.x));
|
|
|
|
CameraEntityUtils.setCameraPitch(Globals.playerCamera, pitch);
|
|
CameraEntityUtils.setCameraYaw(Globals.playerCamera, yaw);
|
|
|
|
} else {
|
|
CameraEntityUtils.setCameraPitch(Globals.playerCamera, pitch);
|
|
CameraEntityUtils.setCameraYaw(Globals.playerCamera, yaw);
|
|
|
|
// System.out.println(pitch);
|
|
// if(Globals.playerCharacter != null){
|
|
// Vector3d charPos = EntityUtils.getPosition(Globals.playerCharacter);
|
|
// CameraEntityUtils.setCameraCenter(Globals.playerCamera, new Vector3f((float)charPos.x,(float)charPos.y,(float)charPos.z));
|
|
// }
|
|
|
|
Quaternionf pitchQuat = new Quaternionf().fromAxisAngleDeg(SpatialMathUtils.getLeftVectorf(), -pitch);
|
|
Quaternionf yawQuat = new Quaternionf().fromAxisAngleDeg(SpatialMathUtils.getUpVectorf(), -yaw);
|
|
// float yawRad = yaw / 180.0f * (float)Math.PI;
|
|
// float pitchRad = pitch / 180.0f * (float)Math.PI;
|
|
// float rollRad = 0.0f;
|
|
// pitchQuat.mul(yawQuat);
|
|
cameraRotationVector = pitchQuat.transform(SpatialMathUtils.getOriginVectorf());
|
|
cameraRotationVector = yawQuat.transform(cameraRotationVector);
|
|
cameraRotationVector.normalize();
|
|
|
|
|
|
// cameraRotationVector.x = 0 + (float) Math.cos(yaw / 180.0f * Math.PI) * 1;
|
|
// cameraRotationVector.y = 0 + (float) Math.sin(pitch / 180.0f * Math.PI) * 1;
|
|
// cameraRotationVector.z = 0 + (float) Math.sin(yaw / 180.0f * Math.PI) * 1;
|
|
// cameraRotationVector.normalize();
|
|
// System.out.println(yaw + " " + pitch);
|
|
}
|
|
if(trackPlayerEntity && Globals.playerEntity != null){
|
|
Vector3d entityPos = EntityUtils.getPosition(Globals.playerEntity);
|
|
CameraEntityUtils.setCameraCenter(Globals.playerCamera, new Vector3f((float)entityPos.x,(float)entityPos.y,(float)entityPos.z).add(CameraEntityUtils.getOrbitalCameraRadialOffset(Globals.playerCamera)));
|
|
}
|
|
//update view matrix offset
|
|
float xFactor = (float)Math.cos(yaw / 180.0f * Math.PI);
|
|
float yFactor = (float)Math.sin(yaw / 180.0f * Math.PI);
|
|
Vector3f radialOffset = CameraEntityUtils.getOrbitalCameraRadialOffset(Globals.playerCamera);
|
|
Vector3f trueOffset = new Vector3f(radialOffset).mul(xFactor,1.0f,yFactor);
|
|
CameraEntityUtils.setOrbitalCameraRadialOffset(Globals.playerCamera, trueOffset);
|
|
cameraRotationVector.mul(CameraEntityUtils.getOrbitalCameraDistance(Globals.playerCamera));
|
|
CameraEntityUtils.setCameraEye(Globals.playerCamera, cameraRotationVector);
|
|
|
|
//tell the server that we changed where we're looking, if we're in first person
|
|
int perspectiveVal = CameraHandler.CAMERA_PERSPECTIVE_FIRST;
|
|
if(Globals.controlHandler.cameraIsThirdPerson()){
|
|
perspectiveVal = CameraHandler.CAMERA_PERSPECTIVE_THIRD;
|
|
}
|
|
if(Globals.cameraHandler.getTrackPlayerEntity() && Globals.playerEntity != null){
|
|
Globals.clientConnection.queueOutgoingMessage(
|
|
EntityMessage.constructupdateEntityViewDirMessage(
|
|
Globals.clientSceneWrapper.mapClientToServerId(Globals.playerEntity.getId()),
|
|
Globals.timekeeper.getNumberOfSimFramesElapsed(),
|
|
perspectiveVal,
|
|
yaw,
|
|
pitch
|
|
)
|
|
);
|
|
}
|
|
|
|
//the view matrix
|
|
Globals.viewMatrix = CameraEntityUtils.getCameraViewMatrix(Globals.playerCamera);
|
|
|
|
//update the cursor on client side
|
|
this.updatePlayerCursor();
|
|
}
|
|
}
|
|
Globals.profiler.endCpuSample();
|
|
}
|
|
|
|
/**
|
|
* Updates the position of the player's in world cursor
|
|
*/
|
|
private void updatePlayerCursor(){
|
|
CollisionEngine collisionEngine = Globals.clientSceneWrapper.getCollisionEngine();
|
|
Entity camera = Globals.playerCamera;
|
|
if(
|
|
collisionEngine != null &&
|
|
camera != null &&
|
|
Globals.playerCursor != null
|
|
){
|
|
Vector3d eyePos = new Vector3d(CameraEntityUtils.getCameraEye(camera));
|
|
Vector3d centerPos = new Vector3d(CameraEntityUtils.getCameraCenter(camera));
|
|
Vector3d cursorPos = collisionEngine.rayCastPosition(centerPos, new Vector3d(eyePos).mul(-1.0), CollisionEngine.DEFAULT_INTERACT_DISTANCE);
|
|
if(cursorPos != null){
|
|
EntityUtils.getPosition(Globals.playerCursor).set(cursorPos);
|
|
} else {
|
|
EntityUtils.getPosition(Globals.playerCursor).set(new Vector3d(centerPos).add(new Vector3d(eyePos).normalize().mul(-CollisionEngine.DEFAULT_INTERACT_DISTANCE)));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the yaw of the camera handler
|
|
* @return the yaw
|
|
*/
|
|
public float getYaw(){
|
|
return yaw;
|
|
}
|
|
|
|
/**
|
|
* Sets the yaw of the camera handler
|
|
* @param yaw The yaw
|
|
*/
|
|
public void setYaw(double yaw){
|
|
this.yaw = (float)yaw;
|
|
}
|
|
|
|
/**
|
|
* Gets the pitch of the camera handler
|
|
* @return the pitch
|
|
*/
|
|
public float getPitch(){
|
|
return pitch;
|
|
}
|
|
|
|
/**
|
|
* Sets the pitch of the camera handler
|
|
* @param pitch The pitch
|
|
*/
|
|
public void setPitch(double pitch){
|
|
this.pitch = (float)pitch;
|
|
}
|
|
|
|
//set player tracking
|
|
public void setTrackPlayerEntity(boolean track){
|
|
trackPlayerEntity = track;
|
|
}
|
|
|
|
//get trackPlayerEntity
|
|
public boolean getTrackPlayerEntity(){
|
|
return trackPlayerEntity;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the camera should update with player input or not
|
|
* @param update true to update with input, false otherwise
|
|
*/
|
|
public void setUpdate(boolean update){
|
|
this.update = update;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|