From d53dca94a566f5856c4f934b3901bb6432f388d0 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 31 May 2020 14:07:06 +0200 Subject: [PATCH] [DEV] basic AABB collision --- src/org/atriaSoft/etk/math/Vector3f.java | 9 +- src/org/atriaSoft/gale/test/sample2/Log.java | 3 +- .../atriaSoft/gameEngine/Environement.java | 3 +- src/org/atriaSoft/gameEngine/Log.java | 1 + .../components/ComponentGravity.java | 16 ++++ .../components/ComponentGravityStatic.java | 23 ++++++ .../components/ComponentPhysics.java | 82 +++++++++++++++++-- .../gameEngine/engines/EngineGravity.java | 66 +++++++++++++++ .../gameEngine/engines/EnginePhysics.java | 39 ++++++--- .../atriaSoft/gameEngine/map/MapVoxel.java | 2 +- .../gameEngine/physics/GravityMap.java | 7 ++ .../physics/PhysicCollisionAABB.java | 3 + .../sample/LoxelEngine/LoxelApplication.java | 13 ++- 13 files changed, 245 insertions(+), 22 deletions(-) create mode 100644 src/org/atriaSoft/gameEngine/components/ComponentGravity.java create mode 100644 src/org/atriaSoft/gameEngine/components/ComponentGravityStatic.java create mode 100644 src/org/atriaSoft/gameEngine/engines/EngineGravity.java create mode 100644 src/org/atriaSoft/gameEngine/physics/GravityMap.java diff --git a/src/org/atriaSoft/etk/math/Vector3f.java b/src/org/atriaSoft/etk/math/Vector3f.java index 2956ddf..270f8f2 100644 --- a/src/org/atriaSoft/etk/math/Vector3f.java +++ b/src/org/atriaSoft/etk/math/Vector3f.java @@ -147,19 +147,24 @@ public class Vector3f { } /** * @brief Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0,0)) + * @return the current vector */ - public void safeNormalize() { + public Vector3f safeNormalize() { float length = length(); if (length != 0.0f) { this.devide(length); + return this; } this.setValue(1,0,0); + return this; } /** * @brief Normalize this vector x^2 + y^2 + z^2 = 1 + * @return the current vector */ - public void normalize() { + public Vector3f normalize() { this.devide(this.length()); + return this; } /** * @brief Return a normalized version of this vector diff --git a/src/org/atriaSoft/gale/test/sample2/Log.java b/src/org/atriaSoft/gale/test/sample2/Log.java index f069a03..619d4f7 100644 --- a/src/org/atriaSoft/gale/test/sample2/Log.java +++ b/src/org/atriaSoft/gale/test/sample2/Log.java @@ -1,12 +1,13 @@ package org.atriaSoft.gale.test.sample2; public class Log { - private static String LIBNAME = "Sample1"; + private static String LIBNAME = "Sample2"; public static void print(String data) { System.out.println(data); } public static void critical(String data) { System.out.println("[C] " + LIBNAME + " | " + data); + System.exit(-1); } public static void error(String data) { System.out.println("[E] " + LIBNAME + " | " + data); diff --git a/src/org/atriaSoft/gameEngine/Environement.java b/src/org/atriaSoft/gameEngine/Environement.java index f7b9800..2d81ac5 100644 --- a/src/org/atriaSoft/gameEngine/Environement.java +++ b/src/org/atriaSoft/gameEngine/Environement.java @@ -18,6 +18,7 @@ import org.atriaSoft.gameEngine.camera.Camera; import org.atriaSoft.gameEngine.engines.EngineRender; import org.atriaSoft.gameEngine.engines.EngineAI; import org.atriaSoft.gameEngine.engines.EngineDynamicMeshs; +import org.atriaSoft.gameEngine.engines.EngineGravity; import org.atriaSoft.gameEngine.engines.EngineLight; import org.atriaSoft.gameEngine.engines.EngineParticle; import org.atriaSoft.gameEngine.engines.EnginePhysics; @@ -41,7 +42,7 @@ public class Environement { //protected List listMeshToDrawFirst = new ArrayList(); public Environement() { - // we add the 4 classical engines (the order is used to the global rendering cycle ... + addEngine(new EngineGravity(this)); addEngine(new EnginePlayer(this)); addEngine(new EngineAI(this)); addEngine(new EngineDynamicMeshs(this)); diff --git a/src/org/atriaSoft/gameEngine/Log.java b/src/org/atriaSoft/gameEngine/Log.java index 9e8e907..ba1b7f4 100644 --- a/src/org/atriaSoft/gameEngine/Log.java +++ b/src/org/atriaSoft/gameEngine/Log.java @@ -7,6 +7,7 @@ public class Log { } public static void critical(String data) { System.out.println("[C] " + LIBNAME + " | " + data); + System.exit(-1); } public static void error(String data) { System.out.println("[E] " + LIBNAME + " | " + data); diff --git a/src/org/atriaSoft/gameEngine/components/ComponentGravity.java b/src/org/atriaSoft/gameEngine/components/ComponentGravity.java new file mode 100644 index 0000000..920dd10 --- /dev/null +++ b/src/org/atriaSoft/gameEngine/components/ComponentGravity.java @@ -0,0 +1,16 @@ +package org.atriaSoft.gameEngine.components; + +import org.atriaSoft.etk.math.Vector3f; +import org.atriaSoft.gameEngine.Component; +import org.atriaSoft.gameEngine.Light; + +public abstract class ComponentGravity extends Component { + public ComponentGravity() { + super(); + } + @Override + public String getType() { + return "gravity"; + } + public abstract Vector3f getGravityAtPosition(Vector3f position); +} diff --git a/src/org/atriaSoft/gameEngine/components/ComponentGravityStatic.java b/src/org/atriaSoft/gameEngine/components/ComponentGravityStatic.java new file mode 100644 index 0000000..4ce2158 --- /dev/null +++ b/src/org/atriaSoft/gameEngine/components/ComponentGravityStatic.java @@ -0,0 +1,23 @@ +package org.atriaSoft.gameEngine.components; + +import org.atriaSoft.etk.math.Vector3f; +import org.atriaSoft.gameEngine.Component; +import org.atriaSoft.gameEngine.Light; + +public class ComponentGravityStatic extends ComponentGravity { + private Vector3f gravity; + public ComponentGravityStatic(Vector3f gravity) { + super(); + this.gravity = gravity; + } + @Override + public Vector3f getGravityAtPosition(Vector3f position) { + return gravity; + } + public Vector3f getGravity() { + return gravity; + } + public void setGravity(Vector3f gravity) { + this.gravity = gravity; + } +} diff --git a/src/org/atriaSoft/gameEngine/components/ComponentPhysics.java b/src/org/atriaSoft/gameEngine/components/ComponentPhysics.java index 9c42779..9b6ef31 100644 --- a/src/org/atriaSoft/gameEngine/components/ComponentPhysics.java +++ b/src/org/atriaSoft/gameEngine/components/ComponentPhysics.java @@ -5,10 +5,12 @@ import java.util.List; import org.atriaSoft.etk.Color; import org.atriaSoft.etk.math.Matrix4f; +import org.atriaSoft.etk.math.Vector3f; import org.atriaSoft.gale.backend3d.OpenGL; import org.atriaSoft.gale.resource.ResourceColored3DObject; import org.atriaSoft.gale.test.sample2.Log; import org.atriaSoft.gameEngine.Component; +import org.atriaSoft.gameEngine.engines.EngineGravity; import org.atriaSoft.gameEngine.physics.PhysicCollisionAABB; import org.atriaSoft.gameEngine.physics.PhysicShape; @@ -16,12 +18,28 @@ import entities.Entity; public class ComponentPhysics extends Component { private PhysicCollisionAABB aabb; + private List aabbIntersection = new ArrayList(); private List shapes = new ArrayList(); private ComponentPosition position; + private boolean manageGravity = false; + public static float globalMaxSpeed = Float.MAX_VALUE; + private float maxSpeed = globalMaxSpeed; + // current speed of the object + private Vector3f speed = new Vector3f(0,0,0); + // current acceleration of the object + private Vector3f acceleration = new Vector3f(0,0,0); + // Applied static force on it + private Vector3f staticForce = new Vector3f(0,0,0); + // Apply dynamic force on it + private Vector3f dynamicForce = new Vector3f(0,0,0); @Override public String getType() { return "physics"; } + + public ComponentPhysics(boolean manageGravity) { + this.manageGravity = manageGravity; + } @Override public void addFriendComponent(Component component) { if (component.getType().contentEquals("position")) { @@ -46,16 +64,45 @@ public class ComponentPhysics extends Component { aabb = aabb_new; } - public PhysicCollisionAABB getcurrentAABB() { + public PhysicCollisionAABB getAABB() { return aabb; } - public void applyForces(float timeStep) { - // TODO Auto-generated method stub - + + public void applyForces(float timeStep, EngineGravity gravity) { + // get the gravity at the specific position... + Vector3f gravityForce; + if (manageGravity == true) { + gravityForce = gravity.getGravityAtPosition(position.getTransform().getPosition()).multiply_new(timeStep); + } else { + gravityForce = new Vector3f(0,0,0); + } + // apply this force on the Object + Log.info("apply gravity: " + gravityForce); + // relative to the object + Vector3f staticForce = this.staticForce.multiply_new(timeStep); + float globalMass = 0; + for (PhysicShape shape : shapes) { + globalMass += shape.getMass(); + } + // note the acceleration is not real, it depend on the current delta time... + this.acceleration = gravityForce.add(this.position.getTransform().getOrientation().multiply(staticForce)).add(this.position.getTransform().getOrientation().multiply(dynamicForce)).multiply(globalMass); + this.dynamicForce = new Vector3f(0,0,0); + this.speed.add(this.acceleration); + limitWithMaxSpeed(); + Log.info("apply acceleration: " + this.acceleration); + Log.info("apply speed: " + this.speed); + this.position.getTransform().getPosition().add(this.speed.multiply_new(timeStep)); } + public void renderDebug(ResourceColored3DObject debugDrawProperty) { + Color displayColor; + if (this.aabbIntersection.size() == 0) { + displayColor = new Color(1,1,1,1); + } else { + displayColor = new Color(1,0,0,1); + } if (aabb != null) { - debugDrawProperty.drawCubeLine(aabb.getMin(), aabb.getMax(), new Color(1,1,1,1), Matrix4f.identity(), true, true); + debugDrawProperty.drawCubeLine(aabb.getMin(), aabb.getMax(), displayColor, Matrix4f.identity(), true, true); //debugDrawProperty.drawCubeLine(new Vector3f(0,0,0), new Vector3f(32,32,32), new Color(1,0,1,1), Matrix4f.identity(), true, true); } else { Log.error("no AABB"); @@ -70,4 +117,29 @@ public class ComponentPhysics extends Component { public void clearShape() { shapes.clear(); } + public boolean isManageGravity() { + return manageGravity; + } + public void setManageGravity(boolean manageGravity) { + this.manageGravity = manageGravity; + } + private void limitWithMaxSpeed() { + if (this.speed.length2() > this.maxSpeed*this.maxSpeed) { + this.speed.safeNormalize().multiply(this.maxSpeed); + } + } + public float getMaxSpeed() { + return maxSpeed; + } + + public void setMaxSpeed(float maxSpeed) { + this.maxSpeed = maxSpeed; + } + + public void clearAABBIntersection() { + this.aabbIntersection.clear(); + } + public void addIntersection(ComponentPhysics component) { + this.aabbIntersection.add(component); + } } diff --git a/src/org/atriaSoft/gameEngine/engines/EngineGravity.java b/src/org/atriaSoft/gameEngine/engines/EngineGravity.java new file mode 100644 index 0000000..d7694ab --- /dev/null +++ b/src/org/atriaSoft/gameEngine/engines/EngineGravity.java @@ -0,0 +1,66 @@ +package org.atriaSoft.gameEngine.engines; + +import java.util.Vector; + +import org.atriaSoft.etk.math.Vector3f; +import org.atriaSoft.gameEngine.Component; +import org.atriaSoft.gameEngine.Engine; +import org.atriaSoft.gameEngine.Environement; +import org.atriaSoft.gameEngine.Light; +import org.atriaSoft.gameEngine.Log; +import org.atriaSoft.gameEngine.camera.Camera; +import org.atriaSoft.gameEngine.components.ComponentAI; +import org.atriaSoft.gameEngine.components.ComponentGravity; +import org.atriaSoft.gameEngine.components.ComponentLight; +import org.atriaSoft.gameEngine.components.ComponentLightSun; + +public class EngineGravity extends Engine { + public static final String ENGINE_NAME = "gravity"; + private Vector components = new Vector(); + public EngineGravity(Environement env) { + super(env); + // TODO Auto-generated constructor stub + } + + @Override + public void componentRemove(Component ref) { + components.remove(ref); + } + + @Override + public void componentAdd(Component ref) { + if (ref instanceof ComponentGravity == true) { + components.add((ComponentGravity)ref); + return; + } + } + + @Override + public void update(long deltaMili) { + // nothing to do ... + } + + @Override + public void render(long deltaMili, Camera camera) { + // nothing to do ... + } + + @Override + public void renderDebug(long deltaMili, Camera camera) { + // nothing to do ... + } + + @Override + public String getType() { + // TODO Auto-generated method stub + return ENGINE_NAME; + } + public Vector3f getGravityAtPosition(Vector3f position) { + Vector3f out = new Vector3f(); + for (ComponentGravity elem: components) { + out.add(elem.getGravityAtPosition(position)); + } + return out; + } + +} diff --git a/src/org/atriaSoft/gameEngine/engines/EnginePhysics.java b/src/org/atriaSoft/gameEngine/engines/EnginePhysics.java index 81d4364..a51d9b5 100644 --- a/src/org/atriaSoft/gameEngine/engines/EnginePhysics.java +++ b/src/org/atriaSoft/gameEngine/engines/EnginePhysics.java @@ -2,29 +2,29 @@ package org.atriaSoft.gameEngine.engines; import java.util.Vector; -import org.atriaSoft.etk.Color; -import org.atriaSoft.etk.math.Matrix4f; -import org.atriaSoft.etk.math.Vector3f; import org.atriaSoft.gale.resource.ResourceColored3DObject; -import org.atriaSoft.gale.test.sample2.Log; +import org.atriaSoft.gameEngine.Log; import org.atriaSoft.gameEngine.Component; import org.atriaSoft.gameEngine.Engine; import org.atriaSoft.gameEngine.Environement; import org.atriaSoft.gameEngine.camera.Camera; -import org.atriaSoft.gameEngine.components.ComponentAI; import org.atriaSoft.gameEngine.components.ComponentPhysics; -import org.atriaSoft.gameEngine.components.ComponentRender; +import org.atriaSoft.gameEngine.physics.PhysicCollisionAABB; public class EnginePhysics extends Engine { public static final String ENGINE_NAME = "physics"; private float accumulator = 0; - private static float TIME_STEP = 0.02f; + private static float TIME_STEP = 0.005f; + private EngineGravity gravity; private Vector components = new Vector(); private ResourceColored3DObject debugDrawProperty = ResourceColored3DObject.create(); public EnginePhysics(Environement env) { super(env); - // TODO Auto-generated constructor stub + this.gravity = (EngineGravity)env.getEngine("gravity"); + if (this.gravity == null) { + Log.critical("Must initialyse Gravity before physics..."); + } } @Override @@ -47,8 +47,9 @@ public class EnginePhysics extends Engine { // While there is enough accumulated time to take one or several physics steps while (accumulator >= TIME_STEP) { Log.info("update physic ... " + accumulator); - applyForces(TIME_STEP); + //applyForces(TIME_STEP); updateAABB(TIME_STEP); + updateCollisionsAABB(TIME_STEP); updateCollisions(TIME_STEP); GenerateResultCollisionsForces(TIME_STEP); // Decrease the accumulated time @@ -59,7 +60,7 @@ public class EnginePhysics extends Engine { private void applyForces(float timeStep) { for (ComponentPhysics it: components) { - it.applyForces(TIME_STEP); + it.applyForces(TIME_STEP, gravity); } } private void updateAABB(float timeStep) { @@ -67,6 +68,24 @@ public class EnginePhysics extends Engine { it.updateAABB(); } } + private void updateCollisionsAABB(float timeStep) { + // clear all object intersection + for (ComponentPhysics it: components) { + it.clearAABBIntersection(); + } + // update the current object intersection... + for (int iii=0; iii< components.size(); iii++) { + ComponentPhysics current = components.get(iii); + PhysicCollisionAABB currentAABB = current.getAABB(); + for (int jjj=iii+1; jjj< components.size(); jjj++) { + ComponentPhysics remote = components.get(jjj); + if (currentAABB.intersect(components.get(jjj).getAABB()) == true) { + current.addIntersection(remote); + remote.addIntersection(current); + } + } + } + } private void updateCollisions(float timeStep) { } diff --git a/src/org/atriaSoft/gameEngine/map/MapVoxel.java b/src/org/atriaSoft/gameEngine/map/MapVoxel.java index 52cbc95..2094dea 100644 --- a/src/org/atriaSoft/gameEngine/map/MapVoxel.java +++ b/src/org/atriaSoft/gameEngine/map/MapVoxel.java @@ -74,7 +74,7 @@ public class MapVoxel extends EngineMap { new Uri("DATA", "basicMaterial.vert"), new Uri("DATA", "basicMaterial.frag"), (EngineLight)env.getEngine(EngineLight.ENGINE_NAME))); - ComponentPhysics physics = new ComponentPhysics(); + ComponentPhysics physics = new ComponentPhysics(false); PhysicMapVoxel box = new PhysicMapVoxel(tmpVoxelChunk); physics.addShape(box); tmpEntity.addComponent(physics); diff --git a/src/org/atriaSoft/gameEngine/physics/GravityMap.java b/src/org/atriaSoft/gameEngine/physics/GravityMap.java new file mode 100644 index 0000000..dcd04dd --- /dev/null +++ b/src/org/atriaSoft/gameEngine/physics/GravityMap.java @@ -0,0 +1,7 @@ +package org.atriaSoft.gameEngine.physics; + +import org.atriaSoft.etk.math.Vector3f; + +public abstract class GravityMap { + public abstract Vector3f getGravityAtPosition(Vector3f position); +} diff --git a/src/org/atriaSoft/gameEngine/physics/PhysicCollisionAABB.java b/src/org/atriaSoft/gameEngine/physics/PhysicCollisionAABB.java index 10f3465..1507cd5 100644 --- a/src/org/atriaSoft/gameEngine/physics/PhysicCollisionAABB.java +++ b/src/org/atriaSoft/gameEngine/physics/PhysicCollisionAABB.java @@ -19,6 +19,9 @@ public class PhysicCollisionAABB { this.maxZ = maxZ; } public boolean intersect(PhysicCollisionAABB other) { + if (this == other) { + return false; + } if (minX > other.maxX) { return false; } diff --git a/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java b/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java index fc92a28..22949bf 100644 --- a/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java +++ b/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java @@ -20,6 +20,7 @@ import org.atriaSoft.gameEngine.GameStatus; import org.atriaSoft.gameEngine.Light; import org.atriaSoft.gameEngine.Material; import org.atriaSoft.gameEngine.camera.Camera; +import org.atriaSoft.gameEngine.components.ComponentGravityStatic; import org.atriaSoft.gameEngine.components.ComponentLight; import org.atriaSoft.gameEngine.components.ComponentLightSun; import org.atriaSoft.gameEngine.components.ComponentMaterial; @@ -57,14 +58,21 @@ public class LoxelApplication extends Application { } @Override public void onCreate(Context _context) { + // set the system global max speed + ComponentPhysics.globalMaxSpeed = 3; Gale.getContext().grabPointerEvents(true, new Vector2f(0,0)); env = new Environement(); this.canDraw = true; setSize(new Vector2f(800, 600)); - setTitle("Low Poly sample"); + setTitle("Loxel sample"); map = new MapVoxel(this.env); this.env.addEngine(map); map.init(); + + // simple sun to have a global light ... + Entity globalGravity = new Entity(this.env); + globalGravity.addComponent(new ComponentGravityStatic(new Vector3f(0,0,-1))); + env.addEntity(globalGravity); // simple sun to have a global light ... Entity sun = new Entity(this.env); @@ -105,10 +113,11 @@ public class LoxelApplication extends Application { new Uri("DATA", "basicMaterial.vert"), new Uri("DATA", "basicMaterial.frag"), (EngineLight)env.getEngine(EngineLight.ENGINE_NAME))); - ComponentPhysics physics = new ComponentPhysics(); + ComponentPhysics physics = new ComponentPhysics(true); PhysicBox box = new PhysicBox(); box.setSize(new Vector3f(0.6f,0.6f,1.8f)); box.setOrigin(new Vector3f(0,0,0.9f)); + box.setMass(1); physics.addShape(box); player.addComponent(physics); env.addEntity(player);