[DEV] collide sphere with triangle and sphere with triangle is good ==> need to add friction to stop object

This commit is contained in:
Edouard DUPIN 2021-12-22 23:22:12 +01:00
parent 4b24223561
commit 1ecc20a08c
9 changed files with 146 additions and 85 deletions

View File

@ -262,17 +262,23 @@ public class LoxelApplicationPerso extends GaleApplication {
// env.addEntity(localBox);
// }
if (true) {
if (!this.disable) {
// add a cube to test collision ...
final Entity localBox = new Entity(this.env);
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentLight(new Light(new Color(0.0f, 1.0f, 0.0f), new Vector3f(0, 0, 0), new Vector3f(0.8f, 0.03f, 0.002f))));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 4, 0))));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 3, 0))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final PhysicTriangle box2 = new PhysicTriangle();
box2.setPoints(new Vector3f(2, 0, 0), new Vector3f(0, 2, 0), new Vector3f(3, 3, 2));
physics2.setBodyType(PhysicBodyType.BODY_STATIC);
PhysicTriangle box2 = new PhysicTriangle();
box2.setPoints(new Vector3f(4, 0, 0), new Vector3f(0, 4, 0), new Vector3f(-2, -2, 1));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(0);
physics2.addShape(box2);
box2 = new PhysicTriangle();
box2.setPoints(new Vector3f(4, 0, 0), new Vector3f(0, 4, 0), new Vector3f(6, 6, 0));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(0);
physics2.addShape(box2);
@ -286,9 +292,28 @@ public class LoxelApplicationPerso extends GaleApplication {
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentLight(new Light(new Color(0.0f, 1.0f, 0.0f), new Vector3f(0, 0, 0), new Vector3f(0.8f, 0.03f, 0.002f))));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(1, 5, 4))));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(1.1f, 5.1f, 1.0f), Quaternion.fromEulerAngles(new Vector3f(0.15f, 0.95f, 0.3f)))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final PhysicSphere box2 = new PhysicSphere();
physics2.setBodyType(PhysicBodyType.BODY_STATIC);
box2.setSize(1.0f);
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(0);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
if (true) {
// add a cube to test collision ...
final Entity localBox = new Entity(this.env);
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentLight(new Light(new Color(0.0f, 1.0f, 0.0f), new Vector3f(0, 0, 0), new Vector3f(0.8f, 0.03f, 0.002f))));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(1, 5, 4), Quaternion.fromEulerAngles(new Vector3f(0.15f, 0.95f, 0.3f)))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
physics2.setBodyType(PhysicBodyType.BODY_DYNAMIC);
final PhysicSphere box2 = new PhysicSphere();
box2.setSize(1.0f);
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);

View File

