Gun + the physics are on evil mode
This commit is contained in:
parent
605c96362b
commit
8ab8c06f9c
23 changed files with 2248 additions and 899 deletions
|
|
@ -7,6 +7,7 @@ import org.joml.Vector3f;
|
|||
import java.util.List;
|
||||
|
||||
public interface IPhysicsController {
|
||||
public boolean ApplyRotationalForce();
|
||||
public String ID();
|
||||
public String ActorID();
|
||||
public String MeshID();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public class LegacyPhysicsController implements IPhysicsController {
|
|||
Sensor
|
||||
}
|
||||
|
||||
|
||||
public List<CollisionSensor> collisionSensors;
|
||||
public Vector3f Velocities = new Vector3f(0,0,0);
|
||||
public Vector3f WeightBalance = new Vector3f(0,0,0);
|
||||
|
|
@ -93,6 +94,11 @@ public class LegacyPhysicsController implements IPhysicsController {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ApplyRotationalForce() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ID() {
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody;
|
|||
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.primitives.AABBf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -34,6 +35,17 @@ public class ConvexMesh {
|
|||
return vertex;
|
||||
}
|
||||
|
||||
public AABBf GetWorldAABB() {
|
||||
float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE, minZ = Float.MAX_VALUE;
|
||||
float maxX = -Float.MAX_VALUE, maxY = -Float.MAX_VALUE, maxZ = -Float.MAX_VALUE;
|
||||
for (int i = 0; i < LocalVertices.size(); i++) {
|
||||
Vector3f w = WorldVertex(i);
|
||||
minX = Math.min(minX, w.x); minY = Math.min(minY, w.y); minZ = Math.min(minZ, w.z);
|
||||
maxX = Math.max(maxX, w.x); maxY = Math.max(maxY, w.y); maxZ = Math.max(maxZ, w.z);
|
||||
}
|
||||
return new AABBf(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
}
|
||||
|
||||
public Vector3f WorldFaceNormal(Face f) {
|
||||
Vector3f normal = new Vector3f(f.LocalNormal);
|
||||
Orientation.transform(normal);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody;
|
||||
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyPhysicsController;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
|
@ -21,6 +22,8 @@ public class RigidBody {
|
|||
|
||||
public AABBf BoundingBox;
|
||||
|
||||
public boolean OnGround = false;
|
||||
public Vector3f LastPosition = new Vector3f();
|
||||
public final Vector3f Position;
|
||||
public final Quaternionf Rotation;
|
||||
public Vector3f WeightBalance = new Vector3f(0,0,0);
|
||||
|
|
@ -44,6 +47,14 @@ public class RigidBody {
|
|||
public float Friction = 0.5f;
|
||||
public boolean IsStatic = false;
|
||||
|
||||
public boolean RotationLocked = false;
|
||||
|
||||
public boolean UsesFrictionResolution = true;
|
||||
|
||||
public final Vector3f PreviousPosition = new Vector3f();
|
||||
|
||||
public boolean Grounded = false;
|
||||
|
||||
public String PhysicsControllerID = "NULL";
|
||||
public final String RigidBodyID;
|
||||
|
||||
|
|
@ -57,6 +68,13 @@ public class RigidBody {
|
|||
SetMass(MassKG);
|
||||
}
|
||||
|
||||
public RigidBody LockRotation(){
|
||||
RotationLocked = true;
|
||||
InverseInertiaLocal.zero();
|
||||
InverseInertiaWorld.zero();
|
||||
return this;
|
||||
}
|
||||
|
||||
public void SetMass(float mass) {
|
||||
this.MassKG = mass;
|
||||
if (mass <= 0f) {
|
||||
|
|
@ -70,7 +88,7 @@ public class RigidBody {
|
|||
}
|
||||
|
||||
public void SetRigidBoxInertia(float x, float y, float z){
|
||||
if(IsStatic) return;
|
||||
if(IsStatic || RotationLocked) return;
|
||||
float width = 2 * x, height = 2 * y, depth = 2 * z;
|
||||
float ix = (MassKG/12.0f) * (height * height + depth * depth);
|
||||
float iy = (MassKG/12.0f) * (width * width + depth * depth);
|
||||
|
|
@ -83,7 +101,7 @@ public class RigidBody {
|
|||
}
|
||||
|
||||
public void UpdateInertiaWorld(){
|
||||
if(IsStatic) {
|
||||
if(IsStatic || RotationLocked) {
|
||||
InverseInertiaWorld.zero();
|
||||
return;
|
||||
}
|
||||
|
|
@ -115,8 +133,11 @@ public class RigidBody {
|
|||
private final Vector3f GravityToAdd = new Vector3f();
|
||||
private final Vector3f VelocityToAdd = new Vector3f();
|
||||
public void Integrate(float DeltaTime, Vector3f Gravity){
|
||||
PreviousPosition.set(Position);
|
||||
if(IsStatic) return;
|
||||
LinearVelocity.add(GravityToAdd.set(Gravity).mul(DeltaTime));
|
||||
if(!Grounded) {
|
||||
LinearVelocity.add(GravityToAdd.set(Gravity).mul(DeltaTime));
|
||||
}
|
||||
Position.add(VelocityToAdd.set(LinearVelocity).mul(DeltaTime));
|
||||
|
||||
Quaternionf Spin = new Quaternionf(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import org.joml.Vector3f;
|
|||
|
||||
//Resolves the Separating Axis Theorem Test into reaction forces in impulses and position correction
|
||||
public class RigidCollision {
|
||||
private static final float CORRECTION_THRESHOLD = 0.9f; //how much it gets corrected positionally per physics step
|
||||
private static final float SLOP = 0.001f; // amount of overlap can happen before collision gets corrected
|
||||
private static final float CORRECTION_THRESHOLD = 1.0f;
|
||||
private static final float SLOP = 0.00f;
|
||||
|
||||
private static final float GROUNDED_DOT_THRESHOLD = 0.7f;
|
||||
private static final Vector3f WorldUp = new Vector3f(0, 1, 0);
|
||||
|
||||
public synchronized static void ResolveCollision(RigidBody body1, RigidBody body2, SeparatingAxisTheoremTester.CollisionResult collisionResult){
|
||||
Vector3f Normal = collisionResult.Normal;
|
||||
|
|
@ -15,6 +18,9 @@ public class RigidCollision {
|
|||
}
|
||||
|
||||
CorrectPositioning(body1,body2,Normal,collisionResult.Penetration);
|
||||
|
||||
if(Normal.dot(WorldUp) > GROUNDED_DOT_THRESHOLD && !body2.IsStatic) body2.Grounded = true;
|
||||
if(-Normal.dot(WorldUp) > GROUNDED_DOT_THRESHOLD && !body1.IsStatic) body1.Grounded = true;
|
||||
}
|
||||
|
||||
private static final Vector3f Dist1 = new Vector3f();
|
||||
|
|
@ -24,7 +30,6 @@ public class RigidCollision {
|
|||
private static final Vector3f RelativeVelocity = new Vector3f();
|
||||
private synchronized static void ResolveContact(RigidBody body1, RigidBody body2, Vector3f normal, SeparatingAxisTheoremTester.Contact contact){
|
||||
Vector3f Point = contact.Point;
|
||||
|
||||
Dist1.set(Point).sub(body1.Position);
|
||||
Dist2.set(Point).sub(body2.Position);
|
||||
|
||||
|
|
@ -43,8 +48,8 @@ public class RigidCollision {
|
|||
float j = -(1 + Restitution) * VelocityAlongNormal / InverseMassSum;
|
||||
Impulse.set(normal).mul(j);
|
||||
|
||||
body1.LinearVelocity.mul(-1,body1.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body1.Bounciness,body1.LinearVelocity.y < 0 ? 1 : body1.Bounciness,body1.Bounciness);
|
||||
body2.LinearVelocity.mul(-1,body2.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body2.Bounciness,body2.LinearVelocity.y < 0 ? 1 : body2.Bounciness,body2.Bounciness);
|
||||
// body1.LinearVelocity.mul(-1,body1.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body1.Bounciness,body1.LinearVelocity.y < 0 ? 1 : body1.Bounciness,body1.Bounciness);
|
||||
// body2.LinearVelocity.mul(-1,body2.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body2.Bounciness,body2.LinearVelocity.y < 0 ? 1 : body2.Bounciness,body2.Bounciness);
|
||||
|
||||
body1.ApplyImpulse(NegatedImpulse.set(Impulse).negate(), Point);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public class RigidPhysicsController implements IPhysicsController {
|
|||
return RigidControllerRegister.get(ID);
|
||||
}
|
||||
public final List<String> Collisions = new ArrayList<>();
|
||||
public boolean ApplyRotation = true;
|
||||
|
||||
public static RigidBody Ground = new RigidBody("FLOOR",ConvexMesh.Box(100,100f,100),0);
|
||||
public static RigidBody Wall = new RigidBody("WALL",ConvexMesh.Box(100,100f,10),0);
|
||||
|
|
@ -78,6 +79,11 @@ public class RigidPhysicsController implements IPhysicsController {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ApplyRotationalForce() {
|
||||
return ApplyRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ID() {
|
||||
return ControllerID;
|
||||
|
|
@ -103,7 +109,7 @@ public class RigidPhysicsController implements IPhysicsController {
|
|||
rigidBody.Integrate(DeltaTime, new Vector3f(0,-1.8f,0));
|
||||
if(Actor.Actors.get(ActorID) != null) {
|
||||
Actor.Actors.get(ActorID).SetPosition(new Vector3f(rigidBody.Position));
|
||||
Actor.Actors.get(ActorID).SetRotation(rigidBody.Rotation);
|
||||
if(ApplyRotation) Actor.Actors.get(ActorID).SetRotation(rigidBody.Rotation);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ public class SeparatingAxisTheoremTester {
|
|||
|
||||
//Face collision/clipping
|
||||
ConvexMesh ReferenceMesh = BestFaceOwner;
|
||||
if(ReferenceMesh == null) return null;
|
||||
ConvexMesh IncidentMesh = (ReferenceMesh == Mesh1) ? Mesh2 : Mesh1;
|
||||
ConvexMesh.Face ReferenceFace = BestFace;
|
||||
Vector3f ReferenceFaceNormalWorld = ReferenceMesh.WorldFaceNormal(ReferenceFace);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package net.halbear.Terrain4J.EngineCore.Logic.Physics;
|
||||
|
||||
import org.joml.primitives.AABBf;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SpatialHashGrid {
|
||||
public static float CellSize = 3f;
|
||||
|
||||
private static final Map<Long, List<String>> Cells = new HashMap<>();
|
||||
|
||||
public static void Clear() {
|
||||
Cells.clear();
|
||||
}
|
||||
|
||||
public static void Insert(String bodyID, AABBf worldBounds) {
|
||||
int minX = (int) Math.floor(worldBounds.minX / CellSize);
|
||||
int minY = (int) Math.floor(worldBounds.minY / CellSize);
|
||||
int minZ = (int) Math.floor(worldBounds.minZ / CellSize);
|
||||
int maxX = (int) Math.floor(worldBounds.maxX / CellSize);
|
||||
int maxY = (int) Math.floor(worldBounds.maxY / CellSize);
|
||||
int maxZ = (int) Math.floor(worldBounds.maxZ / CellSize);
|
||||
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
long key = HashCell(x, y, z);
|
||||
Cells.computeIfAbsent(key, k -> new ArrayList<>()).add(bodyID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static long HashCell(int x, int y, int z) {
|
||||
long xi = ((long) x) & 0x1FFFFFL;
|
||||
long yi = ((long) y) & 0x1FFFFFL;
|
||||
long zi = ((long) z) & 0x1FFFFFL;
|
||||
return (xi << 42) | (yi << 21) | zi;
|
||||
}
|
||||
|
||||
public static Collection<List<String>> Buckets() {
|
||||
return Cells.values();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,15 +1,17 @@
|
|||
package net.halbear.Terrain4J.EngineCore.Logic.Physics;
|
||||
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidCollision;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.SeparatingAxisTheoremTester;
|
||||
import net.halbear.Terrain4J.EngineCore.Threads.PhysicsThread;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.primitives.AABBf;
|
||||
import org.joml.primitives.Intersectionf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class WorldPhysicsManager {
|
||||
public static float GravityMS = 9.8f;
|
||||
|
|
@ -75,6 +77,8 @@ public class WorldPhysicsManager {
|
|||
for (int i = 0; i < ActiveControllers.size(); i++) {
|
||||
PhysicsObjects.get(ActiveControllers.get(i)).PhysicsTick(FixedTimeStep, TargetFrameTime);
|
||||
}
|
||||
SweepForTunneling();
|
||||
ResetGroundedFlags();
|
||||
ResolveAllCollisions();
|
||||
Accumulator -= FixedTimeStep;
|
||||
stepsRun++;
|
||||
|
|
@ -86,20 +90,61 @@ public class WorldPhysicsManager {
|
|||
}
|
||||
private static void ResolveAllCollisions() {
|
||||
List<String> ids = RigidBody.RigidBodies;
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
RigidBody a = RigidBody.RigidBodyRegister.get(ids.get(i));
|
||||
if (a == null) continue;
|
||||
for (int j = i + 1; j < ids.size(); j++) {
|
||||
RigidBody b = RigidBody.RigidBodyRegister.get(ids.get(j));
|
||||
if (b == null) continue;
|
||||
if (a.IsStatic && b.IsStatic) continue;
|
||||
|
||||
SeparatingAxisTheoremTester.CollisionResult result = SeparatingAxisTheoremTester.TestCollision(a.shape, b.shape);
|
||||
if (result != null) {
|
||||
RigidCollision.ResolveCollision(a, b, result);
|
||||
List<RigidBody> dynamicBodies = new ArrayList<>();
|
||||
List<RigidBody> staticBodies = new ArrayList<>();
|
||||
Map<String, AABBf> worldBounds = new HashMap<>();
|
||||
|
||||
SpatialHashGrid.Clear();
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
RigidBody body = RigidBody.RigidBodyRegister.get(ids.get(i));
|
||||
if (body == null) continue;
|
||||
|
||||
AABBf bounds = body.shape.GetWorldAABB();
|
||||
worldBounds.put(body.RigidBodyID, bounds);
|
||||
|
||||
if (body.IsStatic) {
|
||||
staticBodies.add(body);
|
||||
} else {
|
||||
dynamicBodies.add(body);
|
||||
SpatialHashGrid.Insert(body.RigidBodyID, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> testedPairs = new HashSet<>();
|
||||
|
||||
for (List<String> bucket : SpatialHashGrid.Buckets()) {
|
||||
int size = bucket.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
RigidBody a = RigidBody.RigidBodyRegister.get(bucket.get(i));
|
||||
if (a == null) continue;
|
||||
for (int j = i + 1; j < size; j++) {
|
||||
RigidBody b = RigidBody.RigidBodyRegister.get(bucket.get(j));
|
||||
if (b == null || a == b) continue;
|
||||
TryResolve(a, b, worldBounds, testedPairs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (RigidBody dyn : dynamicBodies) {
|
||||
for (RigidBody stat : staticBodies) {
|
||||
TryResolve(dyn, stat, worldBounds, testedPairs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryResolve(RigidBody a, RigidBody b, Map<String, AABBf> worldBounds, Set<String> testedPairs) {
|
||||
String key = a.RigidBodyID.compareTo(b.RigidBodyID) < 0
|
||||
? a.RigidBodyID + "|" + b.RigidBodyID
|
||||
: b.RigidBodyID + "|" + a.RigidBodyID;
|
||||
if (!testedPairs.add(key)) return;
|
||||
|
||||
if (!worldBounds.get(a.RigidBodyID).intersectsAABB(worldBounds.get(b.RigidBodyID))) return;
|
||||
|
||||
SeparatingAxisTheoremTester.CollisionResult result = SeparatingAxisTheoremTester.TestCollision(a.shape, b.shape);
|
||||
if (result != null) {
|
||||
RigidCollision.ResolveCollision(a, b, result);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PhysicsTick2(float DeltaTime, float TargetFrameTime){
|
||||
|
|
@ -109,6 +154,8 @@ public class WorldPhysicsManager {
|
|||
for (int i = 0; i < ActiveControllers.size(); i++) {
|
||||
PhysicsObjects.get(ActiveControllers.get(i)).PhysicsTick(DeltaTime, TargetFrameTime);
|
||||
}
|
||||
SweepForTunneling();
|
||||
ResetGroundedFlags();
|
||||
ResolveAllCollisions();
|
||||
for (int i = 0; i < ActiveControllers.size(); i++) {
|
||||
PhysicsObjects.get(ActiveControllers.get(i)).Collisions().clear();
|
||||
|
|
@ -130,4 +177,67 @@ public class WorldPhysicsManager {
|
|||
}
|
||||
}
|
||||
|
||||
private static void ResetGroundedFlags() {
|
||||
List<String> ids = RigidBody.RigidBodies;
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
RigidBody body = RigidBody.RigidBodyRegister.get(ids.get(i));
|
||||
if (body != null) body.Grounded = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static float MinSweepDistanceFactor = 0.5f;
|
||||
|
||||
public static float SweepMarginFactor = 0.5f;
|
||||
private static void SweepForTunneling() {
|
||||
List<String> ids = RigidBody.RigidBodies;
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
RigidBody body = RigidBody.RigidBodyRegister.get(ids.get(i));
|
||||
if (body == null || body.IsStatic) continue;
|
||||
|
||||
Vector3f from = body.PreviousPosition;
|
||||
Vector3f to = body.Position;
|
||||
float movedDistanceSq = from.distanceSquared(to);
|
||||
if (movedDistanceSq < 1e-8f) continue;
|
||||
|
||||
float radius = BoundingRadius(body.shape);
|
||||
float minSweepDistSq = (radius * radius) * (MinSweepDistanceFactor * MinSweepDistanceFactor);
|
||||
if (movedDistanceSq < minSweepDistSq) continue; // moved a normal, slow amount - discrete SAT already handles this fine
|
||||
|
||||
float margin = radius * SweepMarginFactor;
|
||||
Float earliestT = null;
|
||||
|
||||
for (int j = 0; j < ids.size(); j++) {
|
||||
if (i == j) continue;
|
||||
RigidBody other = RigidBody.RigidBodyRegister.get(ids.get(j));
|
||||
if (other == null) continue;
|
||||
|
||||
Float t = RaySweepAABB(from, to, other.shape.GetWorldAABB(), margin);
|
||||
if (t != null && (earliestT == null || t < earliestT)) {
|
||||
earliestT = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (earliestT != null) {
|
||||
Vector3f safePosition = new Vector3f(from).lerp(to, Math.max(0f, earliestT - 0.01f));
|
||||
body.Position.set(safePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Float RaySweepAABB(Vector3f from, Vector3f to, AABBf bounds, float margin) {
|
||||
Vector3f dir = new Vector3f(to).sub(from);
|
||||
Vector3f min = new Vector3f(bounds.minX - margin, bounds.minY - margin, bounds.minZ - margin);
|
||||
Vector3f max = new Vector3f(bounds.maxX + margin, bounds.maxY + margin, bounds.maxZ + margin);
|
||||
Vector2f result = new Vector2f();
|
||||
boolean hit = Intersectionf.intersectRayAab(from, dir, min, max, result);
|
||||
if (!hit) return null;
|
||||
if (result.x < 0f || result.x > 1f) return null;
|
||||
return result.x;
|
||||
}
|
||||
|
||||
private static float BoundingRadius(ConvexMesh shape) {
|
||||
Vector3f half = new Vector3f(shape.TopRightForward).sub(shape.BottomLeftBack).mul(0.5f);
|
||||
return half.length();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import static org.lwjgl.glfw.GLFW.*;
|
|||
public class GameCore implements GameLogic {
|
||||
|
||||
private static final float MOUSE_SENSITIVITY = 0.1f;
|
||||
private static final float MOVEMENT_SPEED = 0.025f;
|
||||
private static final float MOVEMENT_SPEED = 0.01f;
|
||||
public static boolean LoadingLevel = false;
|
||||
|
||||
public List<Actor> CubeActors = new ArrayList<>();
|
||||
|
|
@ -67,6 +67,7 @@ public class GameCore implements GameLogic {
|
|||
public List<IMoveableActorComponent> ActorEditorComponents = new ArrayList<>();
|
||||
private Gimbal gimbal;
|
||||
private Vector2f DeltaPos = new Vector2f(0,0);
|
||||
private String PlayerActorID = "NULL";
|
||||
|
||||
public Vector2f GetDeltaPos(){return DeltaPos;}
|
||||
@Override
|
||||
|
|
@ -101,6 +102,17 @@ public class GameCore implements GameLogic {
|
|||
CollisionMesh mesh = new CollisionMesh("Super Collision Mesh","NULL");
|
||||
mesh.AddNewCollisionPoly(new Vector3f(-100,-5,100),new Vector3f(-100,-5.5f,-100),new Vector3f(100,-6,-100));
|
||||
mesh.AddNewCollisionPoly(new Vector3f(100,-5.5f,100),new Vector3f(100,-6,-100),new Vector3f(-100,-5,100));
|
||||
|
||||
ModelData MusketData = ModelLoader.LoadModel("resources/models/musket/musket.json");
|
||||
List<MaterialData> MusketMat = ModelLoader.LoadMaterials("resources/models/musket/musket_mat.json");
|
||||
var Musket = new PlayerActor("DebugCamera","Player", MusketData.ID(), new Vector3f(0,5f,-5f)).SetCameraOffset(new Vector3f(0,1.0f,0));
|
||||
Musket.SetPositionOffset(new Vector3f(0.5f,1.0f,-1.25f));
|
||||
Musket.SetRotation(0,(float)Math.toRadians(180),0);
|
||||
Musket.CreatePhysicsController( ConvexMesh.Box(0.5f,0.75f,0.5f),200f);
|
||||
PlayerActorID = "Player";
|
||||
|
||||
RigidPhysicsController physicsController = (RigidPhysicsController) Musket.GetPhysicsController();
|
||||
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LockRotation();
|
||||
try {
|
||||
Melona.GenerateCollisionMesh(MelonaData);
|
||||
Melona.SetPhysicsType(Actor.PhysicsControllerType.T4JLegacyCollision);
|
||||
|
|
@ -110,12 +122,15 @@ public class GameCore implements GameLogic {
|
|||
}
|
||||
mesh.RegisterMesh();
|
||||
scene.AddActor(Melona);
|
||||
scene.AddActor(Musket);
|
||||
ActorEditorComponents.add(new EditorActorComponent(Melona,new Vector3f(0,0f,-5f),new Vector3f(1.0f,1.8f,1.0f)));
|
||||
CubeActors.forEach(scene::AddActor);
|
||||
|
||||
List<MaterialData> materials = new ArrayList<>();
|
||||
materials.addAll(MelonaDataMat);
|
||||
materials.addAll(MusketMat);
|
||||
models.add(MelonaData);
|
||||
models.add(MusketData);
|
||||
Camera camera = scene.GetCamera();
|
||||
camera.SetPosition(0,0,0);
|
||||
camera.SetRotation(0,0,0);
|
||||
|
|
@ -170,7 +185,7 @@ public class GameCore implements GameLogic {
|
|||
|
||||
Melona.CreatePhysicsController( ConvexMesh.Box(0.5f,0.5f,0.5f),20);
|
||||
RigidPhysicsController physicsController = (RigidPhysicsController) Melona.GetPhysicsController();
|
||||
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random()));
|
||||
//RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random()));
|
||||
scene.AddActor(Melona);
|
||||
}
|
||||
|
||||
|
|
@ -224,6 +239,10 @@ public class GameCore implements GameLogic {
|
|||
|
||||
@Override
|
||||
public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
|
||||
Actor player = Actor.Actors.get(PlayerActorID);
|
||||
if(player != null){
|
||||
player.TickUpdate();
|
||||
}
|
||||
engineInstance.scene().CameraTick(FrameDiffNanoSeconds);
|
||||
if(ChangeGraphicsSettings){
|
||||
if(NextAAMode != -1){
|
||||
|
|
@ -248,6 +267,8 @@ public class GameCore implements GameLogic {
|
|||
KeyboardInput input = window.getKeyboardInput();
|
||||
float MovementDist = (float)(FrameDiffNanoSeconds / 1000000L) * MOVEMENT_SPEED;
|
||||
Camera camera = scene.GetCamera();
|
||||
PlayerActor playerActor = (PlayerActor) Actor.Actors.get(PlayerActorID);
|
||||
if(playerActor!= null)camera = Camera.GetCamera(playerActor.AttachedCameraID);
|
||||
if(input.keyPressed(GLFW_KEY_ENTER)) {
|
||||
SpawnNewActor(engineInstance, new Vector3f( (float)(5 * Math.random()),20 + (float)(10 * Math.random()), (float)(5 * Math.random())),new Vector3f(-1f + (float)(2 * Math.random()),-1f + (float)(2 * Math.random()),-1f + (float)(2 * Math.random())),new Vector3f((float)Math.random(),(float)Math.random(),(float)Math.random()));
|
||||
}
|
||||
|
|
@ -269,22 +290,30 @@ public class GameCore implements GameLogic {
|
|||
EngineConfig.getInstance().SetRenderCollisionMesh(!EngineConfig.getInstance().RenderCollisionMeshes());
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_W)){
|
||||
camera.MoveForward(MovementDist);
|
||||
if(playerActor == null)camera.MoveForward(MovementDist);
|
||||
else playerActor.Move(new Vector3f(MovementDist* (float)Math.sin((camera.GetRotation().y)),0,-MovementDist* (float)Math.cos((camera.GetRotation().y))));
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_S)){
|
||||
camera.MoveBackward(MovementDist);
|
||||
if(playerActor == null)camera.MoveBackward(MovementDist);
|
||||
else playerActor.Move(new Vector3f(-MovementDist* (float)Math.sin((camera.GetRotation().y)),0,MovementDist * (float)Math.cos((camera.GetRotation().y))));
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_A)){
|
||||
camera.MoveLeft(MovementDist);
|
||||
if(playerActor == null) camera.MoveLeft(MovementDist);
|
||||
else playerActor.Move(new Vector3f(-MovementDist * (float)Math.cos((camera.GetRotation().y)),0,-MovementDist * (float)Math.sin((camera.GetRotation().y))));
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_D)){
|
||||
camera.MoveRight(MovementDist);
|
||||
if(playerActor == null)camera.MoveRight(MovementDist);
|
||||
else playerActor.Move(new Vector3f(MovementDist * (float)Math.cos((camera.GetRotation().y)),0,MovementDist * (float)Math.sin((camera.GetRotation().y))));
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_SPACE)){
|
||||
camera.MoveUp(MovementDist);
|
||||
if(playerActor == null)camera.MoveUp(MovementDist);
|
||||
}
|
||||
if(input.keySinglePress(GLFW_KEY_SPACE)){
|
||||
// camera.MoveUp(MovementDist);
|
||||
if(playerActor != null)playerActor.Move(new Vector3f(0,5f,0));
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_LEFT_SHIFT)){
|
||||
camera.MoveDown(MovementDist);
|
||||
if(playerActor == null)camera.MoveDown(MovementDist);
|
||||
}
|
||||
if(input.keyPressed(GLFW_KEY_LEFT_CONTROL)){
|
||||
camera.Sprint(true);
|
||||
|
|
@ -340,7 +369,7 @@ public class GameCore implements GameLogic {
|
|||
if(PrimaryRuntime.GetFastThread().Ticks(20)==0){
|
||||
//CollisionManager.UpdateCollisionChunks();
|
||||
}
|
||||
WorldPhysicsManager.SteppedPhysicsTick2(DeltaTime, PhysicsFramerate);
|
||||
WorldPhysicsManager.PhysicsTick2(DeltaTime, PhysicsFramerate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public class Actor{
|
|||
private final String ModelID;
|
||||
private final Matrix4f ModelMatrix;
|
||||
private final Vector3f Position;
|
||||
private final Vector3f PositionOffset;
|
||||
private final Quaternionf Rotation;
|
||||
private CollisionMesh collisionMesh;
|
||||
private Vector3f Scale;
|
||||
|
|
@ -51,6 +52,7 @@ public class Actor{
|
|||
ActorNames.add(ID);
|
||||
this.ModelID = ModelID;
|
||||
this.Position = Position;
|
||||
this.PositionOffset = new Vector3f();
|
||||
TemporaryVector = new Vector3f();
|
||||
PivotOffset = new Vector3f();
|
||||
AdditionalPivotOffset = new Vector3f();
|
||||
|
|
@ -61,6 +63,20 @@ public class Actor{
|
|||
Actors.put(ID,this);
|
||||
}
|
||||
|
||||
public Vector3f GetPositionOffset(){
|
||||
return PositionOffset;
|
||||
}
|
||||
|
||||
public Actor SetPositionOffset(Vector3f PositionOffset){
|
||||
this.PositionOffset.set(PositionOffset);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Actor SetPositionOffset(float x, float y, float z){
|
||||
this.PositionOffset.set(x,y,z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Vector3f GetAditionalPivotOffset(){return AdditionalPivotOffset;}
|
||||
|
||||
public Actor SetAditionalPivotOffset(Vector3f offset){
|
||||
|
|
@ -75,6 +91,10 @@ public class Actor{
|
|||
return this;
|
||||
}
|
||||
|
||||
public void TickUpdate() {
|
||||
|
||||
}
|
||||
|
||||
public IPhysicsController GetPhysicsController(){return physicsController;}
|
||||
|
||||
public Actor CreatePhysicsController(ConvexMesh mesh, float Mass){
|
||||
|
|
@ -106,6 +126,13 @@ public class Actor{
|
|||
UpdateModelMatrix();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Actor SetRotMatrix(Vector3f rot){
|
||||
Rotation.set(0,0,0,1.0f);
|
||||
SetRotation(rot);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Actor SetRotation(Vector3f rot){
|
||||
Rotation.rotateX(rot.x);
|
||||
Rotation.rotateY(rot.y);
|
||||
|
|
@ -146,7 +173,8 @@ public class Actor{
|
|||
|
||||
public void UpdateModelMatrix(){
|
||||
ModelMatrix.translateLocal(TemporaryVector.set(PivotOffset).add(AdditionalPivotOffset));
|
||||
ModelMatrix.translationRotateScale(Position, Rotation, Scale);
|
||||
ModelMatrix.translationRotateScale(new Vector3f(Position), Rotation, Scale);
|
||||
ModelMatrix.translate(PositionOffset);
|
||||
ModelMatrix.translateLocal(TemporaryVector.negate());
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,12 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
|||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Camera {
|
||||
public static final Map<String, Camera> CameraRegistry = new HashMap<>();
|
||||
|
||||
private final Vector3f Direction;
|
||||
private final Vector3f Position;
|
||||
private final Vector3f Right;
|
||||
|
|
@ -13,12 +18,13 @@ public class Camera {
|
|||
private final Matrix4f ViewMatrix;
|
||||
private float FOV = (float) (60 * EngineConfig.DegToRad);
|
||||
private boolean Sprint;
|
||||
private final String ID;
|
||||
|
||||
public Vector3f GetDirection(){
|
||||
return Direction;
|
||||
}
|
||||
public Camera CloneCamera(){
|
||||
Camera NewCam = new Camera();
|
||||
public Camera CloneCamera(String CameraName){
|
||||
Camera NewCam = new Camera(CameraName);
|
||||
NewCam.SetPosition(Position.x, Position.y, Position.z);
|
||||
NewCam.SetRotation(Rotation.x, Rotation.y, Rotation.z);
|
||||
NewCam.Right.set(new Vector3f(Right));
|
||||
|
|
@ -29,13 +35,23 @@ public class Camera {
|
|||
return NewCam;
|
||||
}
|
||||
|
||||
public Camera(){
|
||||
public static Camera GetCamera(String CameraID){
|
||||
return CameraRegistry.get(CameraID);
|
||||
}
|
||||
|
||||
public String GetID(){
|
||||
return ID;
|
||||
}
|
||||
|
||||
public Camera(String CameraName){
|
||||
Direction = new Vector3f();
|
||||
Position = new Vector3f();
|
||||
Right = new Vector3f();
|
||||
Rotation = new Vector3f();
|
||||
Up = new Vector3f();
|
||||
ViewMatrix = new Matrix4f();
|
||||
ID = CameraName;
|
||||
CameraRegistry.put(CameraName,this);
|
||||
}
|
||||
|
||||
public Camera SetFOVrad(float FOVradians){
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
package net.halbear.Terrain4J.EngineCore.Main.Scene;
|
||||
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody;
|
||||
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
public class PlayerActor extends Actor{
|
||||
|
||||
public String AttachedCameraID;
|
||||
public final Vector3f CameraOffset = new Vector3f(0,0,0);
|
||||
Camera PlayerCam;
|
||||
|
||||
public PlayerActor(String AttachedCameraID, String ID, String ModelID, Vector3f Position) {
|
||||
this.AttachedCameraID = AttachedCameraID;
|
||||
PlayerCam = Camera.CameraRegistry.get(AttachedCameraID);
|
||||
super(ID, ModelID, Position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Actor CreatePhysicsController(ConvexMesh mesh, float Mass){
|
||||
super.CreatePhysicsController(mesh,Mass);
|
||||
RigidPhysicsController controller = (RigidPhysicsController)GetPhysicsController();
|
||||
controller.ApplyRotation = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public PlayerActor SetCameraOffset(Vector3f Offset){
|
||||
CameraOffset.set(Offset);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void TickUpdate(){
|
||||
Vector3f Rotation = PlayerCam.GetRotation();
|
||||
Vector3f Position = new Vector3f(GetPosition());
|
||||
GetRotation().identity().rotateYXZ(-Rotation.y, -Rotation.x, Rotation.z);
|
||||
UpdateModelMatrix();
|
||||
if(Position == null || CameraOffset == null) return;
|
||||
Position.add(CameraOffset);
|
||||
PlayerCam.SetPosition(Position.x, Position.y, Position.z);
|
||||
}
|
||||
|
||||
public void Move(Vector3f Velocity){
|
||||
if(PhysicsType == PhysicsControllerType.RigidBodySeparatingAxisTheory) {
|
||||
RigidPhysicsController physicsController = (RigidPhysicsController) GetPhysicsController();
|
||||
RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.add(Velocity);
|
||||
}
|
||||
}
|
||||
|
||||
/* @Override
|
||||
public void UpdateModelMatrix(){
|
||||
if(PlayerCam != null){
|
||||
Vector3f Rotation = PlayerCam.GetRotation();
|
||||
Vector3f Position = new Vector3f(GetPosition());
|
||||
SetRotMatrix(new Vector3f(Rotation.x,Rotation.y,Rotation.z));
|
||||
super.UpdateModelMatrix();
|
||||
if(Position == null || CameraOffset == null) return;
|
||||
Position.add(CameraOffset);
|
||||
PlayerCam.SetPosition(Position.x, Position.y, Position.z);
|
||||
} else{
|
||||
super.UpdateModelMatrix();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ public class Scene implements IScene {
|
|||
ActiveActors = new ArrayList<>();
|
||||
CameraFrames = new HashMap<>();
|
||||
var EngConfig = EngineConfig.getInstance();
|
||||
camera = new Camera();
|
||||
camera = new Camera("DebugCamera");
|
||||
LastCameraFrame = new CameraFrame(camera.GetPosition(),camera.GetRotation(),camera.GetFOV(), "NO_FRAME");
|
||||
Projection = new Project3D(camera.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(),
|
||||
window.getWidth(), window.getHeight());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue