[DEV] basic AABB collision

This commit is contained in:
Edouard DUPIN 2020-05-31 14:07:06 +02:00
parent e72f6b3449
commit d53dca94a5
13 changed files with 245 additions and 22 deletions

View File

@ -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

View File

@ -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);

View File

@ -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<Mesh> listMeshToDrawFirst = new ArrayList<Mesh>();
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));

View File

@ -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);

View File

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

View File

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

View File

@ -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<ComponentPhysics> aabbIntersection = new ArrayList<ComponentPhysics>();
private List<PhysicShape> shapes = new ArrayList<PhysicShape>();
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);
}
}

View File

@ -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<ComponentGravity> components = new Vector<ComponentGravity>();
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;
}
}

View File

@ -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<ComponentPhysics> components = new Vector<ComponentPhysics>();
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) {
}

View File

@ -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);

View File

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

View File

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

View File

@ -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);