Physics corrections

This commit is contained in:
Halbear 2026-07-05 17:56:47 +01:00
parent 2b0344630e
commit eb09963e3a
17 changed files with 1126 additions and 899 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

Binary file not shown.

View file

@ -0,0 +1,15 @@
{
"ID": "Cube",
"Meshes": [
{
"ID": "mesh_0",
"MaterialID": "Cube-mat-1",
"OffsetVertex": 0,
"VertexSize": 1344,
"OffsetIndex": 0,
"IndexSize": 144
}
],
"VertexPath": "resources/models/cube/Cube.vtx",
"IndexPath": "resources/models/cube/Cube.idx"
}

View file

@ -0,0 +1,4 @@
# Made in Blockbench 5.1.4
newmtl m_69683abb-0cbc-2632-be2c-1aa8a2ddc888
map_Kd cubetexture.png
newmtl none

View file

@ -0,0 +1,49 @@
# Made in Blockbench 5.1.4
mtllib Cube.mtl
o mesh
v 0.5 0.75 0.5
v 0.5 0.75 -0.5
v 0.5 -0.25 0.5
v 0.5 -0.25 -0.5
v -0.5 0.75 0.5
v -0.5 0.75 -0.5
v -0.5 -0.25 0.5
v -0.5 -0.25 -0.5
vt 0.25 1
vt 0 1
vt 0 0.75
vt 0.25 0.75
vt 0.25 0.484375
vt 0.25 0.734375
vt 0 0.734375
vt 0 0.484375
vt 0.265625 0.75
vt 0.515625 0.75
vt 0.515625 1
vt 0.265625 1
vt 0.515625 0.484375
vt 0.515625 0.734375
vt 0.265625 0.734375
vt 0.265625 0.484375
vt 0.25 0.21875
vt 0.25 0.46875
vt 0 0.46875
vt 0 0.21875
vt 0.78125 1
vt 0.53125 1
vt 0.53125 0.75
vt 0.78125 0.75
vn 1 0 0
vn -1 0 0
vn 0 1 0
vn 0 -1 0
vn 0 0 1
vn 0 0 -1
usemtl m_69683abb-0cbc-2632-be2c-1aa8a2ddc888
f 2/1/1 1/2/1 3/3/1 4/4/1
f 7/5/2 5/6/2 6/7/2 8/8/2
f 5/9/3 1/10/3 2/11/3 6/12/3
f 4/13/4 3/14/4 7/15/4 8/16/4
f 3/17/5 1/18/5 5/19/5 7/20/5
f 6/21/6 2/22/6 4/23/6 8/24/6

Binary file not shown.

View file