@ -333,9 +333,13 @@ public class Environement {
this.startTime = System.nanoTime();
this.lastCallTime = this.startTime;
}
final long lastUpdate = this.lastCallTime;
long lastUpdate = this.lastCallTime;
this.lastCallTime = System.nanoTime();
Clock currentClock = Clock.systemUTC();
// in the simulation, we need to limit the delta...
if (this.lastCallTime - lastUpdate > 1000000000) {
lastUpdate = this.lastCallTime - 5100000;
}
final EventTime event = new EventTime(currentClock, this.startClock, this.lastCallTime, this.startTime, Duration.ofNanos(this.lastCallTime - lastUpdate),
Duration.ofNanos(this.lastCallTime - lastUpdate));
for (final ControlInterface elem : this.controls) {

View File

@ -1,7 +1,10 @@
package org.atriasoft.ege.components;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.atriasoft.ege.Component;
import org.atriasoft.ege.Environement;
@ -29,11 +32,10 @@ public class ComponentPhysicsPerso extends Component {
public static float globalMaxSpeed = Float.MAX_VALUE;
private AABB aabb;
private List<ComponentPhysicsPerso> aabbIntersection = new ArrayList<>();
private List<ComponentPhysicsPerso> narrowIntersection = new ArrayList<>();
List<ColisionPoint> collisionPoints = new ArrayList<>();
private Map<ComponentPhysicsPerso, List<ColisionPoint>> narrowIntersection = new HashMap<>();
//List<ColisionPoint> collisionPoints = new ArrayList<>();
private List<PhysicShape> shapes = new ArrayList<>();
private ComponentPosition position;
private boolean staticObject = false;
private boolean manageGravity = true;
private float maxSpeed = globalMaxSpeed;
// current speed of the object
@ -44,6 +46,8 @@ public class ComponentPhysicsPerso extends Component {
private Vector3f staticForce = new Vector3f(0, 0, 0);
// Apply dynamic force on it
private Vector3f dynamicForce = new Vector3f(0, 0, 0);
// Apply dynamic force on it
private Vector3f dynamicForceGlobal = new Vector3f(0, 0, 0);
private EnginePhysicsPerso engine;
private PhysicBodyType bodyType;
@ -75,37 +79,51 @@ public class ComponentPhysicsPerso extends Component {
}
public void applyColisionForce() {
for (ColisionPoint impact : this.collisionPoints) {
this.position.applyForce(impact.force);
Vector3f globalForce = Vector3f.ZERO;
for (Entry<ComponentPhysicsPerso, List<ColisionPoint>> elem : this.narrowIntersection.entrySet()) {
for (ColisionPoint impact : elem.getValue()) {
globalForce = globalForce.add(impact.force);
}
}
// this force is not depending on the mass...
this.speed = this.speed.add(globalForce);
this.position.applyForce(globalForce);
}
public void applyForces(float timeStep, EngineGravity gravity) {
// get the gravity at the specific position...
Vector3f gravityForce;
Vector3f gravityAcceleration;
if (this.manageGravity) {
gravityForce = gravity.getGravityAtPosition(this.position.getTransform().getPosition()).multiply(timeStep);
gravityAcceleration = gravity.getGravityAtPosition(this.position.getTransform().getPosition());
} else {
gravityForce = new Vector3f(0, 0, 0);
gravityAcceleration = new Vector3f(0, 0, 0);
}
// apply this force on the Object
Log.info("apply gravity: " + gravityForce);
Log.info("apply gravity: " + gravityAcceleration);
// relative to the object
Vector3f staticForce = this.staticForce.multiply(timeStep);
Vector3f staticForce = this.staticForce;
float globalMass = 0;
for (PhysicShape shape : this.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(this.dynamicForce))
.multiply(globalMass);
this.dynamicForce = new Vector3f(0, 0, 0);
this.speed = this.speed.add(this.acceleration);
Vector3f staticforceOriented = this.position.getTransform().getOrientation().multiply(staticForce);
Vector3f dynamicforceOriented = this.position.getTransform().getOrientation().multiply(this.dynamicForce);
Vector3f globalForce = staticforceOriented.add(dynamicforceOriented);
if (globalMass > 0.0) {
globalForce = globalForce.divide(globalMass);
} else {
gravityAcceleration = Vector3f.ZERO;
}
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
gravityAcceleration = Vector3f.ZERO;
}
this.acceleration = gravityAcceleration.add(globalForce);
this.speed = this.speed.add(this.acceleration.multiply(timeStep));
limitWithMaxSpeed();
Log.info("apply acceleration: " + this.acceleration);
Log.info("apply speed: " + this.speed);
this.position.setTransform(this.position.getTransform().withPosition(this.position.getTransform().getPosition().add(this.speed.multiply(timeStep))));
this.position.setTransform(this.position.getTransform().withPosition(this.position.getTransform().getPosition().add(this.speed)));
}
private boolean checkCollide(PhysicShape shapeCurrent) {
@ -175,7 +193,7 @@ public class ComponentPhysicsPerso extends Component {
}
public boolean checkNarrowCollision() {
if (this.staticObject) {
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
return false;
}
for (ComponentPhysicsPerso elem : this.aabbIntersection) {
@ -187,8 +205,12 @@ public class ComponentPhysicsPerso extends Component {
}
}
if (collide) {
this.narrowIntersection.add(elem);
elem.narrowIntersection.add(this);
if (!this.narrowIntersection.containsKey(elem)) {
this.narrowIntersection.put(elem, new ArrayList<>());
}
if (!elem.narrowIntersection.containsKey(this)) {
elem.narrowIntersection.put(this, new ArrayList<>());
}
}
}
return isNarrowCollide();
@ -199,7 +221,6 @@ public class ComponentPhysicsPerso extends Component {
}
public void clearPreviousCollision() {
this.collisionPoints.clear();
this.aabbIntersection.clear();
this.narrowIntersection.clear();
}
@ -259,16 +280,12 @@ public class ComponentPhysicsPerso extends Component {
}
public boolean isNarrowCollide() {
if (this.narrowIntersection.size() == 0) {
if (this.narrowIntersection.isEmpty()) {
return false;
}
return true;
}
public boolean isStaticObject() {
return this.staticObject;
}
private void limitWithMaxSpeed() {
if (this.speed.length2() > this.maxSpeed * this.maxSpeed) {
this.speed = this.speed.safeNormalize().multiply(this.maxSpeed);
@ -276,14 +293,13 @@ public class ComponentPhysicsPerso extends Component {
}
public void narrowCollisionCreateContactAndForce() {
if (this.staticObject) {
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
return;
}
if (this.narrowIntersection.size() == 0) {
return;
}
for (ComponentPhysicsPerso elem : this.narrowIntersection) {
for (Entry<ComponentPhysicsPerso, List<ColisionPoint>> elem : this.narrowIntersection.entrySet()) {
for (PhysicShape shapeCurrent : this.shapes) {
//TODO Do a better method we do this many times ...
/*
@ -291,8 +307,8 @@ public class ComponentPhysicsPerso extends Component {
continue;
}
*/
List<ColisionPoint> points = elem.getCollidePoints(shapeCurrent);
this.collisionPoints.addAll(points);
List<ColisionPoint> points = elem.getKey().getCollidePoints(shapeCurrent);
elem.getValue().addAll(points);
}
}
}
@ -305,9 +321,11 @@ public class ComponentPhysicsPerso extends Component {
public void renderDebug(ResourceColored3DObject debugDrawProperty) {
Color displayColor;
displayColor = new Color(1.0f, 0.0f, 0.0f, 1.0f);
for (ColisionPoint impact : this.collisionPoints) {
for (Entry<ComponentPhysicsPerso, List<ColisionPoint>> elem : this.narrowIntersection.entrySet()) {
for (ColisionPoint impact : elem.getValue()) {
debugDrawProperty.drawSquare(new Vector3f(0.02f, 0.02f, 0.02f), Matrix4f.createMatrixTranslate(impact.position), displayColor);
}
}
if (this.aabbIntersection.size() == 0) {
displayColor = new Color(1.0f, 1.0f, 1.0f, 1.0f);
} else {
@ -342,10 +360,6 @@ public class ComponentPhysicsPerso extends Component {
this.maxSpeed = maxSpeed;
}
public void setStaticObject(boolean staticObject) {
this.staticObject = staticObject;
}
public void updateAABB() {
if (this.position == null) {

View File

@ -10,12 +10,14 @@ import org.atriasoft.etk.math.Vector3f;
public class ComponentPosition extends Component implements PositionningInterface {
public final Signal<Transform3D> signalPosition = new Signal<>();
protected Transform3D transform;
//protected Vector3f speed;
/**
* Create a basic position component (no orientation and position (0,0,0))
*/
public ComponentPosition() {
this.transform = Transform3D.IDENTITY;
//this.speed = Vector3f.ZERO;
}
/**
@ -37,6 +39,10 @@ public class ComponentPosition extends Component implements PositionningInterfac
this.transform = this.transform.withPosition(this.transform.getPosition().add(force));
}
//public Vector3f getSpeed() {
// return this.speed;
//}
/**
* set a new transformation
* @return Transformation of the position
@ -51,6 +57,10 @@ public class ComponentPosition extends Component implements PositionningInterfac
return "position";
}
//public void setSpeed(Vector3f speed) {
// this.speed = speed;
//}
/**
* set a new transformation
* @param transform transformation of the position

View File

@ -1,7 +1,7 @@
package org.atriasoft.ege.components;
public enum PhysicBodyType {
BODY_DYNAMIC,
BODY_STATIC,
BODY_KINEMATIC,
BODY_DYNAMIC, // mobile object that move and interact with other (42)
BODY_STATIC, // static object that does not move (map, wall)
BODY_KINEMATIC // static object that can change position by the user (like doors, lift ...)
}

View File

@ -1,9 +1,9 @@
package org.atriasoft.ege.engines;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.ege.Component;
import org.atriasoft.ege.Engine;
import org.atriasoft.ege.Environement;
@ -12,42 +12,32 @@ import org.atriasoft.ege.components.ComponentAI;
public class EngineAI extends Engine {
public static final String ENGINE_NAME = "ia";
private float accumulator = 0;
private static final float TIME_STEP = 5.0f;
private final List<ComponentAI> components = new ArrayList<ComponentAI>();
private float accumulator = 0;
private final List<ComponentAI> components = new ArrayList<>();
public EngineAI(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 ComponentAI)) {
return;
}
components.add((ComponentAI)ref);
this.components.add((ComponentAI) ref);
}
@Override
public void update(long deltaMili) {
// Add the time difference in the accumulator
accumulator += (float)deltaMili*0.0001f;
// While there is enough accumulated time to take one or several physics steps
while (accumulator >= TIME_STEP) {
//Log.warning("AI: Generate for " + accumulator + " / " + TIME_STEP + " for:" + components.size());
// call every object to usdate their constant forces applyed
for (ComponentAI it: components) {
it.update(TIME_STEP);
}
// Decrease the accumulated time
accumulator -= TIME_STEP;
public void componentRemove(Component ref) {
this.components.remove(ref);
}
@Override
public String getType() {
// TODO Auto-generated method stub
return ENGINE_NAME;
}
@Override
@ -61,9 +51,20 @@ public class EngineAI extends Engine {
}
@Override
public String getType() {
// TODO Auto-generated method stub
return ENGINE_NAME;
public void update(long deltaMili) {
// Add the time difference in the accumulator
this.accumulator += deltaMili * 0.0001f;
// While there is enough accumulated time to take one or several physics steps
while (this.accumulator >= TIME_STEP) {
//Log.warning("AI: Generate for " + accumulator + " / " + TIME_STEP + " for:" + components.size());
// call every object to usdate their constant forces applyed
for (ComponentAI it : this.components) {
it.update(TIME_STEP);
}
// Decrease the accumulated time
this.accumulator -= TIME_STEP;
}
}
}

View File

@ -7,6 +7,7 @@ import org.atriasoft.ege.Engine;
import org.atriasoft.ege.Environement;
import org.atriasoft.ege.camera.Camera;
import org.atriasoft.ege.components.ComponentPhysicsPerso;
import org.atriasoft.ege.components.PhysicBodyType;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.gale.resource.ResourceColored3DObject;
import org.atriasoft.phyligram.DebugDisplay;
@ -149,6 +150,9 @@ public class EnginePhysicsPerso extends Engine {
AABB currentAABB = current.getAABB();
for (int jjj = iii + 1; jjj < this.components.size(); jjj++) {
ComponentPhysicsPerso remote = this.components.get(jjj);
if (current.getBodyType() != PhysicBodyType.BODY_DYNAMIC && remote.getBodyType() != PhysicBodyType.BODY_DYNAMIC) {
continue;
}
// prefer checking the collision, this a time-constant operation, check if collision already exist is a unpredictable time.
if (currentAABB.intersect(this.components.get(jjj).getAABB()) == true) {
current.addIntersection(remote);

View File

@ -15,13 +15,16 @@ public class ToolCollisionSphereWithSphere {
Vector3f impact = force.multiply(shapeReference.getSize());
force = force.multiply(distance);
force = force.multiply(sphere1.getSize() + distance);
return new ColisionPoint(impact, force);
// set relative impact position:
//return new ColisionPoint(impact, force);
// set global position
return new ColisionPoint(shapeReference.narrowPhaseGlobalPos.add(impact), force);
}
// Note sphere 2 is the reference ...
public static boolean testCollide(PhysicSphere sphere1, PhysicSphere shapeReference) {
float distance1 = sphere1.narrowPhaseGlobalPos.distance2(shapeReference.narrowPhaseGlobalPos);
float distance2 = sphere1.getSize() * shapeReference.getSize();
float distance2 = sphere1.getSize() + shapeReference.getSize();
distance2 = distance2 * distance2;
return distance1 <= distance2;
}

View File

@ -55,7 +55,7 @@ public class ToolCollisionSphereWithTriangle {
if (distance < 0) {
force = force.multiply(-(sphere1.getSize() + distance));
} else {
force = force.multiply(-(sphere1.getSize() + distance));
force = force.multiply(sphere1.getSize() - distance);
}
return new ColisionPoint(impact, force);
}