[DEV] last development of the 3 physic engine (next step is migration to a generic engine)

This commit is contained in:
Edouard DUPIN 2020-12-18 11:30:03 +01:00
parent 839a2f9c4f
commit 711ef047fc
10 changed files with 177 additions and 63 deletions

View File

@ -117,12 +117,12 @@ public class ComponentPhysics extends Component {
return;
}
for (ComponentPhysics elem : narrowIntersection) {
for (PhysicShape shapeCurrent : shapes) {
for (PhysicShape shapeCurrent : this.shapes) {
//TODO Do a better method we do this many times ...
if (elem.checkCollide(shapeCurrent) == false) {
continue;
}
elem.getCollidePoints(shapeCurrent);
elem.getCollidePoints(shapeCurrent, this.staticObject);
}
}
}
@ -173,13 +173,13 @@ public class ComponentPhysics extends Component {
}
return false;
}
private void getCollidePoints(PhysicShape shapeCurrent) {
private void getCollidePoints(PhysicShape shapeCurrent, boolean isStatic) {
if (shapeCurrent instanceof PhysicBox) {
PhysicBox shape111 = (PhysicBox)shapeCurrent;
for (PhysicShape shape : shapes) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicBox) {
PhysicBox shape222 = (PhysicBox)shape;
ToolCollisionOBBWithOBB.getCollidePoints(shape111, shape222);
ToolCollisionOBBWithOBB.getCollidePoints(shape111, isStatic, shape222, this.staticObject);
} else if (shape instanceof PhysicSphere) {
} else if (shape instanceof PhysicMapVoxel) {
@ -189,7 +189,7 @@ public class ComponentPhysics extends Component {
}
}
} else if (shapeCurrent instanceof PhysicSphere) {
for (PhysicShape shape : shapes) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicBox) {
} else if (shape instanceof PhysicSphere) {
@ -201,7 +201,7 @@ public class ComponentPhysics extends Component {
}
}
} else if (shapeCurrent instanceof PhysicMapVoxel) {
for (PhysicShape shape : shapes) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicBox) {
} else if (shape instanceof PhysicSphere) {
@ -294,6 +294,12 @@ public class ComponentPhysics extends Component {
this.aabbIntersection.clear();
}
public void addIntersection(ComponentPhysics component) {
// do not add multiple times
for (ComponentPhysics elem : this.aabbIntersection) {
if (elem == component) {
return;
}
}
this.aabbIntersection.add(component);
}
public List<ComponentPhysics> getAabbIntersection() {

View File

@ -63,11 +63,19 @@ public class EnginePhysics extends Engine {
it.applyForces(TIME_STEP, gravity);
}
}
/**
* Collision detection STEP 1: Upadte the AABB positioning of each elements
* @param timeStep Delta time since the last check
*/
private void updateAABB(float timeStep) {
for (ComponentPhysics it: components) {
it.updateAABB();
}
}
/**
* Collision Detection STEP 2: update the list of each element that collide together in the AABB Boxs (update is done between each boxes)
* @param timeStep Delta time since the last check
*/
private void updateCollisionsAABB(float timeStep) {
// clear all object intersection
for (ComponentPhysics it: components) {
@ -86,6 +94,10 @@ public class EnginePhysics extends Engine {
}
}
}
/**
* Collision Detection STEP 3: Narrow phase: process the collision between every OBB boxes (or other..)
* @param timeStep Delta time since the last check
*/
private void updateCollisionsNarrowPhase(float timeStep) {
// clear all object intersection
for (ComponentPhysics it: components) {
@ -103,6 +115,10 @@ public class EnginePhysics extends Engine {
current.narrowCollisionCreateContactAndForce();
}
}
/**
* Collision Detection STEP 4: apply all calculated forces (with containts)
* @param timeStep
*/
private void generateResultCollisionsForces(float timeStep) {
}

View File

@ -7,7 +7,6 @@ public class ColisionPoints {
public Vector3f force;
public ColisionPoints(Vector3f position, Vector3f force) {
super();
this.position = position;
this.force = force;
}

View File

@ -0,0 +1,17 @@
package org.atriasoft.gameengine.physics;
public class Collision {
public final ColisionPoints[] colisionPointLocal;
public final PhysicShape shapeRemote;
public final ColisionPoints[] colisionPointRemote;
public final boolean staticRemote;
public Collision(ColisionPoints[] colisionPointLocal, PhysicShape shapeRemote,
ColisionPoints[] colisionPointRemote, boolean staticRemote) {
super();
this.colisionPointLocal = colisionPointLocal;
this.shapeRemote = shapeRemote;
this.colisionPointRemote = colisionPointRemote;
this.staticRemote = staticRemote;
}
}

View File

@ -1,10 +1,14 @@
package org.atriasoft.gameengine.physics;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.math.Matrix4f;
import org.atriasoft.etk.math.Transform3D;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.resource.ResourceColored3DObject;
import org.atriasoft.gameengine.internal.Log;
public class PhysicBox extends PhysicShape {
// Box size property in X, Y and Z
@ -26,6 +30,7 @@ public class PhysicBox extends PhysicShape {
public void updateAABB(Transform3D transformGlobal, PhysicCollisionAABB aabb) {
// store it, many time usefull...
this.transformGlobal = transformGlobal;
this.colisionPoints.clear();
// TODO Auto-generated method stub
aabb.update(transformGlobal.multiply(this.transform.multiply(new Vector3f(this.size.x * 0.5f, this.size.y * 0.5f, this.size.z * 0.5f))));
aabb.update(transformGlobal.multiply(this.transform.multiply(new Vector3f(-this.size.x * 0.5f, this.size.y * 0.5f, this.size.z * 0.5f))));
@ -56,7 +61,7 @@ public class PhysicBox extends PhysicShape {
private void renderPoint(Vector3f subPosition, Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) {
Matrix4f transformation = transformGlobal.getOpenGLMatrix().multiplyNew(this.transform.getOpenGLMatrix()).multiply(Matrix4f.createMatrixTranslate(subPosition));
debugDrawProperty.drawSquare(new Vector3f(0.1f, 0.1f, 0.1f), transformation, new Color(0, 0, 1, 1));
debugDrawProperty.drawSquare(new Vector3f(0.08f, 0.08f, 0.08f), transformation, new Color(0, 0, 1, 1));
}
private void renderPoint2(Vector3f subPosition, Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) {
@ -71,9 +76,12 @@ public class PhysicBox extends PhysicShape {
}
private void renderPoint4(Vector3f subPosition, ResourceColored3DObject debugDrawProperty) {
private void renderPoint4(Vector3f subPosition, Vector3f force, ResourceColored3DObject debugDrawProperty) {
debugDrawProperty.drawSquare(new Vector3f(0.1f, 0.1f, 0.1f), Matrix4f.identity().multiply(Matrix4f.createMatrixTranslate(subPosition)), new Color(1, 0, 0, 1));
List<Vector3f> tmp = new ArrayList<>();
tmp.add(new Vector3f(0,0,0));
tmp.add(force);
debugDrawProperty.drawLine(tmp, new Color(1, 0, 0, 1), Matrix4f.identity().multiply(Matrix4f.createMatrixTranslate(subPosition)), true, false);
}
@Override
@ -88,10 +96,17 @@ public class PhysicBox extends PhysicShape {
renderPoint(new Vector3f(-dimention.x, +dimention.y, -dimention.z), transformGlobal, debugDrawProperty);
renderPoint(new Vector3f(+dimention.x, -dimention.y, -dimention.z), transformGlobal, debugDrawProperty);
renderPoint3(new Vector3f(-dimention.x, -dimention.y, -dimention.z), transformGlobal, debugDrawProperty);
if (this.colisionPointTest != null) {
for (int iii = 0; iii < this.colisionPointTest.length; iii++) {
renderPoint4(this.colisionPointTest[iii].position, debugDrawProperty);
for (Collision elem: this.colisionPoints) {
if (elem != null) {
if (elem.colisionPointLocal == null) {
Log.error("colision point must be set !!!");
continue;
}
for (int iii = 0; iii < elem.colisionPointLocal.length; iii++) {
renderPoint4(elem.colisionPointLocal[iii].position, elem.colisionPointLocal[iii].force, debugDrawProperty);
}
}
}
}
}

View File

@ -17,6 +17,7 @@ public class PhysicMapVoxel extends PhysicShape {
if (this.chunk == null) {
return;
}
this.colisionPoints.clear();
aabb.update(new Vector3f(this.chunk.getPosition().x,this.chunk.getPosition().y,this.chunk.getPosition().z));
aabb.update(new Vector3f(
this.chunk.getPosition().x + VoxelChunk.VOXEL_CHUNK_SIZE,

View File

@ -1,12 +1,21 @@
package org.atriasoft.gameengine.physics;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.etk.math.Quaternion;
import org.atriasoft.etk.math.Transform3D;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.resource.ResourceColored3DObject;
public abstract class PhysicShape {
public ColisionPoints[] colisionPointTest;
protected List<Collision> colisionPoints = new ArrayList<>();
// protected Quaternion quaternion;
// protected Vector3f origin;
protected Transform3D transform;
@ -78,6 +87,11 @@ public abstract class PhysicShape {
return type;
}
public void addColision(Collision colision) {
colisionPoints.add(colision);
}
public abstract void updateAABB(Transform3D transform, PhysicCollisionAABB aabb);
public abstract void updateForNarrowCollision(Transform3D transform);

View File

@ -44,42 +44,42 @@ public class ToolCollisionOBBWithOBB {
|| getSeparatingPlane(rPos, box1.axisZ.cross(box2.axisZ), box1, box2);
return !ret;
}
// a quick test to see the code working
public static void main(String[] args) {
// create two obbs
OBB aaa = new OBB();
OBB bbb = new OBB();
// set the first obb's properties
aaa.position = new Vector3f(0.0f, 0.0f, 0.0f); // set its center position
// set the half size
aaa.halfSize = new Vector3f(10.0f, 1.0f, 1.0f);
// set the axes orientation
aaa.axisX = new Vector3f(1.0f, 0.0f, 0.0f);
aaa.axisY = new Vector3f(0.0f, 1.0f, 0.0f);
aaa.axisZ = new Vector3f(0.0f, 0.0f, 1.0f);
// set the second obb's properties
bbb.position = new Vector3f(20.0f, 0.0f, 0.0f); // set its center position
// set the half size
bbb.halfSize = new Vector3f(10.0f, 1.0f, 1.0f);
// set the axes orientation
bbb.axisX = new Vector3f(1.0f, 0.0f, 0.0f);
bbb.axisY = new Vector3f(0.0f, 1.0f, 0.0f);
bbb.axisZ = new Vector3f(0.0f, 0.0f, 1.0f);
// run the code and get the result as a message
if (getCollision(aaa, bbb)) {
Log.info("Collision!!!");
} else {
Log.info("NO Collision!!!");
}
}
//
// // a quick test to see the code working
// public static void main(String[] args) {
// // create two obbs
// OBB aaa = new OBB();
// OBB bbb = new OBB();
//
// // set the first obb's properties
// aaa.position = new Vector3f(0.0f, 0.0f, 0.0f); // set its center position
//
// // set the half size
// aaa.halfSize = new Vector3f(10.0f, 1.0f, 1.0f);
//
// // set the axes orientation
// aaa.axisX = new Vector3f(1.0f, 0.0f, 0.0f);
// aaa.axisY = new Vector3f(0.0f, 1.0f, 0.0f);
// aaa.axisZ = new Vector3f(0.0f, 0.0f, 1.0f);
//
// // set the second obb's properties
// bbb.position = new Vector3f(20.0f, 0.0f, 0.0f); // set its center position
//
// // set the half size
// bbb.halfSize = new Vector3f(10.0f, 1.0f, 1.0f);
//
// // set the axes orientation
// bbb.axisX = new Vector3f(1.0f, 0.0f, 0.0f);
// bbb.axisY = new Vector3f(0.0f, 1.0f, 0.0f);
// bbb.axisZ = new Vector3f(0.0f, 0.0f, 1.0f);
//
// // run the code and get the result as a message
// if (getCollision(aaa, bbb)) {
// Log.info("Collision!!!");
// } else {
// Log.info("NO Collision!!!");
// }
// }
// check if there's a separating plane in between the selected axes
private static boolean getSeparatingPlane222(Vector3f rPos, Vector3f plane, PhysicBox box1, PhysicBox box2) {
@ -107,7 +107,7 @@ public class ToolCollisionOBBWithOBB {
return !ret;
}
public static void getCollidePoints(PhysicBox box1, PhysicBox box2) {
public static void getCollidePoints(PhysicBox box1, boolean isStatic1, PhysicBox box2, boolean isStatic2) {
// Log.info("Try to calculare reverse force ........");
Vector3f rPos1 = box1.narrowPhaseGlobalPos.lessNew(box2.narrowPhaseGlobalPos);
Vector3f rPos2 = box2.narrowPhaseGlobalPos.lessNew(box1.narrowPhaseGlobalPos);
@ -143,11 +143,11 @@ public class ToolCollisionOBBWithOBB {
// fonctionne quand le block est trourner de 90% petit pb de positionnement en hauteur....
// getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer2, quat2.multiply(rPos2));
ColisionPoints[] collide1 = getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer2, quat2.inverseNew().getMatrix4().multiply(rPos1));
box1.colisionPointTest = collide1;
// transfer detection point collision in global environement:
if (collide1 != null) {
for (int iii = 0; iii < collide1.length; iii++) {
collide1[iii].position = quat1.multiply(collide1[iii].position).add(box1.narrowPhaseGlobalPos);
collide1[iii].force = quat2.multiply(collide1[iii].force);//.add(box1.narrowPhaseGlobalPos);
}
}
/* res = trensfert in generic plan the new res ... */
@ -157,12 +157,21 @@ public class ToolCollisionOBBWithOBB {
LoxelApplication.box1HalfSize = box1.narrowPhaseHalfSize;
LoxelApplication.box2HalfSize = box2.narrowPhaseHalfSize;
ColisionPoints[] collide2 = getCollidePointsAABBCenteredWithOBB(box1.narrowPhaseHalfSize, box2.narrowPhaseHalfSize, quatTransfer1, quat1.inverseNew().getMatrix4().multiply(rPos2));
box2.colisionPointTest = collide2;
if (collide2 != null) {
for (int iii = 0; iii < collide2.length; iii++) {
collide2[iii].position = quat2.multiply(collide2[iii].position).add(box2.narrowPhaseGlobalPos);
collide2[iii].force = quat1.multiply(collide2[iii].force);//.add(box2.narrowPhaseGlobalPos);
}
}
// add only if NOT static, when static no colision is performed
if (true) { //!isStatic1) {
Collision colision = new Collision(collide1, box2, collide2, isStatic2);
box1.addColision(colision);
}
if (true) { //!isStatic1) {
Collision colision = new Collision(collide2, box1, collide1, isStatic1);
box2.addColision(colision);
}
}
@ -273,13 +282,15 @@ public class ToolCollisionOBBWithOBB {
}
if (count != 0) {
// Find a point inside the BOX ...
/*
Log.info("Detect point inside ... " + insideTopBackRight + " " + insideTopBackLeft + " " + insideTopFrontRight + " " + insideTopFrontLeft + " " + insideBottomBackRight + " "
+ insideBottomBackLeft + " " + insideBottomFrontRight + " " + insideBottomFrontLeft);
*/
return out;
}
// line in AABB
Log.info("Need to detect line inside ...");
// TODO:
// Log.info("Need to detect line inside ..."); // pas tot a fait... si ca colisione déja avec un point de l'autre ...
return null;
}
@ -294,46 +305,61 @@ public class ToolCollisionOBBWithOBB {
Vector3f out = new Vector3f();
if (point.x < 0) {
if (point.x > -halfSize.x) {
out.x = -halfSize.x + point.x;
out.x = -(halfSize.x + point.x);
//out.x = -halfSize.x - point.x;
//out.x = -halfSize.x + point.x;
//out.x = + point.x;
} else {
return null;
}
} else {
if (point.x < halfSize.x) {
//out.x = halfSize.x + point.x;
out.x = halfSize.x - point.x;
//out.x = - point.x;
} else {
return null;
}
}
if (point.y < 0) {
if (point.y > -halfSize.y) {
out.y = -halfSize.y + point.y;
out.y = -halfSize.y - point.y;
//out.y = -halfSize.y + point.y;
//out.y = point.y;
} else {
return null;
}
} else {
if (point.y < halfSize.y) {
//out.y = halfSize.y + point.y;
out.y = halfSize.y - point.y;
//out.y = - point.y;
} else {
return null;
}
}
if (point.z < 0) {
if (point.z > -halfSize.z) {
out.z = -halfSize.z + point.z;
out.z = -halfSize.z - point.z;
//out.z = -halfSize.z + point.z;
//out.z = + point.z;
} else {
return null;
}
} else {
if (point.z < halfSize.z) {
//out.z = halfSize.z + point.z;
out.z = halfSize.z - point.z;
//out.z = - point.z;
} else {
return null;
}
}
if (out.x < out.y) {
if (Math.abs(out.x) < Math.abs(out.y)) {
out.y = 0;
if (out.x < out.z) {
if (Math.abs(out.x) < Math.abs(out.z)) {
out.z = 0;
return out;
}
@ -341,7 +367,7 @@ public class ToolCollisionOBBWithOBB {
return out;
}
out.x = 0;
if (out.y < out.z) {
if (Math.abs(out.y) < Math.abs(out.z)) {
out.z = 0;
return out;
}

View File

@ -184,6 +184,26 @@ public class LoxelApplication extends Application {
Entity localBox = new Entity(this.env);
Quaternion transform = new Quaternion(0.5f,0.2f,0.4f,1);
transform.normalize();
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(15,15,14), transform)));
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(
new Uri("DATA", "basic.vert"),
new Uri("DATA", "basic.frag")));
ComponentPhysics physics2 = new ComponentPhysics(true);
PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(8,8,8));
box2.setOrigin(new Vector3f(0,0,0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
env.addEntity(localBox);
}
{
// add a cube to test collision ...
Entity localBox = new Entity(this.env);
Quaternion transform = new Quaternion(0.3f,0.3f,0.4f,1);
transform.normalize();
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(2,-2,14.2f),transform)));
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png")));

View File

@ -5,7 +5,7 @@ import org.atriasoft.gale.Gale;
public class Main {
public static void main(String[] args) {
Uri.setGroup("DATA", "src/org/atriasoft/gameengine/sample/lowPoly/");
Uri.setGroup("DATA", "src/org/atriasoft/gameengine/samples/lowPoly/");
Uri.setGroup("DATA_EGE", "src/org/atriasoft/gameengine/data/");
Uri.setGroup("RES", "res");
Gale.run(new LowPolyApplication(), args);