@ -0,0 +1,44 @@
[
{
"ID": "Cube-mat-0",
"TexturePath": "",
"NormalTexturePath": "",
"MetalRoughnessMap": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
},
"Roughness": 0.0,
"Metallic": 0.0
},
{
"ID": "Cube-mat-1",
"TexturePath": "resources\\models\\cube\\cubetexture.png",
"NormalTexturePath": "",
"MetalRoughnessMap": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
},
"Roughness": 0.0,
"Metallic": 0.0
},
{
"ID": "Cube-mat-2",
"TexturePath": "",
"NormalTexturePath": "",
"MetalRoughnessMap": "",
"DiffuseColour": {
"X": 0.6,
"Y": 0.6,
"Z": 0.6,
"W": 1.0
},
"Roughness": 0.0,
"Metallic": 0.0
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -29,7 +29,7 @@ public class RigidBody {
public Vector3f CrossSectionAreas = new Vector3f(1.8f * 0.9f, 0.6f * 0.9f, 1.8f * 0.6f); public Vector3f CrossSectionAreas = new Vector3f(1.8f * 0.9f, 0.6f * 0.9f, 1.8f * 0.6f);
public Vector3f WeightDistribution = new Vector3f(2.0f,5.0f,7.0f); public Vector3f WeightDistribution = new Vector3f(2.0f,5.0f,7.0f);
public float FallingAcceleration = 0.0f; public float FallingAcceleration = 0.0f;
public float Bounciness = 1f; public float Bounciness = 0.3f;
public final Vector3f LinearVelocity = new Vector3f(); public final Vector3f LinearVelocity = new Vector3f();
public final Vector3f AngularVelocity = new Vector3f(); public final Vector3f AngularVelocity = new Vector3f();

View file

@ -6,7 +6,7 @@ import org.joml.Vector3f;
//Resolves the Separating Axis Theorem Test into reaction forces in impulses and position correction //Resolves the Separating Axis Theorem Test into reaction forces in impulses and position correction
public class RigidCollision { public class RigidCollision {
private static final float CORRECTION_THRESHOLD = 1.0f; //how much it gets corrected positionally per physics step private static final float CORRECTION_THRESHOLD = 1.0f; //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 SLOP = 0.000f; // amount of overlap can happen before collision gets corrected
public synchronized static void ResolveCollision(RigidBody body1, RigidBody body2, SeparatingAxisTheoremTester.CollisionResult collisionResult){ public synchronized static void ResolveCollision(RigidBody body1, RigidBody body2, SeparatingAxisTheoremTester.CollisionResult collisionResult){
Vector3f Normal = collisionResult.Normal; Vector3f Normal = collisionResult.Normal;
@ -43,6 +43,9 @@ public class RigidCollision {
float j = -(1 + Restitution) * VelocityAlongNormal / InverseMassSum; float j = -(1 + Restitution) * VelocityAlongNormal / InverseMassSum;
Impulse.set(normal).mul(j); 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,body1.LinearVelocity.y < 0 ? 1 : -1,-1).mul(body1.Bounciness,body1.LinearVelocity.y < 0 ? 1 : body1.Bounciness,body1.Bounciness);
body1.ApplyImpulse(NegatedImpulse.set(Impulse).negate(), Point); body1.ApplyImpulse(NegatedImpulse.set(Impulse).negate(), Point);
body2.ApplyImpulse(Impulse,Point); body2.ApplyImpulse(Impulse,Point);

View file

@ -25,9 +25,17 @@ public class RigidPhysicsController implements IPhysicsController {
public final List<String> Collisions = new ArrayList<>(); public final List<String> Collisions = new ArrayList<>();
public static RigidBody Ground = new RigidBody("FLOOR",ConvexMesh.Box(100,100f,100),0); 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);
public static RigidBody Wall2 = new RigidBody("WALL2",ConvexMesh.Box(100,100f,10),0);
public static RigidBody Wall3 = new RigidBody("WALL3",ConvexMesh.Box(10,100f,100),0);
public static RigidBody Wall4 = new RigidBody("WALL4",ConvexMesh.Box(10,100f,100),0);
static { static {
Ground.Position.set(0,-100f,0); Ground.Position.set(0,-100f,0);
Wall.Position.set(0,0f,-60f);
Wall2.Position.set(0,0f,60f);
Wall3.Position.set(-60f,0f,0);
Wall4.Position.set(60f,0f,0);
} }
public String RigidBodyID = "NULL"; public String RigidBodyID = "NULL";
@ -49,6 +57,12 @@ public class RigidPhysicsController implements IPhysicsController {
newRigidBody.UpdateInertiaWorld(); newRigidBody.UpdateInertiaWorld();
WorldPhysicsManager.PhysicsObjects.put(ControllerID, this); WorldPhysicsManager.PhysicsObjects.put(ControllerID, this);
WorldPhysicsManager.ActiveControllers.add(ControllerID); WorldPhysicsManager.ActiveControllers.add(ControllerID);
if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") {
RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID);
if (Actor.Actors.get(ActorID) != null) {
Actor.Actors.get(ActorID).SetPivotOffset(new Vector3f(0, (rigidBody.shape.TopRightForward.y - rigidBody.shape.BottomLeftBack.y) / 2f, 0));
}
}
return this; return this;
} }
@ -56,6 +70,11 @@ public class RigidPhysicsController implements IPhysicsController {
RigidBodyID = rigidBody.GetID(); RigidBodyID = rigidBody.GetID();
WorldPhysicsManager.PhysicsObjects.put(ControllerID, this); WorldPhysicsManager.PhysicsObjects.put(ControllerID, this);
WorldPhysicsManager.ActiveControllers.add(ControllerID); WorldPhysicsManager.ActiveControllers.add(ControllerID);
if( rigidBody != null && ActorID != "NULL") {
if (Actor.Actors.get(ActorID) != null) {
Actor.Actors.get(ActorID).SetPivotOffset(new Vector3f(0, (rigidBody.shape.TopRightForward.y - rigidBody.shape.BottomLeftBack.y) / 2f, 0));
}
}
return this; return this;
} }
@ -77,7 +96,7 @@ public class RigidPhysicsController implements IPhysicsController {
@Override @Override
public void PhysicsTick(float DeltaTime, float TargetFrameRate) { public void PhysicsTick(float DeltaTime, float TargetFrameRate) {
DeltaTime/=10f; DeltaTime/=10f;
if(DeltaTime >0.1f) DeltaTime = 0.1f; // if(DeltaTime >0.1f) DeltaTime = 0.1f;
if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") { if(RigidBodyID != null && RigidBodyRegister.get(RigidBodyID) != null && ActorID != "NULL") {
RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID); RigidBody rigidBody = RigidBodyRegister.get(RigidBodyID);
rigidBody.Integrate(DeltaTime, new Vector3f(0,-1.8f,0)); rigidBody.Integrate(DeltaTime, new Vector3f(0,-1.8f,0));
@ -91,7 +110,6 @@ public class RigidPhysicsController implements IPhysicsController {
} }
} }
if(Actor.Actors.get(ActorID) != null) { if(Actor.Actors.get(ActorID) != null) {
Actor.Actors.get(ActorID).SetPivotOffset(new Vector3f(0,(rigidBody.shape.TopRightForward.y - rigidBody.shape.BottomLeftBack.y)/2f,0));
Actor.Actors.get(ActorID).SetPosition(new Vector3f(rigidBody.Position)); Actor.Actors.get(ActorID).SetPosition(new Vector3f(rigidBody.Position));
Actor.Actors.get(ActorID).SetRotation(rigidBody.Rotation); Actor.Actors.get(ActorID).SetRotation(rigidBody.Rotation);
} }

View file

@ -36,12 +36,12 @@ public class SeparatingAxisTheoremTester {
public final List<Contact> Contacts = new ArrayList<>(); public final List<Contact> Contacts = new ArrayList<>();
} }
//as much as i'd like to multithread the fuck out of this, im putting it as synchronised so it doesn't get messy, and so memory management is smoother, i want to minimize the amount of Vectors creating during loops //as much as i'd like to multithread the fuck out of this, im putting it as synchronised so it doesn't get messy, and so memory management is smoother, i want to minimize the amount of Vectors creating during loops
public synchronized static CollisionResult TestCollision(ConvexMesh Mesh1, ConvexMesh Mesh2){ public static CollisionResult TestCollision(ConvexMesh Mesh1, ConvexMesh Mesh2){
float BestOverlap = Float.MAX_VALUE; float BestOverlap = Float.MAX_VALUE;
Vector3f BestAxis = null; Vector3f BestAxis = null;
ConvexMesh.Face BestFace =null; ConvexMesh.Face BestFace =null;
ConvexMesh BestFaceOwner = null; ConvexMesh BestFaceOwner = null;
if(Mesh1 == null || Mesh2 == null) return null;
for(ConvexMesh.Face face : Mesh1.Faces){ for(ConvexMesh.Face face : Mesh1.Faces){
Vector3f Axis = Mesh1.WorldFaceNormal(face); Vector3f Axis = Mesh1.WorldFaceNormal(face);
Float Overlap = AxisOverlap(Mesh1,Mesh2,Axis); Float Overlap = AxisOverlap(Mesh1,Mesh2,Axis);
@ -147,14 +147,14 @@ public class SeparatingAxisTheoremTester {
return result; return result;
} }
private synchronized static Float AxisOverlap(ConvexMesh mesh1, ConvexMesh mesh2, Vector3f axis) { private static Float AxisOverlap(ConvexMesh mesh1, ConvexMesh mesh2, Vector3f axis) {
float[] Range1 = ProjectOntoAxis(mesh1, axis); float[] Range1 = ProjectOntoAxis(mesh1, axis);
float[] Range2 = ProjectOntoAxis(mesh2, axis); float[] Range2 = ProjectOntoAxis(mesh2, axis);
float Overlap = Math.min(Range1[1],Range2[1]) - Math.max(Range1[0],Range2[0]); float Overlap = Math.min(Range1[1],Range2[1]) - Math.max(Range1[0],Range2[0]);
return (Overlap < 0) ? null : Overlap; return (Overlap < 0) ? null : Overlap;
} }
private synchronized static float[] ProjectOntoAxis(ConvexMesh mesh, Vector3f axis){ private static float[] ProjectOntoAxis(ConvexMesh mesh, Vector3f axis){
float minimum = Float.MAX_VALUE, maximum = -Float.MAX_VALUE; float minimum = Float.MAX_VALUE, maximum = -Float.MAX_VALUE;
for(int i = 0; i < mesh.LocalVertices.size(); i++){ for(int i = 0; i < mesh.LocalVertices.size(); i++){
float distance = mesh.WorldVertex(i).dot(axis); float distance = mesh.WorldVertex(i).dot(axis);
@ -164,14 +164,14 @@ public class SeparatingAxisTheoremTester {
return new float[]{minimum,maximum}; return new float[]{minimum,maximum};
} }
private synchronized static Vector3f MeshCenter(ConvexMesh mesh){ private static Vector3f MeshCenter(ConvexMesh mesh){
Vector3f Center = new Vector3f(); Vector3f Center = new Vector3f();
for(int i = 0; i < mesh.LocalVertices.size(); i++) Center.add(mesh.WorldVertex(i)); for(int i = 0; i < mesh.LocalVertices.size(); i++) Center.add(mesh.WorldVertex(i));
Center.div(mesh.LocalVertices.size()); Center.div(mesh.LocalVertices.size());
return Center; return Center;
} }
private synchronized static ConvexMesh.Face FindIncidentFace(ConvexMesh mesh, Vector3f ReferenceNormal){ private static ConvexMesh.Face FindIncidentFace(ConvexMesh mesh, Vector3f ReferenceNormal){
ConvexMesh.Face Best = null; ConvexMesh.Face Best = null;
float BestDot = Float.MAX_VALUE; float BestDot = Float.MAX_VALUE;
for(ConvexMesh.Face face : mesh.Faces){ for(ConvexMesh.Face face : mesh.Faces){
@ -184,7 +184,7 @@ public class SeparatingAxisTheoremTester {
return Best; return Best;
} }
private synchronized static List<Vector3f> ClipPolygonAgainstFace(List<Vector3f> Incident, List<Vector3f> ReferencePoly, Vector3f ReferenceNormal){ private static List<Vector3f> ClipPolygonAgainstFace(List<Vector3f> Incident, List<Vector3f> ReferencePoly, Vector3f ReferenceNormal){
List<Vector3f> Output = new ArrayList<>(Incident); List<Vector3f> Output = new ArrayList<>(Incident);
int Count = ReferencePoly.size(); int Count = ReferencePoly.size();
for(int i = 0; i < Count; i++){ for(int i = 0; i < Count; i++){
@ -215,7 +215,7 @@ public class SeparatingAxisTheoremTester {
return Output; return Output;
} }
private synchronized static Vector3f IntersectEdge(Vector3f Vertex1, Vector3f Vertex2, Vector3f Normal, float Offset) { private static Vector3f IntersectEdge(Vector3f Vertex1, Vector3f Vertex2, Vector3f Normal, float Offset) {
Vector3f Distance = new Vector3f(Vertex2).sub(Vertex1); Vector3f Distance = new Vector3f(Vertex2).sub(Vertex1);
float Denominator = Normal.dot(Distance); float Denominator = Normal.dot(Distance);
float t = (Math.abs(Denominator) < T4Math.Math3D.epsilon) ? 0 : (Offset - Normal.dot(Vertex1)) / Denominator; float t = (Math.abs(Denominator) < T4Math.Math3D.epsilon) ? 0 : (Offset - Normal.dot(Vertex1)) / Denominator;
@ -223,7 +223,7 @@ public class SeparatingAxisTheoremTester {
} }
private synchronized static Vector3f[] ClosestPointsSegment2(Vector3f p1, Vector3f q1, Vector3f p2, Vector3f q2) { private static Vector3f[] ClosestPointsSegment2(Vector3f p1, Vector3f q1, Vector3f p2, Vector3f q2) {
Vector3f d1 = new Vector3f(q1).sub(p1); Vector3f d1 = new Vector3f(q1).sub(p1);
Vector3f d2 = new Vector3f(q2).sub(p2); Vector3f d2 = new Vector3f(q2).sub(p2);
Vector3f r = new Vector3f(p1).sub(p2); Vector3f r = new Vector3f(p1).sub(p2);

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Logic.Physics; package net.halbear.Terrain4J.EngineCore.Logic.Physics;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Threads.PhysicsThread;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -21,11 +22,20 @@ public class WorldPhysicsManager {
public static float FixedTimeStep = 1f / 60f; public static float FixedTimeStep = 1f / 60f;
public static int MaxSubStepsPerFrame = 8; public static int MaxSubStepsPerFrame = 8;
private static float Accumulator = 0f; private static float Accumulator = 0f;
private static boolean SingleThread = false;
private static List<PhysicsThread> physicsThreads = new ArrayList<>();
public static void SteppedPhysicsTick(float DeltaTime, float TargetFrameTime){ public static void SteppedPhysicsTick(float DeltaTime, float TargetFrameTime){
int ThreadsNeeded = (int)Math.floor(ActiveControllers.size()/100f);
SingleThread = ThreadsNeeded <= 1;
if(EngineConfig.getInstance().IsEngineThrottled()) return; if(EngineConfig.getInstance().IsEngineThrottled()) return;
DeltaTime *= EngineConfig.getInstance().PhysicsSpeed(); DeltaTime *= EngineConfig.getInstance().PhysicsSpeed();
/* if(!SingleThread && ThreadsNeeded > physicsThreads.size()) {
while(ThreadsNeeded > physicsThreads.size()) {
int Index = physicsThreads.size();
physicsThreads.add(new PhysicsThread("PhysThread"+Index, Index, ThreadsNeeded).StartThread());
}
} else if(SingleThread){*/
Accumulator += DeltaTime; Accumulator += DeltaTime;
float maxAccumulated = FixedTimeStep * MaxSubStepsPerFrame; float maxAccumulated = FixedTimeStep * MaxSubStepsPerFrame;
if (Accumulator > maxAccumulated) Accumulator = maxAccumulated; if (Accumulator > maxAccumulated) Accumulator = maxAccumulated;
@ -45,6 +55,7 @@ public class WorldPhysicsManager {
for (int i = 0; i < ActiveControllers.size(); i++) { for (int i = 0; i < ActiveControllers.size(); i++) {
PhysicsObjects.get(ActiveControllers.get(i)).Collisions().clear(); PhysicsObjects.get(ActiveControllers.get(i)).Collisions().clear();
} }
// }
} }
public static void PhysicsTick(float DeltaTime, float TargetFrameTime){ public static void PhysicsTick(float DeltaTime, float TargetFrameTime){

View file

@ -17,6 +17,8 @@ import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
import net.halbear.Terrain4J.EngineCore.Logic.InitData; import net.halbear.Terrain4J.EngineCore.Logic.InitData;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.LegacyPhysicsController;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.ConvexMesh; 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 net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager; import net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader;
import net.halbear.Terrain4J.EngineCore.Main.Scene.*; import net.halbear.Terrain4J.EngineCore.Main.Scene.*;
@ -76,8 +78,8 @@ public class GameCore implements GameLogic {
public InitData Initialise(EngineInstance engineInstance) { public InitData Initialise(EngineInstance engineInstance) {
IScene scene = engineInstance.scene(); IScene scene = engineInstance.scene();
List<ModelData> models = new ArrayList<>(); List<ModelData> models = new ArrayList<>();
MelonaData = ModelLoader.LoadModel("resources/models/melona/melona.json"); MelonaData = ModelLoader.LoadModel("resources/models/cube/Cube.json");
List<MaterialData> MelonaDataMat = ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json"); List<MaterialData> MelonaDataMat = ModelLoader.LoadMaterials("resources/models/cube/Cube_mat.json");
var Melona = new Actor("Melona", MelonaData.ID(), new Vector3f(0,0f,-5f)).SetRotation(0,(float)Math.toRadians(180),0); var Melona = new Actor("Melona", MelonaData.ID(), new Vector3f(0,0f,-5f)).SetRotation(0,(float)Math.toRadians(180),0);
Melona.CreatePhysicsController(LegacyPhysicsController.CollisionType.Sensor); Melona.CreatePhysicsController(LegacyPhysicsController.CollisionType.Sensor);
/* Melona.GetPhysicsController() /* Melona.GetPhysicsController()
@ -166,7 +168,9 @@ public class GameCore implements GameLogic {
SpawnPosition.add(SpawnDirection); SpawnPosition.add(SpawnDirection);
var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), MelonaData.ID(), new Vector3f(SpawnPosition)); var Melona = new Actor("MelonaSpawned" + scene.GetActors().size(), MelonaData.ID(), new Vector3f(SpawnPosition));
Melona.CreatePhysicsController( ConvexMesh.Box(0.75f,1,0.5f),20); 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()));
scene.AddActor(Melona); scene.AddActor(Melona);
} }
@ -245,7 +249,7 @@ public class GameCore implements GameLogic {
float MovementDist = (float)(FrameDiffNanoSeconds / 1000000L) * MOVEMENT_SPEED; float MovementDist = (float)(FrameDiffNanoSeconds / 1000000L) * MOVEMENT_SPEED;
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
if(input.keyPressed(GLFW_KEY_ENTER)) { if(input.keyPressed(GLFW_KEY_ENTER)) {
SpawnNewActor(engineInstance, new Vector3f( (float)(2 * Math.random()),20 + (float)(10 * Math.random()), (float)(2 * 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())); 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()));
} }
if(input.keyPressed(GLFW_KEY_1)) { if(input.keyPressed(GLFW_KEY_1)) {
Gimbal.universalType = Gimbal.GimbalType.Move; Gimbal.universalType = Gimbal.GimbalType.Move;

View file

@ -0,0 +1,79 @@
package net.halbear.Terrain4J.EngineCore.Threads;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import org.tinylog.Logger;
import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.ActiveControllers;
import static net.halbear.Terrain4J.EngineCore.Logic.Physics.WorldPhysicsManager.PhysicsObjects;
public class PhysicsThread implements Runnable{
public static boolean running = true;
public final Thread EngineThread;
public static float FixedTimeStep = 1f / 60f;
public static int PhysicsTick = 0;
public static int MaxSubStepsPerFrame = 8;
public int Frames = 0;
public int TickFrames = 0;
private static float Accumulator = 0f;
public String ThreadName;
public int Index;
public int Total;
public Thread FetchThread(){
return EngineThread;
}
public PhysicsThread StartThread(){
EngineThread.start();
return this;
}
public PhysicsThread(String ThreadName, int Index, int TotalCount){
this.ThreadName = ThreadName;
Logger.debug("Starting {} Thread",ThreadName);
EngineThread = new Thread(this);
EngineThread.setName("Terrain4J "+ThreadName+" Engine Thread");
this.Index = Index;
this.Total = TotalCount;
}
@Override
public void run() {
long InitialTime = System.nanoTime();
long updateTime = InitialTime;
double[] FrameTimes = new double[]{0,0,0,0};
while(FastTickThread.running && (Index/Total) * ActiveControllers.size() < ActiveControllers.size()){
long now = System.nanoTime();
TickFrames++;
long nsTimeDiff = now - updateTime;
updateTime = now;
float PhysicsFramerate = 24f;
float PhysicsFrameTime = 1000f/PhysicsFramerate;
float DeltaTime = (float)nsTimeDiff/(PhysicsFrameTime*1000000f);
SteppedPhysicsTickMultiThreaded(DeltaTime, 60,Index,Total);
}
}
public static void SteppedPhysicsTickMultiThreaded(float DeltaTime, float TargetFrameTime, int Index, int Total){
Accumulator += DeltaTime;
float maxAccumulated = FixedTimeStep * MaxSubStepsPerFrame;
if (Accumulator > maxAccumulated) Accumulator = maxAccumulated;
int stepsRun = 0;
while (Accumulator >= FixedTimeStep && stepsRun < MaxSubStepsPerFrame) {
PhysicsTick++;
for (int i = (Index/Total) * ActiveControllers.size(); i < Math.min((Index + 1/Total) * ActiveControllers.size(),ActiveControllers.size()); i++) {
if (PhysicsObjects.get(ActiveControllers.get(i)) != null) {
PhysicsObjects.get(ActiveControllers.get(i)).PhysicsTick(FixedTimeStep, TargetFrameTime);
}
}
Accumulator -= FixedTimeStep;
stepsRun++;
}
}
}