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; } }