Compare commits

...

2 Commits

22 changed files with 752 additions and 1970 deletions

View File

@ -6,17 +6,6 @@
</attributes>
</classpathentry>
<classpathentry kind="src" path="resources"/>
<classpathentry including="**/*.java" kind="src" output="out/eclipse/classes-test" path="test/src">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/atriasoft-ephysics">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" exported="true" kind="src" path="/atriasoft-ewol">
<attributes>
<attribute name="module" value="true"/>
@ -27,7 +16,11 @@
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5">
<attributes>
<attribute name="test" value="true"/>

View File

@ -19,12 +19,10 @@ import org.atriasoft.ege.components.ComponentPlayer;
import org.atriasoft.ege.components.ComponentPosition;
import org.atriasoft.ege.components.ComponentPositionPlayer;
import org.atriasoft.ege.components.ComponentRenderColoredStaticMesh;
import org.atriasoft.ege.components.ComponentRenderTexturedMaterialsStaticMesh;
import org.atriasoft.ege.components.ComponentRenderTexturedStaticMesh;
import org.atriasoft.ege.components.ComponentStaticMesh;
import org.atriasoft.ege.components.ComponentTexture;
import org.atriasoft.ege.components.PhysicBodyType;
import org.atriasoft.ege.engines.EngineLight;
import org.atriasoft.ege.engines.EnginePhysics;
import org.atriasoft.ege.map.MapVoxel;
import org.atriasoft.ege.tools.MeshGenerator;
@ -35,8 +33,8 @@ import org.atriasoft.etk.math.Quaternion;
import org.atriasoft.etk.math.Transform3D;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.Gale;
import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.backend3d.OpenGL;
import org.atriasoft.gale.backend3d.OpenGL.Flag;
import org.atriasoft.gale.context.GaleContext;
@ -45,7 +43,7 @@ import org.atriasoft.gale.key.KeySpecial;
import org.atriasoft.gale.key.KeyStatus;
import org.atriasoft.gale.key.KeyType;
import org.atriasoft.gale.resource.ResourceColored3DObject;
import org.atriasoft.phyligram.shape.Box;
import org.atriasoft.phyligram.PhysicBox;
public class CollisionTestApplication extends GaleApplication {
public static Vector3f box1HalfSize;
@ -112,19 +110,15 @@ public class CollisionTestApplication extends GaleApplication {
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/dirt.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
if (false) {
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setBodyType(PhysicBodyType.BODY_STATIC);
physics2.setTransform(new Transform3D(Vector3f.ZERO, orientation));
final Box box2 = new Box();
box2.setSize(new Vector3f(5.0f, 5.0f, 0.5f));
box2.setOrigin(Vector3f.ZERO);
box2.setMass(0);
physics2.addShape(box2);
localBox.addComponent(physics2);
} else {
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 0, 0))));
}
localBox.addComponent(new ComponentPosition(new Transform3D(Vector3f.ZERO, orientation)));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setBodyType(PhysicBodyType.BODY_STATIC);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(5.0f, 5.0f, 0.5f));
box2.setOrigin(Vector3f.ZERO);
box2.setMass(0);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
/*
@ -158,40 +152,17 @@ public class CollisionTestApplication extends GaleApplication {
this.env.addEntity(gird);
final Entity player = new Entity(this.env);
if (false) {
final Transform3D playerTransform = new Transform3D(new Vector3f(0, -5, 13));
//this.objectPosition = new ComponentPositionPlayer();
//player.addComponent(this.objectPosition);
this.objectPlayer = new ComponentPlayer();
player.addComponent(this.objectPlayer);
player.addComponent(new ComponentMaterial(new Material()));
//player.addComponent(new ComponentStaticMesh(new Uri("RES", "person.obj")));
player.addComponent(new ComponentStaticMesh(new Uri("RES", "person_-yfw_zup.obj")));
player.addComponent(new ComponentTexture(new Uri("RES", "playerTexture.png")));
player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"),
(EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
final ComponentPhysics physics = new ComponentPhysics(this.env, playerTransform);
physics.setBodyType(PhysicBodyType.BODY_DYNAMIC);
final Box box = new Box();
box.setSize(new Vector3f(0.3f, 0.3f, 0.9f));
box.setOrigin(new Vector3f(0, 0, 0.9f));
box.setMass(100);
physics.addShape(box);
player.addComponent(physics);
this.env.addEntity(player);
} else {
final Transform3D playerTransform = new Transform3D(new Vector3f(0, -5, 0));
this.objectPosition = new ComponentPositionPlayer();
player.addComponent(this.objectPosition);
this.objectPlayer = new ComponentPlayer();
player.addComponent(this.objectPlayer);
player.addComponent(new ComponentMaterial(new Material()));
//player.addComponent(new ComponentStaticMesh(new Uri("RES", "person.obj")));
player.addComponent(new ComponentStaticMesh(new Uri("RES", "person_-yfw_zup.obj")));
player.addComponent(new ComponentTexture(new Uri("RES", "playerTexture.png")));
//player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"), (EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
this.env.addEntity(player);
}
final Transform3D playerTransform = new Transform3D(new Vector3f(0, -5, 0));
this.objectPosition = new ComponentPositionPlayer();
player.addComponent(this.objectPosition);
this.objectPlayer = new ComponentPlayer();
player.addComponent(this.objectPlayer);
player.addComponent(new ComponentMaterial(new Material()));
//player.addComponent(new ComponentStaticMesh(new Uri("RES", "person.obj")));
player.addComponent(new ComponentStaticMesh(new Uri("RES", "person_-yfw_zup.obj")));
player.addComponent(new ComponentTexture(new Uri("RES", "playerTexture.png")));
//player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"), (EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
this.env.addEntity(player);
final Camera mainView = new Camera();
this.env.addCamera("default", mainView);
mainView.setPitch((float) Math.PI * -0.25f);
@ -209,9 +180,9 @@ public class CollisionTestApplication extends GaleApplication {
final Engine tmpEngine = this.env.getEngine("physics");
if (tmpEngine != null) {
final EnginePhysics physicsEngine = (EnginePhysics) tmpEngine;
//Disable gravity for test ...
//Disable gravity for test ...
//physicsEngine.setGravity(new Vector3f(0.0f, 0.0f, -1.0f));
physicsEngine.setGravity(new Vector3f(0.0f, 0.0f, -10.0f));
//physicsEngine.setGravity(new Vector3f(0.0f, 0.0f, -10.0f));
}
// ready to let Gale & Ege manage the display

View File

@ -1,7 +1,7 @@
package sample.atriasoft.ege.loxelEngine;
public class Log {
private static final String LIBNAME = "LoxelEngine";
private static final String LIBNAME = "LoxelEnginePerso";
public static void critical(String data) {
System.out.println("[C] " + Log.LIBNAME + " | " + data);

View File

@ -1,437 +0,0 @@
package sample.atriasoft.ege.loxelEngine;
import java.util.ArrayList;
import java.util.List;
import org.atriasoft.ege.ControlCameraPlayer;
import org.atriasoft.ege.Engine;
import org.atriasoft.ege.Entity;
import org.atriasoft.ege.Environement;
import org.atriasoft.ege.GameStatus;
import org.atriasoft.ege.Light;
import org.atriasoft.ege.Material;
import org.atriasoft.ege.camera.Camera;
import org.atriasoft.ege.components.ComponentGravityStatic;
import org.atriasoft.ege.components.ComponentLight;
import org.atriasoft.ege.components.ComponentLightSun;
import org.atriasoft.ege.components.ComponentMaterial;
import org.atriasoft.ege.components.ComponentPhysics;
import org.atriasoft.ege.components.ComponentPlayer;
import org.atriasoft.ege.components.ComponentPosition;
import org.atriasoft.ege.components.ComponentPositionPlayer;
import org.atriasoft.ege.components.ComponentRenderColoredStaticMesh;
import org.atriasoft.ege.components.ComponentRenderTexturedMaterialsStaticMesh;
import org.atriasoft.ege.components.ComponentRenderTexturedStaticMesh;
import org.atriasoft.ege.components.ComponentStaticMesh;
import org.atriasoft.ege.components.ComponentTexture;
import org.atriasoft.ege.components.PhysicBodyType;
import org.atriasoft.ege.engines.EngineLight;
import org.atriasoft.ege.engines.EnginePhysics;
import org.atriasoft.ege.map.MapVoxel;
import org.atriasoft.ege.tools.MeshGenerator;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.Uri;
import org.atriasoft.etk.math.Matrix4f;
import org.atriasoft.etk.math.Quaternion;
import org.atriasoft.etk.math.Transform3D;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.Gale;
import org.atriasoft.gale.GaleApplication;
import org.atriasoft.gale.backend3d.OpenGL;
import org.atriasoft.gale.backend3d.OpenGL.Flag;
import org.atriasoft.gale.context.GaleContext;
import org.atriasoft.gale.key.KeyKeyboard;
import org.atriasoft.gale.key.KeySpecial;
import org.atriasoft.gale.key.KeyStatus;
import org.atriasoft.gale.key.KeyType;
import org.atriasoft.gale.resource.ResourceColored3DObject;
import org.atriasoft.phyligram.shape.Box;
public class LoxelApplication extends GaleApplication {
public static Vector3f box1HalfSize;
public static Vector3f box2HalfSize;
// public static ComponentPosition relativeTestPos;
// public static Box boxTest;
public static List<Vector3f> testPoints = new ArrayList<>();
public static List<Vector3f> testPointsBox = new ArrayList<>();
public static List<Boolean> testPointsCollide = new ArrayList<>();
public static Quaternion testQTransfert;
public static Vector3f testRpos;
private float angleLight = 0;
private Quaternion basicRotation = Quaternion.IDENTITY;
private Quaternion basicRotation2 = Quaternion.IDENTITY;
private ResourceColored3DObject debugDrawProperty;
private Environement env;
private ComponentPosition lightPosition;
private MapVoxel map;
private ComponentPlayer objectPlayer;
private ComponentPosition objectPosition;
private ControlCameraPlayer simpleControl;
public LoxelApplication() {
}
@Override
public void onCreate(final GaleContext context) {
// set the system global max speed
//ComponentPhysics.globalMaxSpeed = 3;
Gale.getContext().grabPointerEvents(true, new Vector2f(0, 0));
this.env = new Environement();
setSize(new Vector2f(1500, 1500));
setTitle("Loxel sample");
this.map = new MapVoxel(this.env);
// this.env.addEngine(map);
// map.init();
// simple sun to have a global light ...
final Entity globalGravity = new Entity(this.env);
globalGravity.addComponent(new ComponentGravityStatic(new Vector3f(0, 0, -1)));
this.env.addEntity(globalGravity);
// simple sun to have a global light ...
final Entity sun = new Entity(this.env);
sun.addComponent(new ComponentPosition(new Transform3D(new Vector3f(1000, 1000, 1000))));
sun.addComponent(new ComponentLightSun(new Light(new Color(0.4f, 0.4f, 0.4f), new Vector3f(0, 0, 0), new Vector3f(0.8f, 0, 0))));
this.env.addEntity(sun);
// add a cube to show where in the light ...
final Entity localLight = new Entity(this.env);
this.lightPosition = new ComponentPosition(new Transform3D(new Vector3f(-10, -10, 17)));
// localLight.addComponent(lightPosition);
// localLight.addComponent(new ComponentStaticMesh(new Uri("RES", "cube.obj")));
// localLight.addComponent(new ComponentTexture(new Uri("RES", "grass.png")));
// localLight.addComponent(new ComponentLight(new Light(new Vector3f(0,1,0), new Vector3f(0,0,0), new Vector3f(0.8f,0.03f,0.002f))));
// localLight.addComponent(new ComponentRenderTexturedStaticMesh(
// new Uri("DATA", "basic.vert"),
// new Uri("DATA", "basic.frag")));
// env.addEntity(localLight);
{
// 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")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setTransform(new Transform3D(new Vector3f(0, 0, 5)));
final Box box2 = new Box();
box2.setSize(new Vector3f(0.5f, 0.5f, 0.5f));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
{
// 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")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setTransform(new Transform3D(new Vector3f(0, 4, 12.5f)));
final Box box2 = new Box();
box2.setSize(new Vector3f(0.5f, 0.5f, 0.5f));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
{
// 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 ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setTransform(new Transform3D(new Vector3f(-2, 2, 14.5f)));
final Box box2 = new Box();
box2.setSize(new Vector3f(0.5f, 0.5f, 0.5f));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
{
// 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 ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setTransform(new Transform3D(new Vector3f(-5, -5, 14)));
final Box box2 = new Box();
box2.setSize(new Vector3f(2, 2, 2));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
{
// add a cube to test collision ...
final Entity localBox = new Entity(this.env);
Quaternion orientation = new Quaternion(0.5f, 0.2f, 0.4f, 1);
orientation = orientation.normalize();
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setTransform(new Transform3D(new Vector3f(15, 15, 14), orientation));
final Box box2 = new Box();
box2.setSize(new Vector3f(4, 4, 4));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
{
// add a cube to test collision ...
final Entity localBox = new Entity(this.env);
final Quaternion orientation = new Quaternion(0.3f, 1.3f, 0.4f, 1);
//orientation.normalize();
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setTransform(new Transform3D(new Vector3f(2, -2, 14.2f), orientation));
physics2.setAngularReactionEnable(false);
final Box box2 = new Box();
box2.setSize(new Vector3f(0.5f, 0.5f, 0.5f));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(1);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
{
// this is the floor
final Entity localBox = new Entity(this.env);
Quaternion orientation = new Quaternion(0, 0, 0, 1);
orientation = orientation.normalize();
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/dirt.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setBodyType(PhysicBodyType.BODY_STATIC);
physics2.setTransform(new Transform3D(new Vector3f(0, 0, 0.0f), orientation));
final Box box2 = new Box();
box2.setSize(new Vector3f(20.0f, 20.0f, 0.5f));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(0);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
// {
// // add a cube to test collision ...
// Entity localBox = new Entity(this.env);
// relativeTestPos = new ComponentPosition(new Transform3D(new Vector3f(0,0,14),new Quaternion(0.5f,0.2f,0.4f,1)));
// localBox.addComponent(relativeTestPos);
//// 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 Vector3f(0,1,0), new Vector3f(0,0,0), new Vector3f(0.8f,0.03f,0.002f))));
//// localBox.addComponent(new ComponentRenderTexturedStaticMesh(
//// new Uri("DATA", "basic.vert"),
//// new Uri("DATA", "basic.frag")));
// ComponentPhysics physics2 = new ComponentPhysics(true);
// boxTest = new Box();
// boxTest.setSize(new Vector3f(1,1,1));
// boxTest.setOrigin(new Vector3f(0,0,0));
// boxTest.setMass(1);
// physics2.addShape(boxTest);
// localBox.addComponent(physics2);
// env.addEntity(localBox);
// }
// {
// Entity localBox = new Entity(this.env);
// localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0,0,14))));
// localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
// localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
// localBox.addComponent(new ComponentRenderTexturedStaticMesh(
// new Uri("DATA", "basic.vert"),
// new Uri("DATA", "basic.frag")));
// env.addEntity(localBox);
// }
final Entity gird = new Entity(this.env);
gird.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 0, 0))));
gird.addComponent(new ComponentStaticMesh(MeshGenerator.createGrid(5)));
gird.addComponent(new ComponentRenderColoredStaticMesh(new Uri("DATA", "wireColor.vert", "ege"), new Uri("DATA", "wireColor.frag", "ege")));
this.env.addEntity(gird);
final Entity player = new Entity(this.env);
if (false) {
final Transform3D playerTransform = new Transform3D(new Vector3f(0, -5, 1));
//this.objectPosition = new ComponentPositionPlayer();
//player.addComponent(this.objectPosition);
this.objectPlayer = new ComponentPlayer();
player.addComponent(this.objectPlayer);
player.addComponent(new ComponentMaterial(new Material()));
//player.addComponent(new ComponentStaticMesh(new Uri("RES", "person.obj")));
player.addComponent(new ComponentStaticMesh(new Uri("RES", "person_-yfw_zup.obj")));
player.addComponent(new ComponentTexture(new Uri("RES", "playerTexture.png")));
player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"),
(EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
final ComponentPhysics physics = new ComponentPhysics(this.env, playerTransform);
physics.setBodyType(PhysicBodyType.BODY_DYNAMIC);
physics.setAngularReactionEnable(false);
physics.setSleepingEnable(false);
final Box box = new Box();
box.setSize(new Vector3f(0.3f, 0.3f, 0.9f));
box.setOrigin(new Vector3f(0, 0, 0.9f));
box.setMass(1);
physics.addShape(box);
player.addComponent(physics);
this.env.addEntity(player);
} else {
final Transform3D playerTransform = new Transform3D(new Vector3f(0, -5, 0));
this.objectPosition = new ComponentPositionPlayer();
player.addComponent(this.objectPosition);
this.objectPlayer = new ComponentPlayer();
player.addComponent(this.objectPlayer);
player.addComponent(new ComponentMaterial(new Material()));
//player.addComponent(new ComponentStaticMesh(new Uri("RES", "person.obj")));
player.addComponent(new ComponentStaticMesh(new Uri("RES", "person_-yfw_zup.obj")));
player.addComponent(new ComponentTexture(new Uri("RES", "playerTexture.png")));
player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"),
(EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
this.env.addEntity(player);
}
final Camera mainView = new Camera();
this.env.addCamera("default", mainView);
mainView.setPitch((float) Math.PI * -0.25f);
mainView.setPosition(new Vector3f(0, -5, 5));
this.simpleControl = new ControlCameraPlayer(mainView, player);
this.env.addControlInterface(this.simpleControl);
// start the engine.
this.env.setPropertyStatus(GameStatus.gameStart);
this.basicRotation = Quaternion.fromEulerAngles(new Vector3f(0.005f, 0.005f, 0.01f));
this.basicRotation2 = Quaternion.fromEulerAngles(new Vector3f(0.003f, 0.01f, 0.001f));
final Engine tmpEngine = this.env.getEngine("physics");
if (tmpEngine != null) {
final EnginePhysics physicsEngine = (EnginePhysics) tmpEngine;
//Disable gravity for test ...
physicsEngine.setGravity(new Vector3f(0.0f, 0.0f, -9.0f));
}
// ready to let Gale & Ege manage the display
Log.info("==> Init APPL (END)");
}
@Override
public void onDraw(final GaleContext context) {
//Log.info("==> appl Draw ...");
final Vector2f size = getSize();
// Store openGl context.
OpenGL.push();
// set projection matrix:
final Matrix4f tmpProjection = Matrix4f.createMatrixPerspective(3.14f * 0.5f, getAspectRatio(), 0.1f, 50000);
OpenGL.setMatrix(tmpProjection);
// set the basic openGL view port: (Draw in all the windows...)
OpenGL.setViewPort(new Vector2f(0, 0), size);
// clear background
final Color bgColor = new Color(0.18f, 0.43f, 0.95f, 1.0f);
OpenGL.clearColor(bgColor);
// real clear request:
OpenGL.clear(OpenGL.ClearFlag.clearFlag_colorBuffer);
OpenGL.clear(OpenGL.ClearFlag.clearFlag_depthBuffer);
OpenGL.enable(Flag.flag_depthTest);
//Log.info("==> appl Draw ...");
this.env.render(20, "default");
if (this.debugDrawProperty == null) {
this.debugDrawProperty = ResourceColored3DObject.create();
}
// now render the point test collision ...
for (int iii = 0; iii < LoxelApplication.testPoints.size(); iii++) {
final Vector3f elem = LoxelApplication.testPoints.get(iii);
final boolean collide = LoxelApplication.testPointsCollide.get(iii);
if (collide) {
this.debugDrawProperty.drawSquare(new Vector3f(0.1f, 0.1f, 0.1f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(1, 0, 0, 1));
} else if (iii == 0) {
this.debugDrawProperty.drawSquare(new Vector3f(0.05f, 0.05f, 0.05f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(0, 1, 0, 1));
} else if (iii == 7) {
this.debugDrawProperty.drawSquare(new Vector3f(0.05f, 0.05f, 0.05f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(1, 1, 0, 1));
} else {
this.debugDrawProperty.drawSquare(new Vector3f(0.1f, 0.1f, 0.1f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(1, 1, 1, 1));
}
}
for (int iii = 0; iii < LoxelApplication.testPointsBox.size(); iii++) {
final Vector3f elem = LoxelApplication.testPointsBox.get(iii);
if (iii == 0) {
this.debugDrawProperty.drawSquare(new Vector3f(0.05f, 0.05f, 0.05f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(0, 1, 0, 1));
} else if (iii == 7) {
this.debugDrawProperty.drawSquare(new Vector3f(0.05f, 0.05f, 0.05f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(1, 1, 0, 1));
} else {
this.debugDrawProperty.drawSquare(new Vector3f(0.1f, 0.1f, 0.1f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(new Vector3f(elem.x(), elem.y(), elem.z() + 14))),
new Color(0, 0, 1, 1));
}
}
if (LoxelApplication.testRpos != null) {
//debugDrawProperty.drawSquare(box2HalfSize, testQTransfert.getMatrix4().multiplyNew(Matrix4f.createMatrixTranslate(new Vector3f(testRpos.x,testRpos.y,testRpos.z+14))), new Color(0,1,0,0.5f));
//Matrix4f transformation = Matrix4f.createMatrixTranslate(new Vector3f(testRpos.x,testRpos.y,testRpos.z)).multiply(testQTransfert.getMatrix4()).multiply(Matrix4f.createMatrixTranslate(new Vector3f(0,0,14)));
//Matrix4f transformation = testQTransfert.getMatrix4().multiply(Matrix4f.createMatrixTranslate(new Vector3f(testRpos.x,testRpos.y,testRpos.z))).multiply(Matrix4f.createMatrixTranslate(new Vector3f(0,0,14)));
//Matrix4f transformation = testQTransfert.getMatrix4().multiply(Matrix4f.createMatrixTranslate(new Vector3f(testRpos.x,testRpos.y,testRpos.z))).multiply(Matrix4f.createMatrixTranslate(new Vector3f(0,0,14)));
final Matrix4f transformation = Matrix4f.createMatrixTranslate(new Vector3f(LoxelApplication.testRpos.x(), LoxelApplication.testRpos.y(), LoxelApplication.testRpos.z()))
.multiply(Matrix4f.createMatrixTranslate(new Vector3f(0, 0, 14))).multiply(LoxelApplication.testQTransfert.getMatrix4());
// OK sans la box1 orientation ...
//Matrix4f transformation = Matrix4f.createMatrixTranslate(new Vector3f(testRpos.x,testRpos.y,testRpos.z)).multiply(testQTransfert.getMatrix4()).multiply(Matrix4f.createMatrixTranslate(new Vector3f(0,0,14)));
//Matrix4f transformation = Matrix4f.createMatrixTranslate(new Vector3f(testRpos.x,testRpos.y,testRpos.z)).multiply(testQTransfert.getMatrix4()).multiply(Matrix4f.createMatrixTranslate(new Vector3f(0,0,14)));
this.debugDrawProperty.drawSquare(LoxelApplication.box2HalfSize, transformation, new Color(0, 1, 0, 0.5f));
this.debugDrawProperty.drawSquare(LoxelApplication.box1HalfSize, Matrix4f.createMatrixTranslate(new Vector3f(0, 0, 14)), new Color(0, 0, 1, 0.5f));
}
// Restore context of matrix
OpenGL.pop();
}
@Override
public void onKeyboard(final KeySpecial special, final KeyKeyboard type, final Character value, final KeyStatus state) {
if (type == KeyKeyboard.F1) {
Gale.getContext().grabPointerEvents(false, new Vector2f(0, 0));
}
if (type == KeyKeyboard.F2) {
Gale.getContext().grabPointerEvents(true, new Vector2f(0, 0));
}
if (type == KeyKeyboard.F12) {
Gale.getContext().setFullScreen(!Gale.getContext().getFullScreen());
}
this.env.onKeyboard(special, type, value, state);
}
@Override
public void onPointer(final KeySpecial special, final KeyType type, final int pointerID, final Vector2f pos, final KeyStatus state) {
this.env.onPointer(special, type, pointerID, pos, state);
}
@Override
public void onRegenerateDisplay(final GaleContext context) {
//Log.verbose("Regenerate Gale Application");
this.angleLight += 0.01;
this.lightPosition.setTransform(this.lightPosition.getTransform()
.withPosition(new Vector3f(5 + (float) Math.cos(this.angleLight) * 7.0f, 5 + (float) Math.sin(this.angleLight) * 7.0f, this.lightPosition.getTransform().getPosition().z())));
this.env.periodicCall();
markDrawingIsNeeded();
}
}

View File

@ -1,4 +1,4 @@
package sample.atriasoft.ege.loxelEnginePerso;
package sample.atriasoft.ege.loxelEngine;
import java.util.ArrayList;
import java.util.List;
@ -14,7 +14,7 @@ import org.atriasoft.ege.components.ComponentGravityStatic;
import org.atriasoft.ege.components.ComponentLight;
import org.atriasoft.ege.components.ComponentLightSun;
import org.atriasoft.ege.components.ComponentMaterial;
import org.atriasoft.ege.components.ComponentPhysicsPerso;
import org.atriasoft.ege.components.ComponentPhysics;
import org.atriasoft.ege.components.ComponentPlayer;
import org.atriasoft.ege.components.ComponentPosition;
import org.atriasoft.ege.components.ComponentPositionPlayer;
@ -116,7 +116,7 @@ public class LoxelApplicationPerso extends GaleApplication {
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, 0, 5))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(1.001f, 1.001f, 1.001f));
box2.setOrigin(new Vector3f(0, 0, 0));
@ -133,7 +133,7 @@ public class LoxelApplicationPerso extends GaleApplication {
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, 2.5f))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(2.0f, 2.0f, 2.0f));
box2.setOrigin(new Vector3f(0, 0, 0));
@ -149,7 +149,7 @@ public class LoxelApplicationPerso extends GaleApplication {
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-2, 2, 1.5f))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(3.0f, 3.0f, 3.0f));
box2.setOrigin(new Vector3f(0, 0, 0));
@ -166,7 +166,7 @@ public class LoxelApplicationPerso extends GaleApplication {
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-5, -5, 0))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(2, 2, 2));
box2.setOrigin(new Vector3f(0, 0, 0));
@ -184,7 +184,7 @@ public class LoxelApplicationPerso extends GaleApplication {
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(15, 15, 0), orientation)));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(4, 4, 4));
box2.setOrigin(new Vector3f(0, 0, 0));
@ -202,7 +202,7 @@ public class LoxelApplicationPerso extends GaleApplication {
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png", "loxelEngine")));
localBox.addComponent(new ComponentRenderTexturedStaticMesh(new Uri("DATA", "basic.vert", "loxelEngine"), new Uri("DATA", "basic.frag", "loxelEngine")));
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(2, -2, 0.2f), orientation)));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
// TODO: physics2.setAngularReactionEnable(false);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(0.5f, 0.5f, 0.5f));
@ -221,7 +221,7 @@ public class LoxelApplicationPerso extends GaleApplication {
localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/dirt.png", "loxelEngine")));
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, 0, 0.0f), orientation)));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setBodyType(PhysicBodyType.BODY_STATIC);
final PhysicBox box2 = new PhysicBox();
box2.setSize(new Vector3f(20.0f, 20.0f, 0.5f));
@ -261,7 +261,7 @@ public class LoxelApplicationPerso extends GaleApplication {
// new Uri("DATA", "basic.frag")));
// env.addEntity(localBox);
// }
boolean selectCase1 = true;
if (!this.disable) {
// add a cube to test collision ...
final Entity localBox = new Entity(this.env);
@ -270,22 +270,31 @@ public class LoxelApplicationPerso extends GaleApplication {
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, 3, 0))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
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);
if (selectCase1) {
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(600, 600, -100));
box2.setOrigin(new Vector3f(0, 0, 0));
box2.setMass(0);
box2.setFrictionCoefficient(1.0f);
box2.setBouncingCoefficient(0.5f);
} else {
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);
box2.setBouncingCoefficient(0.5f);
}
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
}
if (true) {
if (selectCase1) {
// add a cube to test collision ...
final Entity localBox = new Entity(this.env);
localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj")));
@ -293,12 +302,13 @@ public class LoxelApplicationPerso extends GaleApplication {
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.1f, 5.1f, 1.0f), Quaternion.fromEulerAngles(new Vector3f(0.15f, 0.95f, 0.3f)))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics2 = new ComponentPhysics(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);
box2.setBouncingCoefficient(0.5f);
physics2.addShape(box2);
localBox.addComponent(physics2);
this.env.addEntity(localBox);
@ -310,8 +320,8 @@ 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), Quaternion.fromEulerAngles(new Vector3f(0.15f, 0.95f, 0.3f)))));
final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env);
localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(1.8f, 5.8f, 4), Quaternion.fromEulerAngles(new Vector3f(0.15f, 0.95f, 0.3f)))));
final ComponentPhysics physics2 = new ComponentPhysics(this.env);
physics2.setBodyType(PhysicBodyType.BODY_DYNAMIC);
final PhysicSphere box2 = new PhysicSphere();
box2.setSize(1.0f);
@ -342,7 +352,7 @@ public class LoxelApplicationPerso extends GaleApplication {
player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"),
(EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
player.addComponent(new ComponentPosition(playerTransform));
final ComponentPhysicsPerso physics = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics = new ComponentPhysics(this.env);
physics.setBodyType(PhysicBodyType.BODY_DYNAMIC);
//physics.setAngularReactionEnable(false);
//physics.setSleepingEnable(false);
@ -365,7 +375,7 @@ public class LoxelApplicationPerso extends GaleApplication {
player.addComponent(new ComponentTexture(new Uri("RES", "playerTexture.png")));
player.addComponent(new ComponentRenderTexturedMaterialsStaticMesh(new Uri("DATA", "basicMaterial.vert", "loxelEngine"), new Uri("DATA", "basicMaterial.frag", "loxelEngine"),
(EngineLight) this.env.getEngine(EngineLight.ENGINE_NAME)));
final ComponentPhysicsPerso physics = new ComponentPhysicsPerso(this.env);
final ComponentPhysics physics = new ComponentPhysics(this.env);
physics.setBodyType(PhysicBodyType.BODY_DYNAMIC);
final PhysicBox box = new PhysicBox();
box.setSize(new Vector3f(0.6f, 0.6f, 1.8f));

View File

@ -1,19 +0,0 @@
package sample.atriasoft.ege.loxelEngine;
import org.atriasoft.ege.Ege;
import org.atriasoft.etk.Uri;
import org.atriasoft.gale.Gale;
import sample.atriasoft.ege.collisiontest.MainCollisionTest;
public class MainLoxelEngine {
public static void main(final String[] args) {
Gale.init();
Ege.init();
Uri.setGroup("DATA", "data/");
Uri.setGroup("RES", "res");
Uri.addLibrary("loxelEngine", MainLoxelEngine.class, "testDataLoxelEngine/");
Uri.setApplication(MainLoxelEngine.class, "");
Gale.run(new LoxelApplication(), args);
}
}

View File

@ -1,4 +1,4 @@
package sample.atriasoft.ege.loxelEnginePerso;
package sample.atriasoft.ege.loxelEngine;
import org.atriasoft.ege.Ege;
import org.atriasoft.etk.Uri;

View File

@ -1,39 +0,0 @@
package sample.atriasoft.ege.loxelEnginePerso;
public class Log {
private static final String LIBNAME = "LoxelEnginePerso";
public static void critical(String data) {
System.out.println("[C] " + Log.LIBNAME + " | " + data);
}
public static void debug(String data) {
System.out.println("[D] " + Log.LIBNAME + " | " + data);
}
public static void error(String data) {
System.out.println("[E] " + Log.LIBNAME + " | " + data);
}
public static void info(String data) {
System.out.println("[I] " + Log.LIBNAME + " | " + data);
}
public static void print(String data) {
System.out.println(data);
}
public static void todo(String data) {
System.out.println("[TODO] " + Log.LIBNAME + " | " + data);
}
public static void verbose(String data) {
System.out.println("[V] " + Log.LIBNAME + " | " + data);
}
public static void warning(String data) {
System.out.println("[W] " + Log.LIBNAME + " | " + data);
}
private Log() {}
}

View File

@ -28,7 +28,7 @@ open module org.atriasoft.ege {
requires transitive org.atriasoft.gale;
requires transitive org.atriasoft.etk;
requires transitive org.atriasoft.ewol;
requires transitive org.atriasoft.ephysics;
//requires transitive org.atriasoft.ephysics;
requires transitive org.atriasoft.loader3d;
requires org.atriasoft.iogami;
}

View File

@ -1,17 +1,16 @@
package org.atriasoft.ege;
import org.atriasoft.ege.camera.Camera;
import org.atriasoft.ege.components.ComponentPhysics;
import org.atriasoft.ege.components.ComponentPlayer;
import org.atriasoft.ege.components.ComponentPositionPlayer;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.etk.math.Transform3D;
import org.atriasoft.etk.math.Vector2f;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.Gale;
import org.atriasoft.ewol.event.EventEntry;
import org.atriasoft.ewol.event.EventInput;
import org.atriasoft.ewol.event.EventTime;
import org.atriasoft.gale.Gale;
import org.atriasoft.gale.key.KeyKeyboard;
import org.atriasoft.gale.key.KeyStatus;
@ -21,7 +20,6 @@ public class ControlCameraPlayer implements ControlInterface {
private boolean fpsMode = false;
private final Entity playerEntity;
private ComponentPositionPlayer playerPosition;
private ComponentPhysics playerPhysics;
private final ComponentPlayer player;
private boolean moveUp = false;
private boolean moveDown = false;
@ -34,8 +32,6 @@ public class ControlCameraPlayer implements ControlInterface {
this.playerEntity = playerEntity;
if (this.playerEntity.exist("position")) {
this.playerPosition = (ComponentPositionPlayer) this.playerEntity.getComponent("position");
} else if (this.playerEntity.exist("physics")) {
this.playerPhysics = (ComponentPhysics) this.playerEntity.getComponent("physics");
}
this.player = (ComponentPlayer) this.playerEntity.getComponent("player");
}
@ -146,8 +142,6 @@ public class ControlCameraPlayer implements ControlInterface {
this.playerPosition.setAngles(new Vector3f(0, 0, tmpAngle));
this.camera.setRoll(-playerZAngle);
Log.info("Change camera: " + this.camera.getYaw() + " " + this.camera.getPitch());
} else if (this.playerPhysics != null) {
//this.playerPhysics.applyTorque(new Vector3f(0, 0, (float) Math.toRadians(delta.x * this.player.getTurnSpeed())));
}
}
return false;
@ -155,9 +149,6 @@ public class ControlCameraPlayer implements ControlInterface {
@Override
public void periodicCall(final EventTime event) {
if (this.playerPhysics != null) {
//this.camera.setRoll(-this.playerPhysics.getAngles().z);
}
float speed = 0;
float walkFactor = 1;
if (this.walk) {
@ -177,9 +168,6 @@ public class ControlCameraPlayer implements ControlInterface {
if (this.playerPosition != null) {
playerZAngle = this.playerPosition.getAngles().z();
playerTransform = this.playerPosition.getTransform();
} else if (this.playerPhysics != null) {
playerZAngle = 0; // TODO ...
playerTransform = this.playerPhysics.getTransform();
}
final float dx = -(float) (distance * Math.sin(playerZAngle));
final float dy = (float) (distance * Math.cos(playerZAngle));
@ -200,8 +188,6 @@ public class ControlCameraPlayer implements ControlInterface {
playerTransform = playerTransform.withPosition(tmpPos);
if (this.playerPosition != null) {
this.playerPosition.setTransform(playerTransform);
} else if (this.playerPhysics != null) {
this.playerPhysics.setTransform(playerTransform);
}
// here the camera is behind the player, we need to move the camera ...
//Log.info(" pitch: " + Math.toDegrees(this.camera.getPitch()) + " " + Math.toDegrees(playerZAngle));

View File

@ -13,7 +13,7 @@ import org.atriasoft.ege.engines.EngineDynamicMeshs;
import org.atriasoft.ege.engines.EngineGravity;
import org.atriasoft.ege.engines.EngineLight;
import org.atriasoft.ege.engines.EngineParticle;
import org.atriasoft.ege.engines.EnginePhysicsPerso;
import org.atriasoft.ege.engines.EnginePhysics;
import org.atriasoft.ege.engines.EnginePlayer;
import org.atriasoft.ege.engines.EngineRender;
import org.atriasoft.ege.internal.Log;
@ -72,7 +72,7 @@ public class Environement {
addEngine(new EngineDynamicMeshs(this));
addEngine(new EngineRender(this));
//addEngine(new EnginePhysics(this));
addEngine(new EnginePhysicsPerso(this));
addEngine(new EnginePhysics(this));
addEngine(new EngineParticle(this));
addEngine(new EngineLight(this));
this.startClock = Clock.systemUTC();

View File

@ -1,574 +1,492 @@
package org.atriasoft.ege.components;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.atriasoft.ege.Component;
import org.atriasoft.ege.Environement;
import org.atriasoft.ege.Signal;
import org.atriasoft.ege.camera.Camera;
import org.atriasoft.ege.components.part.PositionningInterface;
import org.atriasoft.ege.engines.EngineGravity;
import org.atriasoft.ege.engines.EnginePhysics;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.ephysics.body.BodyType;
import org.atriasoft.ephysics.body.RigidBody;
import org.atriasoft.ephysics.collision.ProxyShape;
import org.atriasoft.ephysics.collision.TriangleMesh;
import org.atriasoft.ephysics.collision.TriangleVertexArray;
import org.atriasoft.ephysics.collision.shapes.BoxShape;
import org.atriasoft.ephysics.collision.shapes.CapsuleShape;
import org.atriasoft.ephysics.collision.shapes.CollisionShape;
import org.atriasoft.ephysics.collision.shapes.ConcaveMeshShape;
import org.atriasoft.ephysics.collision.shapes.ConcaveShape;
import org.atriasoft.ephysics.collision.shapes.ConeShape;
import org.atriasoft.ephysics.collision.shapes.CylinderShape;
import org.atriasoft.ephysics.collision.shapes.SphereShape;
import org.atriasoft.etk.Color;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Matrix4f;
import org.atriasoft.etk.math.Quaternion;
import org.atriasoft.etk.math.Transform3D;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.resource.ResourceColored3DObject;
import org.atriasoft.phyligram.shape.Box;
import org.atriasoft.phyligram.shape.Capsule;
import org.atriasoft.phyligram.shape.Concave;
import org.atriasoft.phyligram.shape.Cone;
import org.atriasoft.phyligram.shape.ConvexHull;
import org.atriasoft.phyligram.shape.Cylinder;
import org.atriasoft.phyligram.shape.Shape;
import org.atriasoft.phyligram.shape.Sphere;
import org.atriasoft.phyligram.ColisionPoint;
import org.atriasoft.phyligram.PhysicBox;
import org.atriasoft.phyligram.PhysicHeightMapChunk;
import org.atriasoft.phyligram.PhysicMapVoxel;
import org.atriasoft.phyligram.PhysicShape;
import org.atriasoft.phyligram.PhysicSphere;
import org.atriasoft.phyligram.PhysicTriangle;
import org.atriasoft.phyligram.math.ToolCollisionOBBWithOBB;
import org.atriasoft.phyligram.math.ToolCollisionSphereWithHeightMapChunk;
import org.atriasoft.phyligram.math.ToolCollisionSphereWithSphere;
import org.atriasoft.phyligram.math.ToolCollisionSphereWithTriangle;
import org.atriasoft.phyligram.shape.AABB;
public class ComponentPhysics extends Component implements PositionningInterface {
public Signal<Transform3D> signalPosition = new Signal<>();
protected Transform3D lastTransformEmit;
protected EnginePhysics engine;
protected RigidBody rigidBody;
protected List<CollisionShape> listShape = new ArrayList<>();
protected List<ProxyShape> listProxyShape = new ArrayList<>();
public class ComponentPhysics extends Component {
public static float MINIMUM_BOUNCING_STOP = 0.0001f;
//public static float ANGLE_MAX_BOUNCING = 0.02f;
public static float globalMaxSpeed = Float.MAX_VALUE;
private AABB aabb;
private List<ComponentPhysics> aabbIntersection = new ArrayList<>();
private Set<ComponentPhysics> collisionPrevious = new HashSet<>();
private Map<ComponentPhysics, List<ColisionPoint>> collisionCurrent = new HashMap<>();
//List<ColisionPoint> collisionPoints = new ArrayList<>();
private List<PhysicShape> shapes = new ArrayList<>();
// collision already exist ==> prepare friction:
Transform3D previousPosition;
private ComponentPosition position;
private boolean manageGravity = true;
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);
// Apply dynamic force on it
private Vector3f dynamicForceGlobal = new Vector3f(0, 0, 0);
private EnginePhysics engine;
private PhysicBodyType bodyType;
protected Vector3f staticForceApplyCenterOfMass = new Vector3f(0, 0, 0);
protected Vector3f staticTorqueApply = new Vector3f(0, 0, 0);
protected List<Shape> shape = new ArrayList<>(); //!< collision shape module ... (independent of bullet lib)
/**
* Create a basic position component (no orientation and position (0,0,0))
*/
public ComponentPhysics(final Environement _env) {
this.engine = (EnginePhysics) _env.getEngine(getType());
// Initial position and orientation of the rigid body
this.lastTransformEmit = new Transform3D(new Vector3f(0, 0, 0), Quaternion.IDENTITY);
this.rigidBody = this.engine.getDynamicsWorld().createRigidBody(this.lastTransformEmit);
this.rigidBody.setUserData(this);
// set collision callback:
//this.engine.getDynamicWorld().testCollision(this.rigidBody, this);
this.rigidBody.getMaterial().setBounciness(0.0f);
this.rigidBody.setAngularDamping(0.9f);
this.rigidBody.setLinearDamping(0.9f);
//this.rigidBody.getMaterial().setFrictionCoefficient(0.01f);
//this.rigidBody.getMaterial().setRollingResistance(0.01f);
}
/**
* Create a basic position component
* @param _transform transformation of the position
*/
public ComponentPhysics(final Environement _env, final Transform3D _transform) {
this.engine = (EnginePhysics) _env.getEngine(getType());
// Create a rigid body in the world
this.rigidBody = this.engine.getDynamicsWorld().createRigidBody(_transform);
this.rigidBody.setUserData(this);
this.lastTransformEmit = _transform;
// set collision callback:
//this.engine.getDynamicWorld().testCollision(this.rigidBody, this);
Log.error("Bounciness=" + this.rigidBody.getMaterial().getBounciness());
Log.error("FrictionCoefficient=" + this.rigidBody.getMaterial().getFrictionCoefficient());
Log.error("RollingResistance=" + this.rigidBody.getMaterial().getRollingResistance());
Log.error("LinearDamping=" + this.rigidBody.getLinearDamping());
Log.error("AngularDamping=" + this.rigidBody.getAngularDamping());
this.rigidBody.getMaterial().setBounciness(0.0f);
//this.rigidBody.getMaterial().setFrictionCoefficient(0.01f);
//this.rigidBody.getMaterial().setRollingResistance(0.01f);
this.rigidBody.setAngularDamping(0.9f);
this.rigidBody.setLinearDamping(0.9f);
}
@Override
public void addFriendComponent(final Component component) {
if (component.getType().contains("position")) {
Log.critical("Can not add a 'physic' component and a 'position' component ... ==> incompatible");
}
}
public void addShape(final Shape _shape) {
this.shape.add(_shape);
}
/**
* Apply an external force to the body at a given point (in world-space coordinates).
* If the point is not at the center of mass of the body, it will also generate some torque and therefore, change the angular velocity of the body.
* If the body is sleeping, calling this method will wake it up. Note that the force will we added to the sum of the applied forces and that this sum will be reset to zero at the end of each call of the DynamicsWorld::update() method. You can only apply a force to a dynamic body otherwise, this method will do nothing.
* @param _force The force to apply on the body
* @param _point The point where the force is applied (in world-space coordinates)
*/
public void applyForce(final Vector3f _force, final Vector3f _point) {
if (this.rigidBody == null) {
return;
}
this.rigidBody.applyForce(_force, _point);
}
/**
* Apply an external force to the body at its center of mass.
* If the body is sleeping, calling this method will wake it up.
* @note The force will we added to the sum of the applied forces and that this sum will be reset to zero at the end of each call of the DynamicsWorld::update() method. You can only apply a force to a dynamic body otherwise, this method will do nothing.
* @param _force The external force to apply on the center of mass of the body
*/
public void applyForceToCenterOfMass(final Vector3f _force) {
if (this.rigidBody == null) {
return;
}
this.rigidBody.applyForceToCenterOfMass(_force);
}
public void applyForceToCenterOfMassStatic(final Vector3f _force) {
if (this.rigidBody == null) {
return;
}
this.staticForceApplyCenterOfMass = _force;
}
/**
* Apply an external force to the body at its center of mass.
* If the body is sleeping, calling this method will wake it up.
* @note The force is apply with a relative axis of the object
* @note The force will we added to the sum of the applied forces and that this sum will be reset to zero at the end of each call of the DynamicsWorld::update() method. You can only apply a force to a dynamic body otherwise, this method will do nothing.
* @param _force The external force to apply on the center of mass of the body
*/
public void applyRelativeForceToCenterOfMass(final Vector3f _force) {
if (this.rigidBody == null) {
return;
}
final Vector3f force = this.rigidBody.getTransform().getOrientation().multiply(_force);
this.rigidBody.applyForceToCenterOfMass(force);
}
public void applyRelativeForceToCenterOfMassStatic(final Vector3f _force) {
if (this.rigidBody == null) {
return;
}
this.staticForceApplyCenterOfMass = this.rigidBody.getTransform().getOrientation().multiply(_force);
}
/**
* Apply an external torque to the body.
* If the body is sleeping, calling this method will wake it up.
* @note The torque is apply with a relative axis of the object
* @note The force will we added to the sum of the applied torques and that this sum will be reset to zero at the end of each call of the DynamicsWorld::update() method. You can only apply a force to a dynamic body otherwise, this method will do nothing.
* @param _torque The external torque to apply on the body
*/
public void applyRelativeTorque(final Vector3f _torque) {
if (this.rigidBody == null) {
return;
}
final Vector3f torque = this.rigidBody.getTransform().getOrientation().multiply(_torque);
this.rigidBody.applyTorque(torque);
}
public void applyRelativeTorqueStatic(final Vector3f _torque) {
if (this.rigidBody == null) {
return;
}
this.staticTorqueApply = this.rigidBody.getTransform().getOrientation().multiply(_torque);
}
/**
* Apply an external torque to the body.
* If the body is sleeping, calling this method will wake it up.
* @note The force will we added to the sum of the applied torques and that this sum will be reset to zero at the end of each call of the DynamicsWorld::update() method. You can only apply a force to a dynamic body otherwise, this method will do nothing.
* @param _torque The external torque to apply on the body
*/
public void applyTorque(final Vector3f _torque) {
if (this.rigidBody == null) {
return;
}
this.rigidBody.applyTorque(_torque);
}
public void applyTorqueStatic(final Vector3f _torque) {
if (this.rigidBody == null) {
return;
}
this.staticTorqueApply = _torque;
}
/**
* Called when a new contact point is found between two bodies that were separated before.
* @param _other The other component that have the impact
* @param _normal Normal of the impact
* @param _pos Position of the impact at the current object
* @param _posOther Position of the impact at the other object
* @param _penetrationDepth Depth penetration in the object
*/
public void beginContact(final Component _other, final Vector3f _normal, final Vector3f _pos, final Vector3f _posOther, final float _penetrationDepth) {
Log.warning(" collision [BEGIN] " + _pos + " depth=" + _penetrationDepth);
}
public void drawShape(final ResourceColored3DObject _draw, final Camera _camera) {
final Transform3D transform = getTransform();
//final float[] mmm = new float[16];
// Get the OpenGL matrix array of the transform
final Matrix4f mmm = transform.getOpenGLMatrix();
final Matrix4f transformationMatrix = mmm.transpose();
final Color tmpColor = new Color(1.0f, 0.0f, 0.0f, 0.3f);
for (final Shape it : this.shape) {
if (it instanceof Box tmpElement) {
Log.debug(" Box");
final Transform3D transformLocal = new Transform3D(it.getOrigin(), it.getOrientation());
Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix();
transformationMatrixLocal = transformationMatrixLocal.transpose();
transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal);
_draw.drawSquare(tmpElement.getSize(), transformationMatrixLocal, tmpColor);
} else if (it instanceof Cylinder tmpElement) {
Log.debug(" Cylinder");
final Transform3D transformLocal = new Transform3D(it.getOrigin(), it.getOrientation());
Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix();
transformationMatrixLocal = transformationMatrixLocal.transpose();
transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal);
_draw.drawCylinder(tmpElement.getRadius(), tmpElement.getSize(), 10, 10, transformationMatrixLocal, tmpColor);
} else if (it instanceof Capsule tmpElement) {
Log.debug(" Capsule");
final Transform3D transformLocal = new Transform3D(it.getOrigin(), it.getOrientation());
Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix();
transformationMatrixLocal = transformationMatrixLocal.transpose();
transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal);
_draw.drawCapsule(tmpElement.getRadius(), tmpElement.getSize(), 10, 10, transformationMatrixLocal, tmpColor);
} else if (it instanceof Cone tmpElement) {
Log.debug(" Cone");
final Transform3D transformLocal = new Transform3D(it.getOrigin(), it.getOrientation());
Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix();
transformationMatrixLocal = transformationMatrixLocal.transpose();
transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal);
_draw.drawCone(tmpElement.getRadius(), tmpElement.getSize(), 10, 10, transformationMatrixLocal, tmpColor);
} else if (it instanceof Sphere tmpElement) {
Log.debug(" Sphere");
final Transform3D transformLocal = new Transform3D(it.getOrigin(), it.getOrientation());
Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix();
transformationMatrixLocal = transformationMatrixLocal.transpose();
transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal);
_draw.drawSphere(tmpElement.getRadius(), 10, 10, transformationMatrixLocal, tmpColor);
} else if (it instanceof Concave tmpElement) {
Log.debug(" concave");
final Transform3D transformLocal = new Transform3D(it.getOrigin(), it.getOrientation());
Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix();
transformationMatrixLocal = transformationMatrixLocal.transpose();
transformationMatrixLocal = transformationMatrixLocal.multiply(transformationMatrixLocal);
_draw.drawTriangles(tmpElement.getVertex(), tmpElement.getIndices(), transformationMatrixLocal, tmpColor);
} else if (it instanceof ConvexHull tmpElement) {
Log.debug(" convexHull");
break;
public void addFriendComponent(Component component) {
if (component.getType().contentEquals("position")) {
if (component instanceof ComponentPosition tmp) {
this.position = tmp;
} else {
Log.error("Not manage position model...");
}
}
}
// call done after all cycle update of the physical engine
public void emitAll() {
// emit only of new ...
final Transform3D transform = getTransform();
if (this.lastTransformEmit != transform) {
this.lastTransformEmit = transform;
this.signalPosition.emit(transform);
}
}
public void generate() {
if (this.shape.size() == 0) {
Log.warning("No Shape Availlable ...");
public void addIntersection(ComponentPhysics component) {
// do not add multiple times
if (this.aabbIntersection.contains(component)) {
return;
}
// TODO: support more than one shape for each elements... (ProxyShape)
for (final Shape it : this.shape) {
if (it == null) {
this.aabbIntersection.add(component);
}
public void addShape(PhysicShape shape) {
this.shapes.add(shape);
}
public void applyColisionForce(float timeStep) {
for (Entry<ComponentPhysics, List<ColisionPoint>> elem : this.collisionCurrent.entrySet()) {
Float globalBouncing = null;
if (!this.collisionPrevious.contains(elem.getKey())) {
globalBouncing = elem.getKey().getBouncingCoefficient();
}
float globalFriction = elem.getKey().getFrictionCoefficient();
Vector3f globalForce = Vector3f.ZERO;
for (ColisionPoint impact : elem.getValue()) {
globalForce = globalForce.add(impact.force);
}
// nothing to apply ?
if (globalForce == Vector3f.ZERO) {
continue;
}
if (it instanceof Box tmpElement) {
Log.debug(" Box");
// Half extents of the box in the x, y and z directions
final Vector3f halfExtents = new Vector3f(tmpElement.getSize().x(), tmpElement.getSize().y(), tmpElement.getSize().z());
// Create the box shape
final BoxShape shape = new BoxShape(halfExtents, 0.0001f);
this.listShape.add(shape);
// The ephysic use Y as UP ==> ege use Z as UP
//orientation = orientation * ephysics::Quaternion(-0.707107, 0, 0, 0.707107);
final Transform3D transform = new Transform3D(it.getOrigin(), it.getOrientation());
final ProxyShape proxyShape = this.rigidBody.addCollisionShape(shape, transform, it.getMass());
proxyShape.setUserData(this);
this.listProxyShape.add(proxyShape);
} else if (it instanceof Cylinder tmpElement) {
Log.debug(" Cylinder");
// Create the Cylinder shape
// Create the Cylinder shape
final CylinderShape shape = new CylinderShape(tmpElement.getRadius(), tmpElement.getSize());
// The ephysic use Y as UP ==> ege use Z as UP
final Quaternion orientation = it.getOrientation().multiply(new Quaternion(-0.707107f, 0.0f, 0.0f, 0.707107f));
final Transform3D transform = new Transform3D(it.getOrigin(), orientation);
final ProxyShape proxyShape = this.rigidBody.addCollisionShape(shape, transform, it.getMass());
proxyShape.setUserData(this);
this.listProxyShape.add(proxyShape);
} else if (it instanceof Capsule tmpElement) {
Log.debug(" Capsule");
// Create the Capsule shape
final CapsuleShape shape = new CapsuleShape(tmpElement.getRadius(), tmpElement.getSize());
// The ephysic use Y as UP ==> ege use Z as UP
final Quaternion orientation = it.getOrientation().multiply(new Quaternion(-0.707107f, 0.0f, 0.0f, 0.707107f));
final Transform3D transform = new Transform3D(it.getOrigin(), orientation);
final ProxyShape proxyShape = this.rigidBody.addCollisionShape(shape, transform, it.getMass());
proxyShape.setUserData(this);
this.listProxyShape.add(proxyShape);
} else if (it instanceof Cone tmpElement) {
Log.debug(" Cone");
// Create the Cone shape
final ConeShape shape = new ConeShape(tmpElement.getRadius(), tmpElement.getSize());
// The ephysic use Y as UP ==> ege use Z as UP
final Quaternion orientation = it.getOrientation().multiply(new Quaternion(-0.707107f, 0.0f, 0.0f, 0.707107f));
final Transform3D transform = new Transform3D(it.getOrigin(), orientation);
final ProxyShape proxyShape = this.rigidBody.addCollisionShape(shape, transform, it.getMass());
proxyShape.setUserData(this);
this.listProxyShape.add(proxyShape);
} else if (it instanceof Sphere tmpElement) {
Log.debug(" Sphere");
// Create the box shape
final SphereShape shape = new SphereShape(tmpElement.getRadius());
// The ephysic use Y as UP ==> ege use Z as UP
final Quaternion orientation = it.getOrientation().multiply(new Quaternion(-0.707107f, 0.0f, 0.0f, 0.707107f));
final Transform3D transform = new Transform3D(it.getOrigin(), orientation);
final ProxyShape proxyShape = this.rigidBody.addCollisionShape(shape, transform, it.getMass());
proxyShape.setUserData(this);
this.listProxyShape.add(proxyShape);
} else if (it instanceof Concave tmpElement) {
Log.debug(" Concave");
//static etk::Vector<Vector3f> vertices = {Vector3f(-100.0f,-100.0f,-50.0f),Vector3f(100.0f,-100.0f,-50.0f),Vector3f(100.0f,100.0f,-50.0f)};
//static etk::Vector<uint32_t> indices = {0,1,2};
//ephysics::TriangleVertexArray* triangleArray = ETK_NEW(ephysics::TriangleVertexArray, vertices, indices);
final TriangleVertexArray triangleArray = new TriangleVertexArray(tmpElement.getVertex(), tmpElement.getIndices());
// Now that we have a TriangleVertexArray, we need to create a TriangleMesh and add the TriangleVertexArray into it as a subpart.
// Once this is done, we can create the actual ConcaveMeshShape and add it to the body we want to simulate as in the following example:
final TriangleMesh triangleMesh = new TriangleMesh();
// Add the triangle vertex array to the triangle mesh
triangleMesh.addSubpart(triangleArray);
// Create the concave mesh shape
// TODO : Manage memory leak ...
final ConcaveShape shape = new ConcaveMeshShape(triangleMesh);
// The ephysic use Y as UP ==> ege use Z as UP
final Quaternion orientation = it.getOrientation().multiply(new Quaternion(-0.707107f, 0.0f, 0.0f, 0.707107f));
final Transform3D transform = new Transform3D(it.getOrigin(), it.getOrientation());
final ProxyShape proxyShape = this.rigidBody.addCollisionShape(shape, transform, it.getMass());
proxyShape.setUserData(this);
this.listProxyShape.add(proxyShape);
// when tuch a kinematy force is divide between the two
if (elem.getKey().getBodyType() == PhysicBodyType.BODY_DYNAMIC) {
globalForce = globalForce.multiply(0.5f);
}
if (globalBouncing != null) {
// detect new collision ==> apply bouncing
if (this.speed.length2() < MINIMUM_BOUNCING_STOP) {
this.speed = Vector3f.ZERO;
} else {
// this force is not depending on the mass...
this.speed = this.speed.reflect(globalForce.normalize()).multiply(globalBouncing); // apply the bouncing...
}
this.position.applyForce(globalForce);
} else {
Log.debug(" ???");
// TODO UNKNOWN type ...
// second consecutive time off collision ==> friction ...
this.position.applyForce(globalForce);
this.speed = this.position.getTransform().getPosition().less(this.previousPosition.getPosition());//.divide(timeStep);
globalFriction = 1.0f - FMath.avg(0.0f, globalFriction, 1.0f) * timeStep;
this.speed = this.speed.multiply(globalFriction);
}
}
}
/**
* Get the angular velocity (whole world).
* @return The angular velocity vector of the body
*/
public Vector3f getAngularVelocity() {
if (this.rigidBody == null) {
return new Vector3f(0, 0, 0);
public void applyForces(float timeStep, EngineGravity gravity) {
// get the gravity at the specific position...
Vector3f gravityAcceleration;
if (this.manageGravity) {
gravityAcceleration = gravity.getGravityAtPosition(this.position.getTransform().getPosition());
} else {
gravityAcceleration = new Vector3f(0, 0, 0);
}
return this.rigidBody.getAngularVelocity();
// apply this force on the Object
Log.info("apply gravity: " + gravityAcceleration);
// relative to the object
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...
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)));
}
/**
* Get the linear velocity (whole world).
* @return The linear velocity vector of the body
*/
public Vector3f getLinearVelocity() {
if (this.rigidBody == null) {
return new Vector3f(0, 0, 0);
/*
public void applyColisionForce(float timeStep) {
Vector3f globalForce = Vector3f.ZERO;
float globalBouncing = 1.0f;
this.haveBouncing = false;
for (Entry<ComponentPhysics, List<ColisionPoint>> elem : this.collisionCurrent.entrySet()) {
if (!this.collisionPrevious.contains(elem.getKey())) {
this.haveBouncing = true;
globalBouncing = FMath.min(globalBouncing, elem.getKey().getBouncingCoefficient());
}
for (ColisionPoint impact : elem.getValue()) {
globalForce = globalForce.add(impact.force);
}
}
if (globalForce == Vector3f.ZERO) {
return;
}
if (this.haveBouncing) {
// detect new collision ==> apply bouncing
if (this.speed.length2() < MINIMUM_BOUNCING_STOP) {
this.speed = Vector3f.ZERO;
} else {
// this force is not depending on the mass...
this.speed = this.speed.reflect(globalForce.normalize()).multiply(globalBouncing); // apply the bouncing...
}
this.position.applyForce(globalForce);
} else {
this.position.applyForce(globalForce);
this.speed = this.position.getTransform().getPosition().less(this.previousPosition.getPosition());//.divide(timeStep);
}
return this.rigidBody.getLinearVelocity();
}
/**
* Get the angular velocity (local Body).
* @return The angular velocity vector of the body
*/
public Vector3f getRelativeAngularVelocity() {
if (this.rigidBody == null) {
return new Vector3f(0, 0, 0);
public void applyFriction(float timeStep) {
if (this.collisionCurrent.isEmpty()) {
return;
}
final Vector3f value = this.rigidBody.getAngularVelocity();
return this.rigidBody.getTransform().getOrientation().inverse().multiply(value);
float globalFriction = 0.0f;
for (Entry<ComponentPhysics, List<ColisionPoint>> elem : this.collisionCurrent.entrySet()) {
globalFriction += elem.getKey().getFrictionCoefficient();
}
globalFriction = 1.0f - FMath.avg(0.0f, globalFriction, 1.0f) * timeStep;
if (!this.haveBouncing) {
this.speed = this.speed.multiply(globalFriction); // c'est ini qu'il faut mettre en place l'absortion complète
}
}
*/
private boolean checkCollide(PhysicShape shapeCurrent) {
if (shapeCurrent instanceof PhysicBox shape111) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicHeightMapChunk shape222) {
// detect collision from cube on height-map !!!
} else if (shape instanceof PhysicBox shape222) {
// detect collision between 2 cubes
if (ToolCollisionOBBWithOBB.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicSphere shape222) {
} else if (shape instanceof PhysicMapVoxel shape222) {
} else {
Log.error("Not manage collision model... " + shape);
}
}
} else if (shapeCurrent instanceof PhysicSphere shape111) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicHeightMapChunk shape222) {
// detect collision from sphere on height-map !!!
if (ToolCollisionSphereWithHeightMapChunk.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicTriangle shape222) {
// detect collision from sphere on height-map !!!
if (ToolCollisionSphereWithTriangle.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicBox shape222) {
// detect collision from sphere on cube !!!
} else if (shape instanceof PhysicSphere shape222) {
// detect collision from sphere on sphere !!!
if (ToolCollisionSphereWithSphere.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicMapVoxel shape222) {
} else {
Log.error("Not manage collision model... " + shape);
}
}
} else if (shapeCurrent instanceof PhysicMapVoxel shape111) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicBox shape222) {
} else if (shape instanceof PhysicSphere shape222) {
} else if (shape instanceof PhysicMapVoxel shape222) {
} else {
Log.error("Not manage collision model... " + shape);
}
}
} else {
Log.error("Not manage collision model... " + shapeCurrent);
}
return false;
}
/**
* Get the linear velocity (local Body).
* @return The linear velocity vector of the body
*/
public Vector3f getRelativeLinearVelocity() {
if (this.rigidBody == null) {
return new Vector3f(0, 0, 0);
public boolean checkNarrowCollision() {
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
return false;
}
final Vector3f value = this.rigidBody.getLinearVelocity();
return this.rigidBody.getTransform().getOrientation().inverse().multiply(value);
for (ComponentPhysics elem : this.aabbIntersection) {
boolean collide = false;
for (PhysicShape shapeCurrent : this.shapes) {
if (elem.checkCollide(shapeCurrent)) {
collide = true;
break;
}
}
if (collide) {
if (!this.collisionCurrent.containsKey(elem)) {
this.collisionCurrent.put(elem, new ArrayList<>());
}
if (!elem.collisionCurrent.containsKey(this)) {
elem.collisionCurrent.put(this, new ArrayList<>());
}
}
}
return isNarrowCollide();
}
public List<Shape> getShape() {
return this.shape;
public void clearAABBIntersection() {
this.aabbIntersection.clear();
}
/**
* set a new transformation
* @return Transformation of the position
*/
@Override
public Transform3D getTransform() {
if (this.rigidBody == null) {
return Transform3D.IDENTITY;
public void clearPreviousCollision() {
// store the previous list of collide elements
this.collisionPrevious = new HashSet<>(this.collisionCurrent.keySet());
this.previousPosition = this.position.getTransform();
this.aabbIntersection.clear();
this.collisionCurrent.clear();
}
public void clearShape() {
this.shapes.clear();
}
public AABB getAABB() {
return this.aabb;
}
public List<ComponentPhysics> getAabbIntersection() {
return this.aabbIntersection;
}
public PhysicBodyType getBodyType() {
return this.bodyType;
}
private float getBouncingCoefficient() {
float total = 0.0f;
for (PhysicShape shape : this.shapes) {
total = FMath.max(total, shape.getBouncingCoefficient());
}
return this.rigidBody.getTransform();
return total;
}
private List<ColisionPoint> getCollidePoints(PhysicShape shapeRemote) {
List<ColisionPoint> out = new ArrayList<>();
if (shapeRemote instanceof PhysicSphere remoteShere) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicSphere localShape) {
ColisionPoint point = ToolCollisionSphereWithSphere.getCollisionPoint(remoteShere, localShape);
if (point != null) {
out.add(point);
}
} else if (shape instanceof PhysicTriangle localShape) {
ColisionPoint point = ToolCollisionSphereWithTriangle.getCollisionPoint(remoteShere, localShape);
if (point != null) {
out.add(point);
}
}
}
} else if (shapeRemote instanceof PhysicTriangle) {
// nothing can happens ...
} else {
Log.error("Not manage collision model... " + shapeRemote);
}
return out;
}
public float getFrictionCoefficient() {
float total = 0.0f;
for (PhysicShape shape : this.shapes) {
total = FMath.max(total, shape.getFrictionCoefficient());
}
return total;
}
public float getMaxSpeed() {
return this.maxSpeed;
}
@Override
public String getType() {
return "physics";
return EnginePhysics.ENGINE_NAME;
}
/**
* Called when a new contact point is found between two bodies.
* @param _other The other component that have the impact
* @param _normal Normal of the impact
* @param _pos Position of the impact at the current object
* @param _posOther Position of the impact at the other object
* @param _penetrationDepth Depth penetration in the object
*/
public void newContact(final Component _other, final Vector3f _normal, final Vector3f _pos, final Vector3f _posOther, final float _penetrationDepth) {
Log.warning(" collision [ NEW ] " + _pos + " depth=" + _penetrationDepth);
public boolean isManageGravity() {
return this.manageGravity;
}
public void renderDebug(final ResourceColored3DObject _draw, final Camera _camera) {
if (this.rigidBody == null) {}
/*
final Matrix4f transformationMatrix = Matrix4f.IDENTITY;
final Color tmpColor = new Color(0.0f, 1.0f, 0.0f, 0.8f);
final AABB value = this.rigidBody.getAABB();
_draw.drawCubeLine(value.getMin(), value.getMax(), tmpColor, transformationMatrix, true, true);
*/
public boolean isNarrowCollide() {
if (this.collisionCurrent.isEmpty()) {
return false;
}
return true;
}
public void setAngularReactionEnable(final boolean value) {
this.rigidBody.setAngularReactionEnable(value);
private void limitWithMaxSpeed() {
if (this.speed.length2() > this.maxSpeed * this.maxSpeed) {
this.speed = this.speed.safeNormalize().multiply(this.maxSpeed);
}
}
/**
* Set the angular velocity (whole world).
* @param _angularVelocity The angular velocity vector of the body
*/
public void setAngularVelocity(final Vector3f _angularVelocity) {
if (this.rigidBody == null) {
public void narrowCollisionCreateContactAndForce() {
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
return;
}
this.rigidBody.setAngularVelocity(_angularVelocity);
}
public void setBodyType(final PhysicBodyType _type) {
if (this.rigidBody == null) {
if (this.collisionCurrent.size() == 0) {
return;
}
switch (_type) {
case BODY_STATIC -> this.rigidBody.setType(BodyType.STATIC);
case BODY_KINEMATIC -> this.rigidBody.setType(BodyType.KINEMATIC);
case BODY_DYNAMIC -> this.rigidBody.setType(BodyType.DYNAMIC);
for (Entry<ComponentPhysics, List<ColisionPoint>> elem : this.collisionCurrent.entrySet()) {
for (PhysicShape shapeCurrent : this.shapes) {
//TODO Do a better method we do this many times ...
/*
if (!elem.checkCollide(shapeCurrent)) {
continue;
}
*/
List<ColisionPoint> points = elem.getKey().getCollidePoints(shapeCurrent);
elem.getValue().addAll(points);
}
}
}
/**
* Set the linear velocity (whole world).
* @param _linearVelocity The linear velocity vector of the body
*/
public void setLinearVelocity(final Vector3f _linearVelocity) {
if (this.rigidBody == null) {
@Override
public void removeFriendComponent(Component component) {
// nothing to do.
}
public void renderDebug(ResourceColored3DObject debugDrawProperty) {
Color displayColor;
displayColor = new Color(1.0f, 0.0f, 0.0f, 1.0f);
for (Entry<ComponentPhysics, List<ColisionPoint>> elem : this.collisionCurrent.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 {
if (this.collisionCurrent.size() == 0) {
displayColor = new Color(0.0f, 1.0f, 0.0f, 1.0f);
} else {
displayColor = new Color(1.0f, 0.0f, 0.0f, 1.0f);
}
}
if (this.aabb != null) {
debugDrawProperty.drawCubeLine(this.aabb.getMin(), this.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");
}
for (PhysicShape shape : this.shapes) {
shape.renderDebug(this.position.getTransform(), debugDrawProperty);
}
}
public void setBodyType(PhysicBodyType bodyType) {
this.bodyType = bodyType;
}
public void setManageGravity(boolean manageGravity) {
this.manageGravity = manageGravity;
}
public void setMaxSpeed(float maxSpeed) {
this.maxSpeed = maxSpeed;
}
public void updateAABB() {
if (this.position == null) {
Log.info("No position in Entity ");
return;
}
this.rigidBody.setLinearVelocity(_linearVelocity);
// TODO Add a flag to check if it is needed to update the AABB...
AABB aabbNew = AABB.createInvertedEmpty();
for (PhysicShape shape : this.shapes) {
shape.updateAABB(this.position.getTransform(), aabbNew);
}
this.aabb = aabbNew;
}
/**
* Set the angular velocity (local Body).
* @param _angularVelocity The angular velocity vector of the body
*/
public void setRelativeAngularVelocity(final Vector3f _angularVelocity) {
if (this.rigidBody == null) {
public void updateForNarrowCollision() {
this.collisionCurrent.clear();
if (this.aabbIntersection.size() == 0) {
return;
}
final Vector3f value = this.rigidBody.getTransform().getOrientation().multiply(_angularVelocity);
this.rigidBody.setAngularVelocity(value);
}
/**
* Set the linear velocity (local Body).
* @param _linearVelocity The linear velocity vector of the body
*/
public void setRelativeLinearVelocity(final Vector3f _linearVelocity) {
if (this.rigidBody == null) {
if (this.position == null) {
Log.info("No position in Entity ");
return;
}
final Vector3f value = this.rigidBody.getTransform().getOrientation().multiply(_linearVelocity);
this.rigidBody.setLinearVelocity(value);
}
public void setShape(final List<Shape> _prop) {
this.shape = _prop;
}
public void setSleepingEnable(final boolean value) {
this.rigidBody.setIsAllowedToSleep(value);
}
/**
* set a new transformation
* @param _transform transformation of the position
*/
public void setTransform(final Transform3D _transform) {
if (this.rigidBody == null) {
return;
}
this.rigidBody.setTransform(_transform);
}
// call of this function every time the call will be done
public void update(final float _delta) {
if (this.rigidBody == null) {
return;
}
if (!this.staticForceApplyCenterOfMass.isZero()) {
final Vector3f tmp = this.staticForceApplyCenterOfMass.multiply(_delta);
Log.error("FORCE : " + tmp);
this.rigidBody.applyForceToCenterOfMass(tmp);
}
if (!this.staticTorqueApply.isZero()) {
final Vector3f tmp = this.staticTorqueApply.multiply(_delta);
Log.error("TORQUE : " + tmp);
this.rigidBody.applyTorque(tmp);
for (PhysicShape shape : this.shapes) {
shape.updateForNarrowCollision(this.position.getTransform());
}
}
}

View File

@ -1,390 +0,0 @@
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;
import org.atriasoft.ege.engines.EngineGravity;
import org.atriasoft.ege.engines.EnginePhysicsPerso;
import org.atriasoft.ege.internal.Log;
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.phyligram.ColisionPoint;
import org.atriasoft.phyligram.PhysicBox;
import org.atriasoft.phyligram.PhysicHeightMapChunk;
import org.atriasoft.phyligram.PhysicMapVoxel;
import org.atriasoft.phyligram.PhysicShape;
import org.atriasoft.phyligram.PhysicSphere;
import org.atriasoft.phyligram.PhysicTriangle;
import org.atriasoft.phyligram.ToolCollisionOBBWithOBB;
import org.atriasoft.phyligram.ToolCollisionSphereWithHeightMapChunk;
import org.atriasoft.phyligram.ToolCollisionSphereWithSphere;
import org.atriasoft.phyligram.ToolCollisionSphereWithTriangle;
import org.atriasoft.phyligram.shape.AABB;
public class ComponentPhysicsPerso extends Component {
public static float globalMaxSpeed = Float.MAX_VALUE;
private AABB aabb;
private List<ComponentPhysicsPerso> aabbIntersection = 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 manageGravity = true;
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);
// Apply dynamic force on it
private Vector3f dynamicForceGlobal = new Vector3f(0, 0, 0);
private EnginePhysicsPerso engine;
private PhysicBodyType bodyType;
public ComponentPhysicsPerso(final Environement _env) {
this.engine = (EnginePhysicsPerso) _env.getEngine(getType());
}
@Override
public void addFriendComponent(Component component) {
if (component.getType().contentEquals("position")) {
if (component instanceof ComponentPosition tmp) {
this.position = tmp;
} else {
Log.error("Not manage position model...");
}
}
}
public void addIntersection(ComponentPhysicsPerso component) {
// do not add multiple times
if (this.aabbIntersection.contains(component)) {
return;
}
this.aabbIntersection.add(component);
}
public void addShape(PhysicShape shape) {
this.shapes.add(shape);
}
public void applyColisionForce() {
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 gravityAcceleration;
if (this.manageGravity) {
gravityAcceleration = gravity.getGravityAtPosition(this.position.getTransform().getPosition());
} else {
gravityAcceleration = new Vector3f(0, 0, 0);
}
// apply this force on the Object
Log.info("apply gravity: " + gravityAcceleration);
// relative to the object
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...
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)));
}
private boolean checkCollide(PhysicShape shapeCurrent) {
if (shapeCurrent instanceof PhysicBox shape111) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicHeightMapChunk shape222) {
// detect collision from cube on height-map !!!
} else if (shape instanceof PhysicBox shape222) {
// detect collision between 2 cubes
if (ToolCollisionOBBWithOBB.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicSphere shape222) {
} else if (shape instanceof PhysicMapVoxel shape222) {
} else {
Log.error("Not manage collision model... " + shape);
}
}
} else if (shapeCurrent instanceof PhysicSphere shape111) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicHeightMapChunk shape222) {
// detect collision from sphere on height-map !!!
if (ToolCollisionSphereWithHeightMapChunk.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicTriangle shape222) {
// detect collision from sphere on height-map !!!
if (ToolCollisionSphereWithTriangle.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicBox shape222) {
// detect collision from sphere on cube !!!
} else if (shape instanceof PhysicSphere shape222) {
// detect collision from sphere on sphere !!!
if (ToolCollisionSphereWithSphere.testCollide(shape111, shape222)) {
return true;
}
} else if (shape instanceof PhysicMapVoxel shape222) {
} else {
Log.error("Not manage collision model... " + shape);
}
}
} else if (shapeCurrent instanceof PhysicMapVoxel shape111) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicBox shape222) {
} else if (shape instanceof PhysicSphere shape222) {
} else if (shape instanceof PhysicMapVoxel shape222) {
} else {
Log.error("Not manage collision model... " + shape);
}
}
} else {
Log.error("Not manage collision model... " + shapeCurrent);
}
return false;
}
public boolean checkNarrowCollision() {
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
return false;
}
for (ComponentPhysicsPerso elem : this.aabbIntersection) {
boolean collide = false;
for (PhysicShape shapeCurrent : this.shapes) {
if (elem.checkCollide(shapeCurrent)) {
collide = true;
break;
}
}
if (collide) {
if (!this.narrowIntersection.containsKey(elem)) {
this.narrowIntersection.put(elem, new ArrayList<>());
}
if (!elem.narrowIntersection.containsKey(this)) {
elem.narrowIntersection.put(this, new ArrayList<>());
}
}
}
return isNarrowCollide();
}
public void clearAABBIntersection() {
this.aabbIntersection.clear();
}
public void clearPreviousCollision() {
this.aabbIntersection.clear();
this.narrowIntersection.clear();
}
public void clearShape() {
this.shapes.clear();
}
public AABB getAABB() {
return this.aabb;
}
public List<ComponentPhysicsPerso> getAabbIntersection() {
return this.aabbIntersection;
}
public PhysicBodyType getBodyType() {
return this.bodyType;
}
private List<ColisionPoint> getCollidePoints(PhysicShape shapeRemote) {
List<ColisionPoint> out = new ArrayList<>();
if (shapeRemote instanceof PhysicSphere remoteShere) {
for (PhysicShape shape : this.shapes) {
if (shape instanceof PhysicSphere localShape) {
ColisionPoint point = ToolCollisionSphereWithSphere.getCollisionPoint(remoteShere, localShape);
if (point != null) {
out.add(point);
}
} else if (shape instanceof PhysicTriangle localShape) {
ColisionPoint point = ToolCollisionSphereWithTriangle.getCollisionPoint(remoteShere, localShape);
if (point != null) {
out.add(point);
}
}
}
} else if (shapeRemote instanceof PhysicTriangle) {
// nothing can happens ...
} else {
Log.error("Not manage collision model... " + shapeRemote);
}
return out;
}
public float getMaxSpeed() {
return this.maxSpeed;
}
@Override
public String getType() {
return EnginePhysicsPerso.ENGINE_NAME;
}
public boolean isManageGravity() {
return this.manageGravity;
}
public boolean isNarrowCollide() {
if (this.narrowIntersection.isEmpty()) {
return false;
}
return true;
}
private void limitWithMaxSpeed() {
if (this.speed.length2() > this.maxSpeed * this.maxSpeed) {
this.speed = this.speed.safeNormalize().multiply(this.maxSpeed);
}
}
public void narrowCollisionCreateContactAndForce() {
if (this.bodyType != PhysicBodyType.BODY_DYNAMIC) {
return;
}
if (this.narrowIntersection.size() == 0) {
return;
}
for (Entry<ComponentPhysicsPerso, List<ColisionPoint>> elem : this.narrowIntersection.entrySet()) {
for (PhysicShape shapeCurrent : this.shapes) {
//TODO Do a better method we do this many times ...
/*
if (!elem.checkCollide(shapeCurrent)) {
continue;
}
*/
List<ColisionPoint> points = elem.getKey().getCollidePoints(shapeCurrent);
elem.getValue().addAll(points);
}
}
}
@Override
public void removeFriendComponent(Component component) {
// nothing to do.
}
public void renderDebug(ResourceColored3DObject debugDrawProperty) {
Color displayColor;
displayColor = new Color(1.0f, 0.0f, 0.0f, 1.0f);
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 {
if (this.narrowIntersection.size() == 0) {
displayColor = new Color(0.0f, 1.0f, 0.0f, 1.0f);
} else {
displayColor = new Color(1.0f, 0.0f, 0.0f, 1.0f);
}
}
if (this.aabb != null) {
debugDrawProperty.drawCubeLine(this.aabb.getMin(), this.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");
}
for (PhysicShape shape : this.shapes) {
shape.renderDebug(this.position.getTransform(), debugDrawProperty);
}
}
public void setBodyType(PhysicBodyType bodyType) {
this.bodyType = bodyType;
}
public void setManageGravity(boolean manageGravity) {
this.manageGravity = manageGravity;
}
public void setMaxSpeed(float maxSpeed) {
this.maxSpeed = maxSpeed;
}
public void updateAABB() {
if (this.position == null) {
Log.info("No position in Entity ");
return;
}
// TODO Add a flag to check if it is needed to update the AABB...
AABB aabbNew = AABB.createInvertedEmpty();
for (PhysicShape shape : this.shapes) {
shape.updateAABB(this.position.getTransform(), aabbNew);
}
this.aabb = aabbNew;
}
public void updateForNarrowCollision() {
this.narrowIntersection.clear();
if (this.aabbIntersection.size() == 0) {
return;
}
if (this.position == null) {
Log.info("No position in Entity ");
return;
}
for (PhysicShape shape : this.shapes) {
shape.updateForNarrowCollision(this.position.getTransform());
}
}
}

View File

@ -3,21 +3,18 @@ package org.atriasoft.ege.components;
import org.atriasoft.ege.Component;
import org.atriasoft.ege.Signal;
import org.atriasoft.ege.components.part.PositionningInterface;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.etk.math.Transform3D;
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;
}
/**
@ -30,19 +27,13 @@ public class ComponentPosition extends Component implements PositionningInterfac
@Override
public void addFriendComponent(final Component component) {
if (component.getType().equals("physics")) {
Log.critical("Can not add a 'physics' component and a 'position' component ... ==> incompatible");
}
}
public void applyForce(Vector3f force) {
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
@ -57,10 +48,6 @@ 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,6 +1,5 @@
package org.atriasoft.ege.engines;
import java.util.List;
import java.util.Vector;
import org.atriasoft.ege.Component;
@ -8,105 +7,73 @@ import org.atriasoft.ege.Engine;
import org.atriasoft.ege.Environement;
import org.atriasoft.ege.camera.Camera;
import org.atriasoft.ege.components.ComponentPhysics;
import org.atriasoft.ege.components.PhysicBodyType;
import org.atriasoft.ege.internal.Log;
import org.atriasoft.ephysics.body.RigidBody;
import org.atriasoft.ephysics.collision.ContactManifold;
import org.atriasoft.ephysics.collision.shapes.AABB;
import org.atriasoft.ephysics.constraint.ContactPoint;
import org.atriasoft.ephysics.constraint.ContactPointInfo;
import org.atriasoft.ephysics.engine.DynamicsWorld;
import org.atriasoft.ephysics.engine.EventListener;
import org.atriasoft.ephysics.engine.Island;
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.phyligram.DebugDisplay;
import org.atriasoft.phyligram.shape.AABB;
public class EnginePhysics extends Engine implements EventListener {
public class EnginePhysics extends Engine {
public static final String ENGINE_NAME = "physics";
// Constant physics time step
private static final float TIME_STEP = 0.016f;//1.0f / 60.0f;
boolean propertyDebugAABB = false;
boolean propertyDebugShape = false;
// Start engine with no gravity
private final Vector3f gravity = new Vector3f(0.0f, 0.0f, 0.0f);
private static final float TIME_STEP = 0.005f;
private float accumulator = 0;
//private final EngineGravity gravity;
private final DynamicsWorld dynamicsWorld;
private EngineGravity gravity;
protected EnginePhysics engine;
private Vector<ComponentPhysics> components = new Vector<>();
private Vector<ComponentPhysics> componentsWithCollision = new Vector<>();
private ResourceColored3DObject debugDrawProperty = ResourceColored3DObject.create();
private final Vector<ComponentPhysics> components = new Vector<>();
private final ResourceColored3DObject debugDrawProperty = ResourceColored3DObject.create();
public EnginePhysics(final Environement env) {
public EnginePhysics(Environement env) {
super(env);
/*
this.gravity = (EngineGravity) env.getEngine("gravity");
if (this.gravity == null) {
Log.critical("Must initialyse Gravity before physics...");
}
*/
final Vector3f gravity = new Vector3f(0.0f, 0.0f, 0.0f);
this.dynamicsWorld = new DynamicsWorld(gravity);
// Set the number of iterations of the constraint solver
this.dynamicsWorld.setNbIterationsVelocitySolver(15);
this.dynamicsWorld.setEventListener(this);
}
private void applyForces(final float timeStep) {
for (final ComponentPhysics it : this.components) {
//it.applyForces(TIME_STEP, gravity);
}
}
@Override
public void beginContact(final ContactPointInfo contact) {
ComponentPhysics component1 = null;
ComponentPhysics component2 = null;
// Called when a new contact point is found between two bodies that were separated before.
Log.warning("collision detection [BEGIN] " + contact.localPoint1 + " depth=" + contact.penetrationDepth);
if (contact.shape1 != null && contact.shape1.getUserData() != null) {
component1 = (ComponentPhysics) contact.shape1.getUserData();
}
if (contact.shape2 != null && contact.shape2.getUserData() != null) {
component2 = (ComponentPhysics) contact.shape2.getUserData();
}
if (component1 != null) {
component1.beginContact(component2, contact.normal, contact.localPoint1, contact.localPoint2, contact.penetrationDepth);
}
if (component2 != null) {
component2.beginContact(component1, contact.normal.multiply(-1), contact.localPoint2, contact.localPoint1, contact.penetrationDepth);
}
}
@Override
public void beginInternalTick() {
// TODO Auto-generated method stub
}
@Override
public void componentAdd(final Component ref) {
if (!(ref instanceof ComponentPhysics elem)) {
private void addIncomponentWithCollision(ComponentPhysics elem) {
if (this.componentsWithCollision.contains(elem)) {
return;
}
this.components.add(elem);
elem.generate();
this.componentsWithCollision.add(elem);
}
private void applyForces(float timeStep) {
for (ComponentPhysics it : this.components) {
it.applyForces(timeStep, this.gravity);
}
}
/**
* Clear the previous data of collision.
*/
private void clearPreviousCycle() {
for (ComponentPhysics it : this.components) {
it.clearPreviousCollision();
}
}
@Override
public void componentRemove(final Component ref) {
public void componentAdd(Component ref) {
if (ref instanceof ComponentPhysics == false) {
return;
}
this.components.add((ComponentPhysics) ref);
}
@Override
public void componentRemove(Component ref) {
this.components.remove(ref);
}
@Override
public void endInternalTick() {
// TODO Auto-generated method stub
}
public DynamicsWorld getDynamicsWorld() {
return this.dynamicsWorld;
/**
* Collision Detection STEP 4: apply all calculated forces (with containts)
* @param timeStep
*/
private void generateResultCollisionsForces(float timeStep) {
for (ComponentPhysics it : this.componentsWithCollision) {
it.applyColisionForce(timeStep);
}
}
@Override
@ -116,32 +83,11 @@ public class EnginePhysics extends Engine implements EventListener {
}
@Override
public void newContact(final ContactPointInfo contact) {
ComponentPhysics component1 = null;
ComponentPhysics component2 = null;
//Called when a new contact point is found between two bodies.
Log.warning("collision detection [ NEW ] " + contact.localPoint1 + " depth=" + contact.penetrationDepth);
if (contact.shape1 != null && contact.shape1.getUserData() != null) {
component1 = (ComponentPhysics) contact.shape1.getUserData();
}
if (contact.shape2 != null && contact.shape2.getUserData() != null) {
component2 = (ComponentPhysics) contact.shape2.getUserData();
}
if (component1 != null) {
component1.newContact(component2, contact.normal, contact.localPoint1, contact.localPoint2, contact.penetrationDepth);
}
if (component2 != null) {
component2.newContact(component1, contact.normal.multiply(-1), contact.localPoint2, contact.localPoint1, contact.penetrationDepth);
}
}
@Override
public void render(final long deltaMili, final Camera camera) {
public void render(long deltaMili, Camera camera) {
// TODO Auto-generated method stub
for (final ComponentPhysics it : this.components) {
for (ComponentPhysics it : this.components) {
//Log.info("Render " + it);
it.renderDebug(this.debugDrawProperty, camera);
it.renderDebug(this.debugDrawProperty);
}
//debugDrawProperty.drawCone(2, 5, 9, 12, Matrix4f.identity(), new Color(1,1,0,1));
//debugDrawProperty.drawSquare(new Vector3f(1,1,1), Matrix4f.identity(), new Color(1,1,0,1));
@ -150,77 +96,93 @@ public class EnginePhysics extends Engine implements EventListener {
}
@Override
public void renderDebug(final long deltaMili, final Camera camera) {
if (this.propertyDebugShape) {
for (final ComponentPhysics it : this.components) {
it.drawShape(this.debugDrawProperty, camera);
}
}
if (this.propertyDebugAABB) {
for (final ComponentPhysics it : this.components) {
it.renderDebug(this.debugDrawProperty, camera);
}
}
final Matrix4f transformationMatrix = Matrix4f.IDENTITY;
final Color tmpColor = new Color(0.0f, 0.0f, 1.0f, 0.8f);
final List<Island> islands = this.dynamicsWorld.getIslands();
for (final Island it : islands) {
// TODO compute island AABB to display it ...
final AABB islandElements = new AABB();
for (final RigidBody elem : it.getBodies()) {
final AABB tmp = elem.getAABB();
islandElements.mergeWithAABB(tmp);
}
this.debugDrawProperty.drawCubeLine(islandElements.getMin(), islandElements.getMax(), tmpColor, transformationMatrix, true, true);
}
final List<ContactManifold> listContact = this.dynamicsWorld.getContactsList();
//Log.info("nb contact: " + listContact.size());
for (final ContactManifold it : listContact) {
for (int iii = 0; iii < it.getNbContactPoints(); iii++) {
final ContactPoint contact = it.getContactPoint(iii);
this.debugDrawProperty.drawSquare(new Vector3f(0.05f, 0.05f, 0.05f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(contact.getWorldPointOnBody1())), new Color(0, 1, 0, 1));
this.debugDrawProperty.drawSquare(new Vector3f(0.05f, 0.05f, 0.05f), Matrix4f.IDENTITY.multiply(Matrix4f.createMatrixTranslate(contact.getWorldPointOnBody2())), new Color(0, 1, 0, 1));
}
}
}
public void setGravity(final Vector3f _axePower) {
if (this.dynamicsWorld != null) {
final Vector3f gravity = _axePower;
this.dynamicsWorld.setGravity(gravity);
}
public void renderDebug(long deltaMili, Camera camera) {
// TODO Auto-generated method stub
DebugDisplay.onDraw();
DebugDisplay.clear();
}
@Override
public void update(long deltaMili) {
//Log.error("=================================================================" + deltaMili);
if (deltaMili > 1000) {
deltaMili = (long) (TIME_STEP * 1000.0f);
}
final float deltaTime = deltaMili * 0.0001f;
// Add the time difference in the accumulator
this.accumulator += deltaTime;
this.accumulator += deltaMili * 0.0001f;
// While there is enough accumulated time to take one or several physics steps
while (this.accumulator >= TIME_STEP) {
//Log.error("---------------------------------------------------" + TIME_STEP);
if (this.dynamicsWorld != null) {
// call every object to usdate their constant forces applied
for (final ComponentPhysics it : this.components) {
if (it != null) {
it.update(TIME_STEP);
}
}
// Update the Dynamics world with a constant time step
Log.debug("Update the Physic engine ... " + TIME_STEP);
this.dynamicsWorld.update(TIME_STEP);
}
Log.info("update physic ... " + this.accumulator);
clearPreviousCycle();
applyForces(TIME_STEP);
// update AABB after because in rotation force, the Bounding box change...
updateAABB(TIME_STEP);
// update the colision tree between each object in the room
updateCollisionsAABB(TIME_STEP);
updateCollisionsNarrowPhase(TIME_STEP);
generateResultCollisionsForces(TIME_STEP);
// Decrease the accumulated time
this.accumulator -= TIME_STEP;
}
for (final ComponentPhysics elem : this.components) {
elem.emitAll();
}
/**
* 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 : this.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
*/
// TODO : generate a B-TREE to manage collision, it is faster, but now, this is not the purpose ...
private void updateCollisionsAABB(float timeStep) {
this.componentsWithCollision.clear();
// clear all object intersection
for (ComponentPhysics it : this.components) {
it.clearAABBIntersection();
}
// update the current object intersection...
for (int iii = 0; iii < this.components.size(); iii++) {
ComponentPhysics current = this.components.get(iii);
AABB currentAABB = current.getAABB();
for (int jjj = iii + 1; jjj < this.components.size(); jjj++) {
ComponentPhysics 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);
remote.addIntersection(current);
addIncomponentWithCollision(remote);
addIncomponentWithCollision(current);
}
}
}
}
/**
* 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 : this.componentsWithCollision) {
it.updateForNarrowCollision();
}
// check for every component if the narrow collision is available.
for (int iii = 0; iii < this.componentsWithCollision.size(); iii++) {
ComponentPhysics current = this.componentsWithCollision.get(iii);
boolean collide = current.checkNarrowCollision();
}
// update the force of collision available.
for (int iii = 0; iii < this.components.size(); iii++) {
ComponentPhysics current = this.components.get(iii);
current.narrowCollisionCreateContactAndForce();
}
}

View File

@ -1,189 +0,0 @@
package org.atriasoft.ege.engines;
import java.util.Vector;
import org.atriasoft.ege.Component;
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;
import org.atriasoft.phyligram.shape.AABB;
public class EnginePhysicsPerso extends Engine {
public static final String ENGINE_NAME = "physicsPerso";
private static final float TIME_STEP = 0.005f;
private float accumulator = 0;
private EngineGravity gravity;
protected EnginePhysicsPerso engine;
private Vector<ComponentPhysicsPerso> components = new Vector<>();
private Vector<ComponentPhysicsPerso> componentsWithCollision = new Vector<>();
private ResourceColored3DObject debugDrawProperty = ResourceColored3DObject.create();
public EnginePhysicsPerso(Environement env) {
super(env);
this.gravity = (EngineGravity) env.getEngine("gravity");
if (this.gravity == null) {
Log.critical("Must initialyse Gravity before physics...");
}
}
private void addIncomponentWithCollision(ComponentPhysicsPerso elem) {
if (this.componentsWithCollision.contains(elem)) {
return;
}
this.componentsWithCollision.add(elem);
}
private void applyForces(float timeStep) {
for (ComponentPhysicsPerso it : this.components) {
it.applyForces(TIME_STEP, this.gravity);
}
}
/**
* Clear the previous data of collision.
*/
private void clearPreviousCycle() {
for (ComponentPhysicsPerso it : this.components) {
it.clearPreviousCollision();
}
}
@Override
public void componentAdd(Component ref) {
if (ref instanceof ComponentPhysicsPerso == false) {
return;
}
this.components.add((ComponentPhysicsPerso) ref);
}
@Override
public void componentRemove(Component ref) {
this.components.remove(ref);
}
/**
* Collision Detection STEP 4: apply all calculated forces (with containts)
* @param timeStep
*/
private void generateResultCollisionsForces(float timeStep) {
for (ComponentPhysicsPerso it : this.componentsWithCollision) {
it.applyColisionForce();
}
}
@Override
public String getType() {
// TODO Auto-generated method stub
return ENGINE_NAME;
}
@Override
public void render(long deltaMili, Camera camera) {
// TODO Auto-generated method stub
for (ComponentPhysicsPerso it : this.components) {
//Log.info("Render " + it);
it.renderDebug(this.debugDrawProperty);
}
//debugDrawProperty.drawCone(2, 5, 9, 12, Matrix4f.identity(), new Color(1,1,0,1));
//debugDrawProperty.drawSquare(new Vector3f(1,1,1), Matrix4f.identity(), new Color(1,1,0,1));
//debugDrawProperty.drawCubeLine(new Vector3f(1,1,1), new Vector3f(5,5,5), new Color(1,0,1,1), 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);
}
@Override
public void renderDebug(long deltaMili, Camera camera) {
// TODO Auto-generated method stub
DebugDisplay.onDraw();
DebugDisplay.clear();
}
@Override
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.info("update physic ... " + this.accumulator);
clearPreviousCycle();
applyForces(TIME_STEP);
// update AABB after because in rotation force, the Bounding box change...
updateAABB(TIME_STEP);
// update the colision tree between each object in the room
updateCollisionsAABB(TIME_STEP);
updateCollisionsNarrowPhase(TIME_STEP);
generateResultCollisionsForces(TIME_STEP);
// Decrease the accumulated time
this.accumulator -= TIME_STEP;
}
}
/**
* 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 (ComponentPhysicsPerso it : this.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
*/
// TODO : generate a B-TREE to manage collision, it is faster, but now, this is not the purpose ...
private void updateCollisionsAABB(float timeStep) {
this.componentsWithCollision.clear();
// clear all object intersection
for (ComponentPhysicsPerso it : this.components) {
it.clearAABBIntersection();
}
// update the current object intersection...
for (int iii = 0; iii < this.components.size(); iii++) {
ComponentPhysicsPerso current = this.components.get(iii);
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);
remote.addIntersection(current);
addIncomponentWithCollision(remote);
addIncomponentWithCollision(current);
}
}
}
}
/**
* 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 (ComponentPhysicsPerso it : this.componentsWithCollision) {
it.updateForNarrowCollision();
}
// check for every component if the narrow collision is available.
for (int iii = 0; iii < this.componentsWithCollision.size(); iii++) {
ComponentPhysicsPerso current = this.componentsWithCollision.get(iii);
boolean collide = current.checkNarrowCollision();
}
// update the force of collision available.
for (int iii = 0; iii < this.components.size(); iii++) {
ComponentPhysicsPerso current = this.components.get(iii);
current.narrowCollisionCreateContactAndForce();
}
}
}

View File

@ -16,7 +16,9 @@ public abstract class PhysicShape {
// protected Vector3f origin;
protected Transform3D transform;
protected Transform3D transformGlobal;
protected float mass = 0;
protected float mass = 0.0f;
protected float frictionCoefficient = 0.0f;
protected float bouncingCoefficient = 0.0f;
public PhysicShape() {
this.transform = Transform3D.IDENTITY;
@ -36,6 +38,14 @@ public abstract class PhysicShape {
this.colisionPoints.add(colision);
}
public float getBouncingCoefficient() {
return this.bouncingCoefficient;
}
public float getFrictionCoefficient() {
return this.frictionCoefficient;
}
public float getMass() {
return this.mass;
}
@ -62,6 +72,14 @@ public abstract class PhysicShape {
public abstract void renderDebug(Transform3D transform, ResourceColored3DObject debugDrawProperty);
public void setBouncingCoefficient(float bouncingCoefficient) {
this.bouncingCoefficient = bouncingCoefficient;
}
public void setFrictionCoefficient(float frictionCoefficient) {
this.frictionCoefficient = frictionCoefficient;
}
public void setMass(float mass) {
this.mass = mass;
}

View File

@ -1,8 +1,11 @@
package org.atriasoft.phyligram;
package org.atriasoft.phyligram.math;
import org.atriasoft.etk.math.Quaternion;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.phyligram.internal.Log;
import org.atriasoft.phyligram.ColisionPoint;
import org.atriasoft.phyligram.Collision;
import org.atriasoft.phyligram.DebugDisplay;
import org.atriasoft.phyligram.PhysicBox;
// set the relevant elements of our oriented bounding box
class OBB {
@ -11,101 +14,17 @@ class OBB {
public Vector3f axisY;
public Vector3f axisZ;
public Vector3f halfSize;
public OBB() {
position = Vector3f.ZERO;
axisX = Vector3f.ZERO;
axisY = Vector3f.ZERO;
axisZ = Vector3f.ZERO;
halfSize = Vector3f.ZERO;
this.position = Vector3f.ZERO;
this.axisX = Vector3f.ZERO;
this.axisY = Vector3f.ZERO;
this.axisZ = Vector3f.ZERO;
this.halfSize = Vector3f.ZERO;
}
};
}
public class ToolCollisionOBBWithOBB {
private ToolCollisionOBBWithOBB() {}
// check if there's a separating plane in between the selected axes
private static boolean getSeparatingPlane(Vector3f rPos, Vector3f plane, OBB box1, OBB box2) {
return (Math.abs(rPos.dot(plane)) > (Math.abs(box1.axisX.multiply(box1.halfSize.x()).dot(plane)) + Math.abs(box1.axisY.multiply(box1.halfSize.y()).dot(plane))
+ Math.abs(box1.axisZ.multiply(box1.halfSize.z()).dot(plane)) + Math.abs(box2.axisX.multiply(box2.halfSize.x()).dot(plane))
+ Math.abs(box2.axisY.multiply(box2.halfSize.y()).dot(plane)) + Math.abs(box2.axisZ.multiply(box2.halfSize.z()).dot(plane))));
}
// test for separating planes in all 15 axes
public static boolean getCollision(OBB box1, OBB box2) {
Vector3f rPos = box2.position.less(box1.position);
boolean ret = getSeparatingPlane(rPos, box1.axisX, box1, box2) || getSeparatingPlane(rPos, box1.axisY, box1, box2) || getSeparatingPlane(rPos, box1.axisZ, box1, box2)
|| getSeparatingPlane(rPos, box2.axisX, box1, box2) || getSeparatingPlane(rPos, box2.axisY, box1, box2) || getSeparatingPlane(rPos, box2.axisZ, box1, box2)
|| getSeparatingPlane(rPos, box1.axisX.cross(box2.axisX), box1, box2) || getSeparatingPlane(rPos, box1.axisX.cross(box2.axisY), box1, box2)
|| getSeparatingPlane(rPos, box1.axisX.cross(box2.axisZ), box1, box2) || getSeparatingPlane(rPos, box1.axisY.cross(box2.axisX), box1, box2)
|| getSeparatingPlane(rPos, box1.axisY.cross(box2.axisY), box1, box2) || getSeparatingPlane(rPos, box1.axisY.cross(box2.axisZ), box1, box2)
|| getSeparatingPlane(rPos, box1.axisZ.cross(box2.axisX), box1, box2) || getSeparatingPlane(rPos, box1.axisZ.cross(box2.axisY), box1, box2)
|| 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!!!");
// }
// }
// check if there's a separating plane in between the selected axes
private static boolean getSeparatingPlane222(Vector3f rPos, Vector3f plane, PhysicBox box1, PhysicBox box2) {
return (Math.abs(rPos.dot(plane)) > (Math.abs(box1.narrowPhaseAxisX.multiply(box1.narrowPhaseHalfSize.x()).dot(plane))
+ Math.abs(box1.narrowPhaseAxisY.multiply(box1.narrowPhaseHalfSize.y()).dot(plane)) + Math.abs(box1.narrowPhaseAxisZ.multiply(box1.narrowPhaseHalfSize.z()).dot(plane))
+ Math.abs(box2.narrowPhaseAxisX.multiply(box2.narrowPhaseHalfSize.x()).dot(plane)) + Math.abs(box2.narrowPhaseAxisY.multiply(box2.narrowPhaseHalfSize.y()).dot(plane))
+ Math.abs(box2.narrowPhaseAxisZ.multiply(box2.narrowPhaseHalfSize.z()).dot(plane))));
}
public static boolean testCollide(PhysicBox box1, PhysicBox box2) {
Vector3f rPos = box2.narrowPhaseGlobalPos.less(box1.narrowPhaseGlobalPos);
boolean ret = getSeparatingPlane222(rPos, box1.narrowPhaseAxisX, box1, box2) || getSeparatingPlane222(rPos, box1.narrowPhaseAxisY, box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ, box1, box2) || getSeparatingPlane222(rPos, box2.narrowPhaseAxisX, box1, box2)
|| getSeparatingPlane222(rPos, box2.narrowPhaseAxisY, box1, box2) || getSeparatingPlane222(rPos, box2.narrowPhaseAxisZ, box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisX.cross(box2.narrowPhaseAxisX), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisX.cross(box2.narrowPhaseAxisY), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisX.cross(box2.narrowPhaseAxisZ), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisY.cross(box2.narrowPhaseAxisX), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisY.cross(box2.narrowPhaseAxisY), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisY.cross(box2.narrowPhaseAxisZ), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ.cross(box2.narrowPhaseAxisX), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ.cross(box2.narrowPhaseAxisY), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ.cross(box2.narrowPhaseAxisZ), box1, box2);
return !ret;
}
public static void getCollidePoints(PhysicBox box1, boolean isStatic1, PhysicBox box2, boolean isStatic2) {
// Log.info("Try to calculare reverse force ........");
Vector3f rPos1 = box1.narrowPhaseGlobalPos.less(box2.narrowPhaseGlobalPos);
@ -116,7 +35,7 @@ public class ToolCollisionOBBWithOBB {
Quaternion quatTransfer1 = Quaternion.diff(quat1, quat2);
Quaternion quatTransfer2 = Quaternion.diff(quat2, quat1);
// quatTransfer.normalize();
// DebugDisplay.relativeTest = quatTransfer;
// Vector3f tmp = rPos.addNew(new Vector3f(0,0,14));
// DebugDisplay.relativeTestPos.getTransform().setPosition(tmp);
@ -133,7 +52,7 @@ public class ToolCollisionOBBWithOBB {
DebugDisplay.testQTransfert = quatTransfer2;
DebugDisplay.box1HalfSize = box2.narrowPhaseHalfSize;
DebugDisplay.box2HalfSize = box1.narrowPhaseHalfSize;
// DebugDisplay.relativeTestPos.getTransform().setPosition(tmp);
// DebugDisplay.relativeTestPos.getTransform().setOrientation(quatTransfer);
// DebugDisplay.boxTest.setSize(box1.getSize());
@ -150,7 +69,7 @@ public class ToolCollisionOBBWithOBB {
}
}
/* res = trensfert in generic plan the new res ... */
DebugDisplay.testRpos = quat1.inverse().getMatrix4().multiply(rPos2);
DebugDisplay.testQTransfert = quatTransfer1;
DebugDisplay.box1HalfSize = box1.narrowPhaseHalfSize;
@ -171,11 +90,11 @@ public class ToolCollisionOBBWithOBB {
Collision colision = new Collision(collide2, box1, collide1, isStatic1);
box2.addColision(colision);
}
}
public static ColisionPoint[] getCollidePointsAABBCenteredWithOBB(Vector3f box1HalfSize, Vector3f box2HalfSize, Quaternion box2Orientation, Vector3f box2Position) {
// point in AABB
Vector3f topBackRight = box2Orientation.multiply(new Vector3f(+box2HalfSize.x(), +box2HalfSize.y(), +box2HalfSize.z())).add(box2Position);
Vector3f topBackLeft = box2Orientation.multiply(new Vector3f(-box2HalfSize.x(), +box2HalfSize.y(), +box2HalfSize.z())).add(box2Position);
@ -288,18 +207,75 @@ public class ToolCollisionOBBWithOBB {
return out;
}
// line in AABB
// TODO:
// 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;
}
public static boolean pointInAABB(Vector3f halfSize, Vector3f point) {
if (point.x() > -halfSize.x() && point.x() < halfSize.x() && point.y() > -halfSize.y() && point.y() < halfSize.y() && point.z() > -halfSize.z() && point.z() < halfSize.z()) {
return true;
}
return false;
// test for separating planes in all 15 axes
public static boolean getCollision(OBB box1, OBB box2) {
Vector3f rPos = box2.position.less(box1.position);
boolean ret = getSeparatingPlane(rPos, box1.axisX, box1, box2) || getSeparatingPlane(rPos, box1.axisY, box1, box2) || getSeparatingPlane(rPos, box1.axisZ, box1, box2)
|| getSeparatingPlane(rPos, box2.axisX, box1, box2) || getSeparatingPlane(rPos, box2.axisY, box1, box2) || getSeparatingPlane(rPos, box2.axisZ, box1, box2)
|| getSeparatingPlane(rPos, box1.axisX.cross(box2.axisX), box1, box2) || getSeparatingPlane(rPos, box1.axisX.cross(box2.axisY), box1, box2)
|| getSeparatingPlane(rPos, box1.axisX.cross(box2.axisZ), box1, box2) || getSeparatingPlane(rPos, box1.axisY.cross(box2.axisX), box1, box2)
|| getSeparatingPlane(rPos, box1.axisY.cross(box2.axisY), box1, box2) || getSeparatingPlane(rPos, box1.axisY.cross(box2.axisZ), box1, box2)
|| getSeparatingPlane(rPos, box1.axisZ.cross(box2.axisX), box1, box2) || getSeparatingPlane(rPos, box1.axisZ.cross(box2.axisY), box1, box2)
|| 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!!!");
// }
// }
// check if there's a separating plane in between the selected axes
private static boolean getSeparatingPlane(Vector3f rPos, Vector3f plane, OBB box1, OBB box2) {
return (Math.abs(rPos.dot(plane)) > (Math.abs(box1.axisX.multiply(box1.halfSize.x()).dot(plane)) + Math.abs(box1.axisY.multiply(box1.halfSize.y()).dot(plane))
+ Math.abs(box1.axisZ.multiply(box1.halfSize.z()).dot(plane)) + Math.abs(box2.axisX.multiply(box2.halfSize.x()).dot(plane))
+ Math.abs(box2.axisY.multiply(box2.halfSize.y()).dot(plane)) + Math.abs(box2.axisZ.multiply(box2.halfSize.z()).dot(plane))));
}
// check if there's a separating plane in between the selected axes
private static boolean getSeparatingPlane222(Vector3f rPos, Vector3f plane, PhysicBox box1, PhysicBox box2) {
return (Math.abs(rPos.dot(plane)) > (Math.abs(box1.narrowPhaseAxisX.multiply(box1.narrowPhaseHalfSize.x()).dot(plane))
+ Math.abs(box1.narrowPhaseAxisY.multiply(box1.narrowPhaseHalfSize.y()).dot(plane)) + Math.abs(box1.narrowPhaseAxisZ.multiply(box1.narrowPhaseHalfSize.z()).dot(plane))
+ Math.abs(box2.narrowPhaseAxisX.multiply(box2.narrowPhaseHalfSize.x()).dot(plane)) + Math.abs(box2.narrowPhaseAxisY.multiply(box2.narrowPhaseHalfSize.y()).dot(plane))
+ Math.abs(box2.narrowPhaseAxisZ.multiply(box2.narrowPhaseHalfSize.z()).dot(plane))));
}
public static Vector3f pointDistanceInAABB(Vector3f halfSize, Vector3f point) {
float outX = 0;
float outY = 0;
@ -375,4 +351,31 @@ public class ToolCollisionOBBWithOBB {
outY = 0;
return new Vector3f(outX, outY, outZ);
}
public static boolean pointInAABB(Vector3f halfSize, Vector3f point) {
if (point.x() > -halfSize.x() && point.x() < halfSize.x() && point.y() > -halfSize.y() && point.y() < halfSize.y() && point.z() > -halfSize.z() && point.z() < halfSize.z()) {
return true;
}
return false;
}
public static boolean testCollide(PhysicBox box1, PhysicBox box2) {
Vector3f rPos = box2.narrowPhaseGlobalPos.less(box1.narrowPhaseGlobalPos);
boolean ret = getSeparatingPlane222(rPos, box1.narrowPhaseAxisX, box1, box2) || getSeparatingPlane222(rPos, box1.narrowPhaseAxisY, box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ, box1, box2) || getSeparatingPlane222(rPos, box2.narrowPhaseAxisX, box1, box2)
|| getSeparatingPlane222(rPos, box2.narrowPhaseAxisY, box1, box2) || getSeparatingPlane222(rPos, box2.narrowPhaseAxisZ, box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisX.cross(box2.narrowPhaseAxisX), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisX.cross(box2.narrowPhaseAxisY), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisX.cross(box2.narrowPhaseAxisZ), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisY.cross(box2.narrowPhaseAxisX), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisY.cross(box2.narrowPhaseAxisY), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisY.cross(box2.narrowPhaseAxisZ), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ.cross(box2.narrowPhaseAxisX), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ.cross(box2.narrowPhaseAxisY), box1, box2)
|| getSeparatingPlane222(rPos, box1.narrowPhaseAxisZ.cross(box2.narrowPhaseAxisZ), box1, box2);
return !ret;
}
private ToolCollisionOBBWithOBB() {}
}

View File

@ -1,7 +1,9 @@
package org.atriasoft.phyligram;
package org.atriasoft.phyligram.math;
import org.atriasoft.ege.geometry.Triangle;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.phyligram.PhysicHeightMapChunk;
import org.atriasoft.phyligram.PhysicSphere;
public class ToolCollisionSphereWithHeightMapChunk {
//intersection entre 2 droite (en 2d avec estimation en 3D

View File

@ -1,6 +1,8 @@
package org.atriasoft.phyligram;
package org.atriasoft.phyligram.math;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.phyligram.ColisionPoint;
import org.atriasoft.phyligram.PhysicSphere;
import org.atriasoft.phyligram.internal.Log;
public class ToolCollisionSphereWithSphere {

View File

@ -1,8 +1,11 @@
package org.atriasoft.phyligram;
package org.atriasoft.phyligram.math;
import org.atriasoft.ege.geometry.Plane;
import org.atriasoft.etk.math.FMath;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.phyligram.ColisionPoint;
import org.atriasoft.phyligram.PhysicSphere;
import org.atriasoft.phyligram.PhysicTriangle;
// https://realtimecollisiondetection.net/blog/?p=103
public class ToolCollisionSphereWithTriangle {

View File

@ -1,15 +1,16 @@
package org.atriasoft.phyligram.shape;
import org.atriasoft.ephysics.collision.Triangle;
import org.atriasoft.ege.geometry.Triangle;
public class HeightMapChunk extends Shape {
private Triangle[] triangles;
public HeightMapChunk(Triangle[] triangles) {
this.triangles = triangles;
}
@Override
public void display() {
// TODO Auto-generated method stub
super.display();
}