From 5874cac33b5f42e9af582f09e9a4572c2f3ebf2e Mon Sep 17 00:00:00 2001 From: austin Date: Sun, 1 Jan 2023 23:53:58 -0500 Subject: [PATCH] improve airplane movement + fix camera calculation --- .../electrosphere/controls/CameraHandler.java | 37 +++++++++---- .../controls/ControlHandler.java | 2 +- .../electrosphere/engine/LoadingThread.java | 2 +- .../electrosphere/entity/state/IdleTree.java | 3 +- .../entity/state/{ => attack}/AttackTree.java | 3 +- .../entity/state/attack/ShooterTree.java | 55 +++++++++++++++++++ .../state/movement/AirplaneMovementTree.java | 39 ++++++++++++- .../state/movement/GroundMovementTree.java | 4 +- .../types/camera/CameraEntityUtils.java | 31 ++++++++++- .../entity/types/creature/CreatureUtils.java | 2 +- .../types/debug/DebugVisualizerUtils.java | 9 +++ .../server/ai/creature/MindlessAttacker.java | 2 +- .../ai/creature/OpportunisticAttacker.java | 2 +- .../game/simulation/MicroSimulation.java | 2 +- .../server/protocol/CharacterProtocol.java | 2 +- .../electrosphere/util/TransformUtils.java | 26 +++++++++ 16 files changed, 195 insertions(+), 26 deletions(-) rename src/main/java/electrosphere/entity/state/{ => attack}/AttackTree.java (99%) create mode 100644 src/main/java/electrosphere/entity/state/attack/ShooterTree.java create mode 100644 src/main/java/electrosphere/util/TransformUtils.java diff --git a/src/main/java/electrosphere/controls/CameraHandler.java b/src/main/java/electrosphere/controls/CameraHandler.java index c54d1b39..30cabf6f 100644 --- a/src/main/java/electrosphere/controls/CameraHandler.java +++ b/src/main/java/electrosphere/controls/CameraHandler.java @@ -1,5 +1,6 @@ package electrosphere.controls; +import org.joml.Quaternionf; import org.joml.Vector3d; import org.joml.Vector3f; @@ -12,7 +13,8 @@ import electrosphere.renderer.ui.events.MouseEvent; public class CameraHandler { - float mouseSensitivity = .1f; + float mouseSensitivityHorizontal = .1f; + float mouseSensitivityVertical = .08f; float cameraSpeed; float yaw = 150; float pitch = 50; @@ -22,14 +24,14 @@ public class CameraHandler { public void handleMouseEvent(MouseEvent event){ if(Globals.controlHandler != null && !Globals.controlHandler.isMouseVisible()){ - yaw = yaw + event.getDeltaX() * mouseSensitivity; - pitch = pitch - event.getDeltaY() * mouseSensitivity; + yaw = yaw + event.getDeltaX() * mouseSensitivityHorizontal; + pitch = pitch - event.getDeltaY() * mouseSensitivityVertical; - if (pitch > 100.0f) { - pitch = 100.0f; + if (pitch >= 89.9f) { + pitch = 89.9f; } - if (pitch < -99.0f) { - pitch = -99.0f; + if (pitch <= -89.9f) { + pitch = -89.9f; } } @@ -64,20 +66,33 @@ public class CameraHandler { 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)); // } - 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; + Quaternionf pitchQuat = new Quaternionf().fromAxisAngleDeg(new Vector3f(1,0,0), -pitch); + Quaternionf yawQuat = new Quaternionf().fromAxisAngleDeg(new Vector3f(0,1,0), -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(new Vector3f(0,0,1)); + 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); } //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 radialOffset = CameraEntityUtils.getOrbitalCameraRadialOffset(Globals.playerCamera); Vector3f trueOffset = new Vector3f(radialOffset).mul(xFactor,1.0f,yFactor); CameraEntityUtils.setOrbitalCameraRadialOffset(Globals.playerCamera, trueOffset); // float cam_Player_Orbit_Magnitude = CameraEntityUtils.getCameraOrbitRadius(Globals.playerCamera); diff --git a/src/main/java/electrosphere/controls/ControlHandler.java b/src/main/java/electrosphere/controls/ControlHandler.java index 187ac68b..ff732e5d 100644 --- a/src/main/java/electrosphere/controls/ControlHandler.java +++ b/src/main/java/electrosphere/controls/ControlHandler.java @@ -75,8 +75,8 @@ import electrosphere.audio.AudioUtils; import electrosphere.controls.Control.ControlMethod; import electrosphere.controls.Control.ControlType; import electrosphere.entity.Entity; -import electrosphere.entity.state.AttackTree; import electrosphere.entity.state.BehaviorTree; +import electrosphere.entity.state.attack.AttackTree; import electrosphere.entity.state.equip.EquipState; import electrosphere.entity.state.inventory.InventoryUtils; import electrosphere.entity.state.inventory.UnrelationalInventoryState; diff --git a/src/main/java/electrosphere/engine/LoadingThread.java b/src/main/java/electrosphere/engine/LoadingThread.java index 27afc933..b7cd334c 100644 --- a/src/main/java/electrosphere/engine/LoadingThread.java +++ b/src/main/java/electrosphere/engine/LoadingThread.java @@ -623,7 +623,7 @@ public class LoadingThread extends Thread { Player Camera */ - Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityTrackingCameraEntity(new Vector3f(1,0,1), new Vector3f(0,0,1)); + Globals.playerCamera = CameraEntityUtils.spawnPlayerEntityAirplaneTrackingCameraEntity(new Vector3f(1,0,1), new Vector3f(0,0,1)); diff --git a/src/main/java/electrosphere/entity/state/IdleTree.java b/src/main/java/electrosphere/entity/state/IdleTree.java index a327f35c..b53072e6 100644 --- a/src/main/java/electrosphere/entity/state/IdleTree.java +++ b/src/main/java/electrosphere/entity/state/IdleTree.java @@ -1,11 +1,12 @@ package electrosphere.entity.state; +import electrosphere.entity.state.attack.AttackTree; +import electrosphere.entity.state.attack.AttackTree.AttackTreeState; import electrosphere.entity.state.movement.AirplaneMovementTree; import electrosphere.entity.state.movement.GroundMovementTree; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.state.AttackTree.AttackTreeState; import electrosphere.entity.state.movement.GroundMovementTree.MovementTreeState; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.main.Globals; diff --git a/src/main/java/electrosphere/entity/state/AttackTree.java b/src/main/java/electrosphere/entity/state/attack/AttackTree.java similarity index 99% rename from src/main/java/electrosphere/entity/state/AttackTree.java rename to src/main/java/electrosphere/entity/state/attack/AttackTree.java index ef7268cd..b5860f69 100644 --- a/src/main/java/electrosphere/entity/state/AttackTree.java +++ b/src/main/java/electrosphere/entity/state/attack/AttackTree.java @@ -1,8 +1,9 @@ -package electrosphere.entity.state; +package electrosphere.entity.state.attack; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; +import electrosphere.entity.state.BehaviorTree; import electrosphere.entity.state.collidable.Impulse; import electrosphere.entity.state.equip.EquipState; import electrosphere.entity.state.movement.GroundMovementTree; diff --git a/src/main/java/electrosphere/entity/state/attack/ShooterTree.java b/src/main/java/electrosphere/entity/state/attack/ShooterTree.java new file mode 100644 index 00000000..b804ffe4 --- /dev/null +++ b/src/main/java/electrosphere/entity/state/attack/ShooterTree.java @@ -0,0 +1,55 @@ +package electrosphere.entity.state.attack; + +import electrosphere.entity.Entity; +import electrosphere.entity.state.BehaviorTree; + +public class ShooterTree implements BehaviorTree { + + public static enum ShooterTreeState { + ATTACK, + COOLDOWN, + IDLE, + } + + ShooterTreeState state; + + Entity parent; + + int ammoAvailable; + int ammoMax; + + public ShooterTree(Entity parent){ + this.parent = parent; + } + + @Override + public void simulate() { + // TODO Auto-generated method stub + switch(state){ + case ATTACK: { + // + } break; + case COOLDOWN: { + // + } break; + case IDLE: { + // + } break; + } + } + + public void fire(){ + boolean canFire = true; + if(ammoAvailable <= 0){ + canFire = false; + } + if(state != ShooterTreeState.IDLE){ + canFire = false; + } + if(canFire){ + //fire + System.out.println("Fire!"); + } + } + +} diff --git a/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java b/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java index 786f5495..0bca2c0e 100644 --- a/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java +++ b/src/main/java/electrosphere/entity/state/movement/AirplaneMovementTree.java @@ -29,6 +29,14 @@ public class AirplaneMovementTree implements BehaviorTree { float minVelocity = 0; float maxRotationSpeed = 1.0f; + //The yaw value last simulation frame + float previousYaw = 270; + //how much we're rolling currently + float rollVal = 0; + // the factor to increment rollVal by while swinging the camera around + float rollFactor = 0.05f; + + static final double STATE_DIFFERENCE_HARD_UPDATE_THRESHOLD = 1.0; static final double STATE_DIFFERENCE_SOFT_UPDATE_THRESHOLD = 0.2; static final double SOFT_UPDATE_MULTIPLIER = 0.1; @@ -45,6 +53,8 @@ public class AirplaneMovementTree implements BehaviorTree { //used to filter out packets before the most recent one long lastUpdateTime = 0; + float pitchCalculationTolerance = 0.99f; + /** * Constructs an airplane movement tree @@ -173,9 +183,34 @@ public class AirplaneMovementTree implements BehaviorTree { void updateRotation(Quaternionf rotation, Vector3d rotationVector){ if(Globals.RUN_CLIENT && this.parent == Globals.playerEntity){ Vector3f cameraEyeVector = CameraEntityUtils.getCameraEye(Globals.playerCamera); + float pitch = CameraEntityUtils.getCameraPitch(Globals.playerCamera) / 180 * (float)Math.PI; + float yaw = -(CameraEntityUtils.getCameraYaw(Globals.playerCamera) + 180) / 180 * (float)Math.PI; + + + float deltaYaw = yaw - previousYaw; + + if(deltaYaw > 0){ + rollVal += -rollFactor; + } + if(deltaYaw < 0){ + rollVal += rollFactor; + } + + + Quaternionf yawQuat = new Quaternionf().fromAxisAngleRad(new Vector3f(0,1,0), yaw); + Quaternionf pitchQuat = new Quaternionf().fromAxisAngleRad(new Vector3f(1,0,0), pitch); + Quaternionf rollQuat = new Quaternionf().fromAxisAngleRad(new Vector3f(0,0,1), rollVal); + + rotation.slerp(yawQuat.mul(pitchQuat).mul(rollQuat),0.1f); + + + + //rotate thrust vector rotationVector.set(new Vector3f((float)rotationVector.x,(float)rotationVector.y,(float)rotationVector.z).mul(1.0f - this.maxRotationSpeed).add(new Vector3f(cameraEyeVector).mul(-this.maxRotationSpeed))); - rotation.set(new Quaternionf().rotationTo(new Vector3f(0,0,1), new Vector3f((float)rotationVector.x,(float)rotationVector.y,(float)rotationVector.z)).normalize()); - // rotation.slerp(new Quaternionf().rotationTo(new Vector3f((float)rotationVector.x,(float)rotationVector.y,(float)rotationVector.z), cameraEyeVector), this.maxRotationSpeed); + + + rollVal = rollVal * 0.9f; + previousYaw = yaw; } } diff --git a/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java b/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java index 908b05e0..98eff05f 100644 --- a/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java +++ b/src/main/java/electrosphere/entity/state/movement/GroundMovementTree.java @@ -10,9 +10,9 @@ import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.state.AttackTree; import electrosphere.entity.state.BehaviorTree; -import electrosphere.entity.state.AttackTree.AttackTreeState; +import electrosphere.entity.state.attack.AttackTree; +import electrosphere.entity.state.attack.AttackTree.AttackTreeState; import electrosphere.entity.state.movement.SprintTree.SprintTreeState; import electrosphere.game.collision.CollisionEngine; import electrosphere.game.collision.PhysicsUtils; diff --git a/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java b/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java index a90f6de2..1ca6e8fa 100644 --- a/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java +++ b/src/main/java/electrosphere/entity/types/camera/CameraEntityUtils.java @@ -75,6 +75,29 @@ public class CameraEntityUtils { Globals.entityManager.registerBehaviorTree(entityTrackingTree); return rVal; } + + public static Entity spawnPlayerEntityAirplaneTrackingCameraEntity(Vector3f center, Vector3f eye){ + Entity rVal = new Entity(); + Globals.entityManager.registerEntity(rVal); + rVal.putData(EntityDataStrings.DATA_STRING_CAMERA_TYPE, EntityDataStrings.DATA_STRING_CAMERA_TYPE_ORBIT); + rVal.putData(EntityDataStrings.DATA_STRING_CAMERA_CENTER, center); + rVal.putData(EntityDataStrings.DATA_STRING_CAMERA_EYE, eye); + rVal.putData(EntityDataStrings.DATA_STRING_CAMERA_ORBIT_DISTANCE, 2.0f); + rVal.putData(EntityDataStrings.CAMERA_ORBIT_RADIAL_OFFSET, new Vector3f(0,0.45f,0)); + rVal.putData(EntityDataStrings.CAMERA_PITCH, 0.0f); + rVal.putData(EntityDataStrings.CAMERA_YAW, 0.0f); + BehaviorTree entityTrackingTree = new BehaviorTree() { + @Override + public void simulate() { + if(Globals.playerEntity != null){ + Vector3d entityPos = EntityUtils.getPosition(Globals.playerEntity); + CameraEntityUtils.setCameraCenter(rVal, new Vector3f((float)entityPos.x,(float)entityPos.y,(float)entityPos.z).add(getOrbitalCameraRadialOffset(rVal))); + } + } + }; + Globals.entityManager.registerBehaviorTree(entityTrackingTree); + return rVal; + } public static Entity getOrbitalCameraTarget(Entity camera){ return (Entity)camera.getData(EntityDataStrings.DATA_STRING_CAMERA_ORBIT_TARGET); @@ -138,8 +161,12 @@ public class CameraEntityUtils { Vector3f cameraCenter = new Vector3f(0,0,0);//getViewMatrixCenterOffset(camera); Vector3f cameraEye = new Vector3f(cameraCenter).add(getCameraEye(camera)); Vector3f cameraUp = new Vector3f(0,1.0f,0); -// System.out.println("eye: " + cameraEye); -// System.out.println("center: " + cameraCenter); + //!!before you make the same mistake I made, cameraEye is NOT NECESSARILY normalized/unit vector + //the orbital distance and offset are included in this vector + //TODO: refactor this to some other matrix of transforms or something?? + cameraEye = new Vector3f(getCameraEye(camera)); + // System.out.println("eye: " + cameraEye); + // System.out.println("center: " + cameraCenter); // System.out.println("up: " + cameraUp); Matrix4f rVal = new Matrix4f().setLookAt( cameraEye, //eye diff --git a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java index 6ecbe52f..f84c8b4a 100644 --- a/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java +++ b/src/main/java/electrosphere/entity/types/creature/CreatureUtils.java @@ -12,9 +12,9 @@ import electrosphere.entity.state.movement.JumpTree; import electrosphere.entity.types.hitbox.HitboxData; import electrosphere.entity.types.hitbox.HitboxUtils; import electrosphere.game.data.creature.type.CreatureType; -import electrosphere.entity.state.AttackTree; import electrosphere.entity.state.BehaviorTree; import electrosphere.entity.state.IdleTree; +import electrosphere.entity.state.attack.AttackTree; import electrosphere.entity.state.collidable.CollidableTree; import electrosphere.entity.state.equip.EquipState; import electrosphere.entity.state.gravity.GravityTree; diff --git a/src/main/java/electrosphere/entity/types/debug/DebugVisualizerUtils.java b/src/main/java/electrosphere/entity/types/debug/DebugVisualizerUtils.java index ba2ffebc..d973f1bb 100644 --- a/src/main/java/electrosphere/entity/types/debug/DebugVisualizerUtils.java +++ b/src/main/java/electrosphere/entity/types/debug/DebugVisualizerUtils.java @@ -18,4 +18,13 @@ public class DebugVisualizerUtils { return rVal; } + public static Entity spawnUpdatingVectorVisualizer(Vector3d position, Vector3d direction){ + Entity rVal = EntityUtils.spawnDrawableEntity("Models/unitcube.fbx"); + Vector3d pos = new Vector3d(position).add(new Vector3d(direction).normalize().mul(0.3)); + EntityUtils.getPosition(rVal).set(pos); + EntityUtils.getScale(rVal).set(0.05f,0.3f,0.05f); + EntityUtils.getRotation(rVal).rotateTo(new Vector3f(0,1,0), new Vector3f((float)direction.x,(float)direction.y,(float)direction.z)); + return rVal; + } + } diff --git a/src/main/java/electrosphere/game/server/ai/creature/MindlessAttacker.java b/src/main/java/electrosphere/game/server/ai/creature/MindlessAttacker.java index ca7a1112..b199e48b 100644 --- a/src/main/java/electrosphere/game/server/ai/creature/MindlessAttacker.java +++ b/src/main/java/electrosphere/game/server/ai/creature/MindlessAttacker.java @@ -3,7 +3,7 @@ package electrosphere.game.server.ai.creature; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.state.AttackTree; +import electrosphere.entity.state.attack.AttackTree; import electrosphere.entity.state.movement.GroundMovementTree; import electrosphere.entity.state.movement.GroundMovementTree.MovementRelativeFacing; import electrosphere.entity.types.creature.CreatureUtils; diff --git a/src/main/java/electrosphere/game/server/ai/creature/OpportunisticAttacker.java b/src/main/java/electrosphere/game/server/ai/creature/OpportunisticAttacker.java index a33eab10..7a3cf261 100644 --- a/src/main/java/electrosphere/game/server/ai/creature/OpportunisticAttacker.java +++ b/src/main/java/electrosphere/game/server/ai/creature/OpportunisticAttacker.java @@ -3,7 +3,7 @@ package electrosphere.game.server.ai.creature; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.state.AttackTree; +import electrosphere.entity.state.attack.AttackTree; import electrosphere.entity.state.equip.EquipState; import electrosphere.entity.state.movement.GroundMovementTree; import electrosphere.entity.state.movement.GroundMovementTree.MovementRelativeFacing; diff --git a/src/main/java/electrosphere/game/simulation/MicroSimulation.java b/src/main/java/electrosphere/game/simulation/MicroSimulation.java index b66b193b..9d048b63 100644 --- a/src/main/java/electrosphere/game/simulation/MicroSimulation.java +++ b/src/main/java/electrosphere/game/simulation/MicroSimulation.java @@ -4,11 +4,11 @@ import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityUtils; -import electrosphere.entity.state.AttackTree; import electrosphere.entity.state.BehaviorTree; import electrosphere.entity.state.IdleTree; import electrosphere.entity.state.movement.GroundMovementTree; import electrosphere.entity.state.ParticleTree; +import electrosphere.entity.state.attack.AttackTree; import electrosphere.entity.state.collidable.CollidableTree; import electrosphere.entity.state.gravity.GravityTree; import electrosphere.entity.types.creature.CreatureUtils; diff --git a/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java b/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java index 716911bc..ad549ee6 100644 --- a/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/CharacterProtocol.java @@ -64,7 +64,7 @@ public class CharacterProtocol { // System.out.println(EntityUtils.getRotation(newPlayerCharacter).set(0,1,0,1).normalize()); Globals.dataCellManager.addPlayerToGroundCells(playerObject); Globals.dataCellManager.movePlayerGroundCells(playerObject, Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.x), Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z)); - IronSightTree.attachIronSightTree(newPlayerEntity); + // IronSightTree.attachIronSightTree(newPlayerEntity); // //spawn player sword // Entity sword = ItemUtils.spawnBasicItem("Katana"); // AttachUtils.attachEntityToEntityAtBone(newPlayerCharacter, sword, "Bone.031"); diff --git a/src/main/java/electrosphere/util/TransformUtils.java b/src/main/java/electrosphere/util/TransformUtils.java new file mode 100644 index 00000000..ce8d4938 --- /dev/null +++ b/src/main/java/electrosphere/util/TransformUtils.java @@ -0,0 +1,26 @@ +package electrosphere.util; + +import org.joml.Quaternionf; +import org.joml.Vector3d; +import org.joml.Vector3f; + +public class TransformUtils { + + + public Quaternionf calculateQuaternionFromPoints(Vector3d origin, Vector3d direction){ + return new Quaternionf().rotateTo(new Vector3f(0,1,0), new Vector3f((float)(direction.x-origin.x),(float)(direction.y-origin.y),(float)(direction.z-origin.z))); + } + + public Quaternionf calculateQuaternionFromPoints(Vector3d direction){ + return new Quaternionf().rotateTo(new Vector3f(0,1,0), new Vector3f((float)direction.x,(float)direction.y,(float)direction.z)); + } + + public Quaternionf calculateQuaternionFromPoints(Vector3f origin, Vector3f direction){ + return new Quaternionf().rotateTo(new Vector3f(0,1,0), new Vector3f(direction.x-origin.x,direction.y-origin.y,direction.z-origin.z)); + } + + public Quaternionf calculateQuaternionFromPoints(Vector3f direction){ + return new Quaternionf().rotateTo(new Vector3f(0,1,0), new Vector3f(direction)); + } + +}