From ea6001ee1aa3333034d6b795badc1c46dc10666f Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 5 Dec 2021 22:27:55 +0100 Subject: [PATCH] [DEV] add my old physic engine objective is adapted with simple game engine ==> no real need of the conplexity of the real physic engine... --- .project | 6 + .pydevproject | 5 + blender/io_scene_emf/__init__.py | 2 +- blender/io_scene_emf/exportEmf.py | 16 +- blender/io_scene_emf/export_emf.py | 2 +- .../ege/loxelEngine/LoxelApplication.java | 2 +- .../ege/loxelEngine/MainLoxelEngine.java | 4 +- .../atriasoft/ege/loxelEnginePerso/Log.java | 39 ++ .../LoxelApplicationPerso.java | 438 ++++++++++++++++++ .../MainLoxelEnginePerso.java | 19 + src/module-info.java | 1 + src/org/atriasoft/ege/Environement.java | 3 + .../ege/components/ComponentLight.java | 7 +- .../ege/components/ComponentPhysics.java | 16 +- .../ege/components/ComponentPhysicsPerso.java | 334 +++++++++++++ .../ege/components/ComponentPlayer.java | 2 +- .../ege/components/ComponentPosition.java | 4 +- .../ege/engines/EnginePhysicsPerso.java | 152 ++++++ .../atriasoft/ege/physics/shape/Shape.java | 2 + .../atriasoft/phyligram/ColisionPoints.java | 13 + src/org/atriasoft/phyligram/Collision.java | 17 + src/org/atriasoft/phyligram/DebugDisplay.java | 327 +++++++++++++ src/org/atriasoft/phyligram/GravityMap.java | 7 + src/org/atriasoft/phyligram/PhysicBox.java | 112 +++++ .../phyligram/PhysicCollisionAABB.java | 77 +++ .../atriasoft/phyligram/PhysicMapVoxel.java | 42 ++ src/org/atriasoft/phyligram/PhysicShape.java | 101 ++++ .../atriasoft/phyligram/PhysicShapeType.java | 13 + src/org/atriasoft/phyligram/PhysicSphere.java | 38 ++ .../phyligram/ToolCollisionOBBWithOBB.java | 378 +++++++++++++++ src/org/atriasoft/phyligram/internal/Log.java | 68 +++ 31 files changed, 2229 insertions(+), 18 deletions(-) create mode 100644 .pydevproject create mode 100644 samples/src/sample/atriasoft/ege/loxelEnginePerso/Log.java create mode 100644 samples/src/sample/atriasoft/ege/loxelEnginePerso/LoxelApplicationPerso.java create mode 100644 samples/src/sample/atriasoft/ege/loxelEnginePerso/MainLoxelEnginePerso.java create mode 100644 src/org/atriasoft/ege/components/ComponentPhysicsPerso.java create mode 100644 src/org/atriasoft/ege/engines/EnginePhysicsPerso.java create mode 100644 src/org/atriasoft/phyligram/ColisionPoints.java create mode 100644 src/org/atriasoft/phyligram/Collision.java create mode 100644 src/org/atriasoft/phyligram/DebugDisplay.java create mode 100644 src/org/atriasoft/phyligram/GravityMap.java create mode 100644 src/org/atriasoft/phyligram/PhysicBox.java create mode 100644 src/org/atriasoft/phyligram/PhysicCollisionAABB.java create mode 100644 src/org/atriasoft/phyligram/PhysicMapVoxel.java create mode 100644 src/org/atriasoft/phyligram/PhysicShape.java create mode 100644 src/org/atriasoft/phyligram/PhysicShapeType.java create mode 100644 src/org/atriasoft/phyligram/PhysicSphere.java create mode 100644 src/org/atriasoft/phyligram/ToolCollisionOBBWithOBB.java create mode 100644 src/org/atriasoft/phyligram/internal/Log.java diff --git a/.project b/.project index 3c97cd6..1902c26 100644 --- a/.project +++ b/.project @@ -6,6 +6,11 @@ atriasoft-ege + + org.python.pydev.PyDevBuilder + + + org.eclipse.jdt.core.javabuilder @@ -14,5 +19,6 @@ org.eclipse.jdt.core.javanature + org.python.pydev.pythonNature diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..2b04565 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,5 @@ + + + Default + python interpreter + diff --git a/blender/io_scene_emf/__init__.py b/blender/io_scene_emf/__init__.py index 3589674..2d8d173 100644 --- a/blender/io_scene_emf/__init__.py +++ b/blender/io_scene_emf/__init__.py @@ -125,7 +125,7 @@ class ExportEMF(bpy.types.Operator, ExportHelper): global_matrix[0][0] = \ global_matrix[1][1] = \ - global_matrix[2][2] = self.global_scale + global_matrix[2][2] = 1.0 #self.global_scale return export_emf.save(self, context, **keywords) diff --git a/blender/io_scene_emf/exportEmf.py b/blender/io_scene_emf/exportEmf.py index 7d8b37b..3c2c122 100644 --- a/blender/io_scene_emf/exportEmf.py +++ b/blender/io_scene_emf/exportEmf.py @@ -8,5 +8,17 @@ import bpy #bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ege/samples/resources/emf/Entry.emf") -bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/workspace-game/model/tower.blend") -bpy.ops.export_scene.emf(filepath="/home/heero/dev/workspace-game/atriasoft/ege/samples/resources/emf/tower.emf") +bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/truck1.blend") +bpy.ops.export_scene.emf(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/truck_001.emf") + +bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/truck2.blend") +bpy.ops.export_scene.emf(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/truck_002.emf") + +bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/truck3.blend") +bpy.ops.export_scene.emf(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/truck_003.emf") + +bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/car1.blend") +bpy.ops.export_scene.emf(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/car_001.emf") + +bpy.ops.wm.open_mainfile(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/map_2.blend") +bpy.ops.export_scene.emf(filepath="/home/heero/dev/WORKSPACE-game/Edouard-DUPIN/zleep/resources/lowPoly/map_002.emf") \ No newline at end of file diff --git a/blender/io_scene_emf/export_emf.py b/blender/io_scene_emf/export_emf.py index dbdb49e..b3ecf17 100644 --- a/blender/io_scene_emf/export_emf.py +++ b/blender/io_scene_emf/export_emf.py @@ -684,7 +684,7 @@ def _write(context, collection = col break if collection.name != "root": - raise "Can not detect collition 'root'" + raise "Can not detect collection 'root'" #print("* collection name: " + str(collection.name) + "/" + str(collection.name_full) ) print("============================================================================================"); diff --git a/samples/src/sample/atriasoft/ege/loxelEngine/LoxelApplication.java b/samples/src/sample/atriasoft/ege/loxelEngine/LoxelApplication.java index cb9b242..a0a0ccc 100644 --- a/samples/src/sample/atriasoft/ege/loxelEngine/LoxelApplication.java +++ b/samples/src/sample/atriasoft/ege/loxelEngine/LoxelApplication.java @@ -37,8 +37,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; diff --git a/samples/src/sample/atriasoft/ege/loxelEngine/MainLoxelEngine.java b/samples/src/sample/atriasoft/ege/loxelEngine/MainLoxelEngine.java index 77eb2bf..c9b1b0f 100644 --- a/samples/src/sample/atriasoft/ege/loxelEngine/MainLoxelEngine.java +++ b/samples/src/sample/atriasoft/ege/loxelEngine/MainLoxelEngine.java @@ -12,8 +12,8 @@ public class MainLoxelEngine { Ege.init(); Uri.setGroup("DATA", "data/"); Uri.setGroup("RES", "res"); - Uri.addLibrary("loxelEngine", MainCollisionTest.class, "testDataLoxelEngine/"); - Uri.setApplication(MainCollisionTest.class, ""); + Uri.addLibrary("loxelEngine", MainLoxelEngine.class, "testDataLoxelEngine/"); + Uri.setApplication(MainLoxelEngine.class, ""); Gale.run(new LoxelApplication(), args); } } diff --git a/samples/src/sample/atriasoft/ege/loxelEnginePerso/Log.java b/samples/src/sample/atriasoft/ege/loxelEnginePerso/Log.java new file mode 100644 index 0000000..e2a2ac6 --- /dev/null +++ b/samples/src/sample/atriasoft/ege/loxelEnginePerso/Log.java @@ -0,0 +1,39 @@ +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() {} +} diff --git a/samples/src/sample/atriasoft/ege/loxelEnginePerso/LoxelApplicationPerso.java b/samples/src/sample/atriasoft/ege/loxelEnginePerso/LoxelApplicationPerso.java new file mode 100644 index 0000000..15acab3 --- /dev/null +++ b/samples/src/sample/atriasoft/ege/loxelEnginePerso/LoxelApplicationPerso.java @@ -0,0 +1,438 @@ +package sample.atriasoft.ege.loxelEnginePerso; + +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.ComponentPhysicsPerso; +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.phyligram.PhysicBox; +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; + +public class LoxelApplicationPerso extends GaleApplication { + public static Vector3f box1HalfSize; + public static Vector3f box2HalfSize; + // public static ComponentPosition relativeTestPos; + // public static Box boxTest; + public static List testPoints = new ArrayList<>(); + public static List testPointsBox = new ArrayList<>(); + public static List 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 LoxelApplicationPerso() { + + } + + @Override + public void onCreate(final GaleContext context) { + // set the system global max speed + //ComponentPhysicsPerso.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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 0, 5)))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + final PhysicBox box2 = new PhysicBox(); + 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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 4, 12.5f)))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + final PhysicBox box2 = new PhysicBox(); + 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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-2, 2, 14.5f)))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + final PhysicBox box2 = new PhysicBox(); + 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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-5, -5, 14)))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + final PhysicBox box2 = new PhysicBox(); + 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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(15, 15, 14), orientation))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + final PhysicBox box2 = new PhysicBox(); + 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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(2, -2, 14.2f), orientation))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + // TODO: physics2.setAngularReactionEnable(false); + final PhysicBox box2 = new PhysicBox(); + 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"))); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0, 0, 0.0f), orientation))); + final ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(this.env); + physics2.setBodyType(PhysicBodyType.BODY_STATIC); + final PhysicBox box2 = new PhysicBox(); + 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"))); + // ComponentPhysicsPerso physics2 = new ComponentPhysicsPerso(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))); + player.addComponent(new ComponentPosition(playerTransform)); + final ComponentPhysicsPerso physics = new ComponentPhysicsPerso(this.env); + physics.setBodyType(PhysicBodyType.BODY_DYNAMIC); + //physics.setAngularReactionEnable(false); + //physics.setSleepingEnable(false); + final PhysicBox box = new PhysicBox(); + 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 < LoxelApplicationPerso.testPoints.size(); iii++) { + final Vector3f elem = LoxelApplicationPerso.testPoints.get(iii); + final boolean collide = LoxelApplicationPerso.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 < LoxelApplicationPerso.testPointsBox.size(); iii++) { + final Vector3f elem = LoxelApplicationPerso.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 (LoxelApplicationPerso.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(LoxelApplicationPerso.testRpos.x(), LoxelApplicationPerso.testRpos.y(), LoxelApplicationPerso.testRpos.z())) + .multiply(Matrix4f.createMatrixTranslate(new Vector3f(0, 0, 14))).multiply(LoxelApplicationPerso.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(LoxelApplicationPerso.box2HalfSize, transformation, new Color(0, 1, 0, 0.5f)); + this.debugDrawProperty.drawSquare(LoxelApplicationPerso.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(); + } +} diff --git a/samples/src/sample/atriasoft/ege/loxelEnginePerso/MainLoxelEnginePerso.java b/samples/src/sample/atriasoft/ege/loxelEnginePerso/MainLoxelEnginePerso.java new file mode 100644 index 0000000..0513658 --- /dev/null +++ b/samples/src/sample/atriasoft/ege/loxelEnginePerso/MainLoxelEnginePerso.java @@ -0,0 +1,19 @@ +package sample.atriasoft.ege.loxelEnginePerso; + +import org.atriasoft.ege.Ege; +import org.atriasoft.etk.Uri; +import org.atriasoft.gale.Gale; + +import sample.atriasoft.ege.collisiontest.MainCollisionTest; + +public class MainLoxelEnginePerso { + public static void main(final String[] args) { + Gale.init(); + Ege.init(); + Uri.setGroup("DATA", "data/"); + Uri.setGroup("RES", "res"); + Uri.addLibrary("loxelEngine", MainLoxelEnginePerso.class, "testDataLoxelEngine/"); + Uri.setApplication(MainLoxelEnginePerso.class, ""); + Gale.run(new LoxelApplicationPerso(), args); + } +} diff --git a/src/module-info.java b/src/module-info.java index 2ff9ef9..341c3ed 100644 --- a/src/module-info.java +++ b/src/module-info.java @@ -11,6 +11,7 @@ open module org.atriasoft.ege { exports org.atriasoft.ege.map; exports org.atriasoft.ege.physics.shape; exports org.atriasoft.ege.tools; + exports org.atriasoft.phyligram; exports entities; exports guis; exports models; diff --git a/src/org/atriasoft/ege/Environement.java b/src/org/atriasoft/ege/Environement.java index 1c4f6fd..5feee6f 100644 --- a/src/org/atriasoft/ege/Environement.java +++ b/src/org/atriasoft/ege/Environement.java @@ -8,12 +8,14 @@ import java.util.List; import java.util.Map; import org.atriasoft.ege.camera.Camera; +import org.atriasoft.ege.components.ComponentPhysicsPerso; import org.atriasoft.ege.engines.EngineAI; 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.EnginePhysics; +import org.atriasoft.ege.engines.EnginePhysicsPerso; import org.atriasoft.ege.engines.EnginePlayer; import org.atriasoft.ege.engines.EngineRender; import org.atriasoft.ege.internal.Log; @@ -72,6 +74,7 @@ public class Environement { addEngine(new EngineDynamicMeshs(this)); addEngine(new EngineRender(this)); addEngine(new EnginePhysics(this)); + addEngine(new EnginePhysicsPerso(this)); addEngine(new EngineParticle(this)); addEngine(new EngineLight(this)); startClock = Clock.systemUTC(); diff --git a/src/org/atriasoft/ege/components/ComponentLight.java b/src/org/atriasoft/ege/components/ComponentLight.java index b774397..896cd5b 100644 --- a/src/org/atriasoft/ege/components/ComponentLight.java +++ b/src/org/atriasoft/ege/components/ComponentLight.java @@ -3,6 +3,7 @@ package org.atriasoft.ege.components; import org.atriasoft.ege.Component; import org.atriasoft.ege.Light; import org.atriasoft.ege.components.part.PositionningInterface; +import org.atriasoft.ege.internal.Log; import org.atriasoft.etk.math.Vector3f; public class ComponentLight extends Component { @@ -21,7 +22,11 @@ public class ComponentLight extends Component { @Override public void addFriendComponent(final Component component) { if (component.getType().contentEquals("position") || component.getType().contentEquals("physics")) { - this.position = (PositionningInterface)component; + if (component instanceof PositionningInterface tmp) { + this.position = tmp; + } else { + Log.error("component: " + component.getClass().getCanonicalName() + " is not an instance of " + PositionningInterface.class.getCanonicalName()); + } } } diff --git a/src/org/atriasoft/ege/components/ComponentPhysics.java b/src/org/atriasoft/ege/components/ComponentPhysics.java index f2b95bd..716922f 100644 --- a/src/org/atriasoft/ege/components/ComponentPhysics.java +++ b/src/org/atriasoft/ege/components/ComponentPhysics.java @@ -7,6 +7,7 @@ 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.EnginePhysics; import org.atriasoft.ege.internal.Log; import org.atriasoft.ege.physics.shape.Box; @@ -38,8 +39,8 @@ import org.atriasoft.etk.math.Transform3D; import org.atriasoft.etk.math.Vector3f; import org.atriasoft.gale.resource.ResourceColored3DObject; -public class ComponentPhysics extends Component { - public Signal signalPosition = new Signal<>();; +public class ComponentPhysics extends Component implements PositionningInterface { + public Signal signalPosition = new Signal<>(); protected Transform3D lastTransformEmit; protected EnginePhysics engine; protected RigidBody rigidBody; @@ -232,7 +233,7 @@ public class ComponentPhysics extends Component { Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix(); transformationMatrixLocal = transformationMatrixLocal.transpose(); - transformationMatrixLocal = transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); + transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); _draw.drawSquare(tmpElement.getSize(), transformationMatrixLocal, tmpColor); } else if (it.isCylinder()) { Log.debug(" Cylinder"); @@ -241,7 +242,7 @@ public class ComponentPhysics extends Component { Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix(); transformationMatrixLocal = transformationMatrixLocal.transpose(); - transformationMatrixLocal = transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); + transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); _draw.drawCylinder(tmpElement.getRadius(), tmpElement.getSize(), 10, 10, transformationMatrixLocal, tmpColor); } else if (it.isCapsule()) { Log.debug(" Capsule"); @@ -250,7 +251,7 @@ public class ComponentPhysics extends Component { Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix(); transformationMatrixLocal = transformationMatrixLocal.transpose(); - transformationMatrixLocal = transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); + transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); _draw.drawCapsule(tmpElement.getRadius(), tmpElement.getSize(), 10, 10, transformationMatrixLocal, tmpColor); } else if (it.isCone()) { Log.debug(" Cone"); @@ -259,7 +260,7 @@ public class ComponentPhysics extends Component { Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix(); transformationMatrixLocal = transformationMatrixLocal.transpose(); - transformationMatrixLocal = transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); + transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); _draw.drawCone(tmpElement.getRadius(), tmpElement.getSize(), 10, 10, transformationMatrixLocal, tmpColor); } else if (it.isSphere()) { @@ -269,7 +270,7 @@ public class ComponentPhysics extends Component { Matrix4f transformationMatrixLocal = transformLocal.getOpenGLMatrix(); transformationMatrixLocal = transformationMatrixLocal.transpose(); - transformationMatrixLocal = transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); + transformationMatrixLocal = transformationMatrix.multiply(transformationMatrixLocal); _draw.drawSphere(tmpElement.getRadius(), 10, 10, transformationMatrixLocal, tmpColor); } else if (it.isConcave()) { @@ -453,6 +454,7 @@ public class ComponentPhysics extends Component { * set a new transformation * @return Transformation of the position */ + @Override public Transform3D getTransform() { if (this.rigidBody == null) { return Transform3D.IDENTITY; diff --git a/src/org/atriasoft/ege/components/ComponentPhysicsPerso.java b/src/org/atriasoft/ege/components/ComponentPhysicsPerso.java new file mode 100644 index 0000000..4df62e6 --- /dev/null +++ b/src/org/atriasoft/ege/components/ComponentPhysicsPerso.java @@ -0,0 +1,334 @@ +package org.atriasoft.ege.components; + +import java.util.ArrayList; +import java.util.List; + +import org.atriasoft.etk.Color; +import org.atriasoft.etk.math.Matrix4f; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.gale.resource.ResourceColored3DObject; +import org.atriasoft.ege.internal.Log; +import org.atriasoft.ege.Component; +import org.atriasoft.ege.Environement; +import org.atriasoft.ege.engines.EngineGravity; +import org.atriasoft.ege.engines.EnginePhysics; +import org.atriasoft.ege.engines.EnginePhysicsPerso; +import org.atriasoft.phyligram.PhysicBox; +import org.atriasoft.phyligram.PhysicCollisionAABB; +import org.atriasoft.phyligram.PhysicMapVoxel; +import org.atriasoft.phyligram.PhysicShape; +import org.atriasoft.phyligram.PhysicSphere; +import org.atriasoft.phyligram.ToolCollisionOBBWithOBB; + + +public class ComponentPhysicsPerso extends Component { + private PhysicCollisionAABB aabb; + private List aabbIntersection = new ArrayList(); + private List narrowIntersection = new ArrayList(); + private List shapes = new ArrayList(); + private ComponentPosition position; + private boolean staticObject = false; + private boolean manageGravity = false; + public static float globalMaxSpeed = Float.MAX_VALUE; + private float maxSpeed = globalMaxSpeed; + // current speed of the object + private Vector3f speed = new Vector3f(0,0,0); + // current acceleration of the object + private Vector3f acceleration = new Vector3f(0,0,0); + // Applied static force on it + private Vector3f staticForce = new Vector3f(0,0,0); + // Apply dynamic force on it + private Vector3f dynamicForce = new Vector3f(0,0,0); + private EnginePhysicsPerso engine; + private PhysicBodyType bodyType; + + + @Override + public String getType() { + return EnginePhysicsPerso.ENGINE_NAME; + } + + 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) { + position = tmp; + } else { + Log.error("Not manage position model..."); + } + } + } + @Override + public void removeFriendComponent(Component component) { + // nothing to do. + } + + public void updateAABB() { + if (position == null) { + Log.info("No position in Entity "); + return; + } + // TODO Add a flag to check if it is needed to update the AABB... + PhysicCollisionAABB aabbNew = PhysicCollisionAABB.beforeCalculated(); + for (PhysicShape shape : shapes) { + shape.updateAABB(position.getTransform(), aabbNew); + } + aabb = aabbNew; + } + + public PhysicCollisionAABB getAABB() { + return aabb; + } + + public void updateForNarrowCollision() { + narrowIntersection.clear(); + if (aabbIntersection.size() == 0) { + return; + } + if (position == null) { + Log.info("No position in Entity "); + return; + } + for (PhysicShape shape : shapes) { + shape.updateForNarrowCollision(position.getTransform()); + } + } + public boolean isNarrowCollide() { + if (narrowIntersection.size() == 0) { + return false; + } + return true; + } + public boolean checkNarrowCollision() { + if (this.staticObject == true) { + return false; + } + for (ComponentPhysicsPerso elem : aabbIntersection) { + boolean collide = false; + for (PhysicShape shapeCurrent : shapes) { + if (elem.checkCollide(shapeCurrent) == true) { + collide = true; + break; + } + } + if (collide == true) { + narrowIntersection.add(elem); + elem.narrowIntersection.add(this); + } + } + return isNarrowCollide(); + } + public void narrowCollisionCreateContactAndForce() { + if (narrowIntersection.size() == 0) { + return; + } + for (ComponentPhysicsPerso elem : narrowIntersection) { + for (PhysicShape shapeCurrent : this.shapes) { + //TODO Do a better method we do this many times ... + if (elem.checkCollide(shapeCurrent) == false) { + continue; + } + elem.getCollidePoints(shapeCurrent, this.staticObject); + } + } + } + + private boolean checkCollide(PhysicShape shapeCurrent) { + if (shapeCurrent instanceof PhysicBox) { + PhysicBox shape111 = (PhysicBox)shapeCurrent; + for (PhysicShape shape : shapes) { + if (shape instanceof PhysicBox) { + PhysicBox shape222 = (PhysicBox)shape; + if (ToolCollisionOBBWithOBB.testCollide(shape111, shape222) == true) { + return true; + } + } else if (shape instanceof PhysicSphere) { + + } else if (shape instanceof PhysicMapVoxel) { + + } else { + Log.error("Not manage collision model... " + shape); + } + } + } else if (shapeCurrent instanceof PhysicSphere) { + for (PhysicShape shape : shapes) { + if (shape instanceof PhysicBox) { + + } else if (shape instanceof PhysicSphere) { + + } else if (shape instanceof PhysicMapVoxel) { + + } else { + Log.error("Not manage collision model... " + shape); + } + } + } else if (shapeCurrent instanceof PhysicMapVoxel) { + for (PhysicShape shape : shapes) { + if (shape instanceof PhysicBox) { + + } else if (shape instanceof PhysicSphere) { + + } else if (shape instanceof PhysicMapVoxel) { + + } else { + Log.error("Not manage collision model... " + shape); + } + } + } else { + Log.error("Not manage collision model... " + shapeCurrent); + } + return false; + } + private void getCollidePoints(PhysicShape shapeCurrent, boolean isStatic) { + if (shapeCurrent instanceof PhysicBox) { + PhysicBox shape111 = (PhysicBox)shapeCurrent; + for (PhysicShape shape : this.shapes) { + if (shape instanceof PhysicBox) { + PhysicBox shape222 = (PhysicBox)shape; + ToolCollisionOBBWithOBB.getCollidePoints(shape111, isStatic, shape222, this.staticObject); + } else if (shape instanceof PhysicSphere) { + + } else if (shape instanceof PhysicMapVoxel) { + + } else { + Log.error("Not manage collision model... " + shape); + } + } + } else if (shapeCurrent instanceof PhysicSphere) { + for (PhysicShape shape : this.shapes) { + if (shape instanceof PhysicBox) { + + } else if (shape instanceof PhysicSphere) { + + } else if (shape instanceof PhysicMapVoxel) { + + } else { + Log.error("Not manage collision model... " + shape); + } + } + } else if (shapeCurrent instanceof PhysicMapVoxel) { + for (PhysicShape shape : this.shapes) { + if (shape instanceof PhysicBox) { + + } else if (shape instanceof PhysicSphere) { + + } else if (shape instanceof PhysicMapVoxel) { + + } else { + Log.error("Not manage collision model... " + shape); + } + } + } else { + Log.error("Not manage collision model... " + shapeCurrent); + } + return; + } + + public void applyForces(float timeStep, EngineGravity gravity) { + // get the gravity at the specific position... + Vector3f gravityForce; + if (manageGravity == true) { + gravityForce = gravity.getGravityAtPosition(position.getTransform().getPosition()).multiply(timeStep); + } else { + gravityForce = new Vector3f(0,0,0); + } + // apply this force on the Object + Log.info("apply gravity: " + gravityForce); + // relative to the object + Vector3f staticForce = this.staticForce.multiply(timeStep); + float globalMass = 0; + for (PhysicShape shape : shapes) { + globalMass += shape.getMass(); + } + // note the acceleration is not real, it depend on the current delta time... + this.acceleration = gravityForce.add(this.position.getTransform().getOrientation().multiply(staticForce)).add(this.position.getTransform().getOrientation().multiply(dynamicForce)).multiply(globalMass); + this.dynamicForce = new Vector3f(0,0,0); + this.speed.add(this.acceleration); + limitWithMaxSpeed(); + Log.info("apply acceleration: " + this.acceleration); + Log.info("apply speed: " + this.speed); + this.position.getTransform().getPosition().add(this.speed.multiply(timeStep)); + } + + public void renderDebug(ResourceColored3DObject debugDrawProperty) { + Color displayColor; + if (this.aabbIntersection.size() == 0) { + displayColor = new Color(1,1,1,1); + } else { + if (this.narrowIntersection.size() == 0) { + displayColor = new Color(1,1,0,1); + } else { + displayColor = new Color(1,0,0,1); + } + } + if (aabb != null) { + debugDrawProperty.drawCubeLine(aabb.getMin(), aabb.getMax(), displayColor, Matrix4f.IDENTITY, true, true); + //debugDrawProperty.drawCubeLine(new Vector3f(0,0,0), new Vector3f(32,32,32), new Color(1,0,1,1), Matrix4f.identity(), true, true); + } else { + Log.error("no AABB"); + } + for (PhysicShape shape : shapes) { + shape.renderDebug(position.getTransform(), debugDrawProperty); + } + } + public void addShape(PhysicShape shape) { + shapes.add(shape); + } + public void clearShape() { + shapes.clear(); + } + public boolean isManageGravity() { + return manageGravity; + } + public void setManageGravity(boolean manageGravity) { + this.manageGravity = manageGravity; + } + private void limitWithMaxSpeed() { + if (this.speed.length2() > this.maxSpeed*this.maxSpeed) { + this.speed.safeNormalize().multiply(this.maxSpeed); + } + } + public float getMaxSpeed() { + return maxSpeed; + } + + public void setMaxSpeed(float maxSpeed) { + this.maxSpeed = maxSpeed; + } + + public void clearAABBIntersection() { + this.aabbIntersection.clear(); + } + public void addIntersection(ComponentPhysicsPerso component) { + // do not add multiple times + for (ComponentPhysicsPerso elem : this.aabbIntersection) { + if (elem == component) { + return; + } + } + this.aabbIntersection.add(component); + } + public List getAabbIntersection() { + return aabbIntersection; + } + + public boolean isStaticObject() { + return staticObject; + } + + public void setStaticObject(boolean staticObject) { + this.staticObject = staticObject; + } + + public PhysicBodyType getBodyType() { + return bodyType; + } + + public void setBodyType(PhysicBodyType bodyType) { + this.bodyType = bodyType; + } +} diff --git a/src/org/atriasoft/ege/components/ComponentPlayer.java b/src/org/atriasoft/ege/components/ComponentPlayer.java index 4f5ae32..58edbff 100644 --- a/src/org/atriasoft/ege/components/ComponentPlayer.java +++ b/src/org/atriasoft/ege/components/ComponentPlayer.java @@ -4,7 +4,7 @@ import org.atriasoft.ege.Component; import org.atriasoft.ege.engines.EnginePlayer; public class ComponentPlayer extends Component { - private float runSpeed = 35; + private float runSpeed = 20; private float strafSpeed = 25; private float turnSpeed = 0.45f; private float jumpPower = 30; diff --git a/src/org/atriasoft/ege/components/ComponentPosition.java b/src/org/atriasoft/ege/components/ComponentPosition.java index 6647a50..2c9fa08 100644 --- a/src/org/atriasoft/ege/components/ComponentPosition.java +++ b/src/org/atriasoft/ege/components/ComponentPosition.java @@ -27,8 +27,8 @@ public class ComponentPosition extends Component implements PositionningInterfac @Override public void addFriendComponent(final Component component) { - if (component.getType().contains("physics")) { - Log.critical("Can not add a 'physic' component and a 'position' component ... ==> incompatible"); + if (component.getType().equals("physics")) { + Log.critical("Can not add a 'physics' component and a 'position' component ... ==> incompatible"); } } diff --git a/src/org/atriasoft/ege/engines/EnginePhysicsPerso.java b/src/org/atriasoft/ege/engines/EnginePhysicsPerso.java new file mode 100644 index 0000000..ceae58f --- /dev/null +++ b/src/org/atriasoft/ege/engines/EnginePhysicsPerso.java @@ -0,0 +1,152 @@ +package org.atriasoft.ege.engines; + +import java.util.Vector; + +import org.atriasoft.gale.resource.ResourceColored3DObject; +import org.atriasoft.ege.internal.Log; +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.phyligram.PhysicCollisionAABB; + +public class EnginePhysicsPerso extends Engine { + public static final String ENGINE_NAME = "physicsPerso"; + private float accumulator = 0; + private static final float TIME_STEP = 0.005f; + private EngineGravity gravity; + protected EnginePhysicsPerso engine; + private Vector components = 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..."); + } + } + + @Override + public void componentRemove(Component ref) { + components.remove(ref); + } + + @Override + public void componentAdd(Component ref) { + if (ref instanceof ComponentPhysicsPerso == false) { + return; + } + components.add((ComponentPhysicsPerso)ref); + } + + @Override + public void update(long deltaMili) { + // Add the time difference in the accumulator + accumulator += (float)deltaMili*0.0001f; + // While there is enough accumulated time to take one or several physics steps + while (accumulator >= TIME_STEP) { + Log.info("update physic ... " + accumulator); + //applyForces(TIME_STEP); + updateAABB(TIME_STEP); + updateCollisionsAABB(TIME_STEP); + updateCollisionsNarrowPhase(TIME_STEP); + generateResultCollisionsForces(TIME_STEP); + // Decrease the accumulated time + accumulator -= TIME_STEP; + } + + } + + private void applyForces(float timeStep) { + for (ComponentPhysicsPerso it: components) { + it.applyForces(TIME_STEP, gravity); + } + } + /** + * Collision detection STEP 1: Upadte the AABB positioning of each elements + * @param timeStep Delta time since the last check + */ + private void updateAABB(float timeStep) { + for (ComponentPhysicsPerso it: components) { + it.updateAABB(); + } + } + /** + * Collision Detection STEP 2: update the list of each element that collide together in the AABB Boxs (update is done between each boxes) + * @param timeStep Delta time since the last check + */ + private void updateCollisionsAABB(float timeStep) { + // clear all object intersection + for (ComponentPhysicsPerso it: components) { + it.clearAABBIntersection(); + } + // update the current object intersection... + for (int iii=0; iii< components.size(); iii++) { + ComponentPhysicsPerso current = components.get(iii); + PhysicCollisionAABB currentAABB = current.getAABB(); + for (int jjj=iii+1; jjj< components.size(); jjj++) { + ComponentPhysicsPerso remote = components.get(jjj); + if (currentAABB.intersect(components.get(jjj).getAABB()) == true) { + current.addIntersection(remote); + remote.addIntersection(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: components) { + it.updateForNarrowCollision(); + } + // check for every component if the narrow collision is available. + for (int iii=0; iii< components.size(); iii++) { + ComponentPhysicsPerso current = components.get(iii); + boolean collide = current.checkNarrowCollision(); + + } + // update the force of collision available. + for (int iii=0; iii< components.size(); iii++) { + ComponentPhysicsPerso current = components.get(iii); + current.narrowCollisionCreateContactAndForce(); + } + } + /** + * Collision Detection STEP 4: apply all calculated forces (with containts) + * @param timeStep + */ + private void generateResultCollisionsForces(float timeStep) { + + } + + @Override + public void render(long deltaMili, Camera camera) { + // TODO Auto-generated method stub + for (ComponentPhysicsPerso it: this.components) { + //Log.info("Render " + it); + it.renderDebug(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 + + } + + @Override + public String getType() { + // TODO Auto-generated method stub + return ENGINE_NAME; + } + +} diff --git a/src/org/atriasoft/ege/physics/shape/Shape.java b/src/org/atriasoft/ege/physics/shape/Shape.java index a7e2cf0..6f33506 100644 --- a/src/org/atriasoft/ege/physics/shape/Shape.java +++ b/src/org/atriasoft/ege/physics/shape/Shape.java @@ -5,6 +5,7 @@ */ package org.atriasoft.ege.physics.shape; +import org.atriasoft.ege.internal.Log; import org.atriasoft.etk.math.Quaternion; import org.atriasoft.etk.math.Vector3f; @@ -58,6 +59,7 @@ public class Shape { }; public boolean parse(final String _line) { + Log.error("dfgdfg"); /* if(strncmp(_line, "origin:", 7) == 0) { sscanf(&_line[7], "%f %f %f", &m_origin.m_floats[0], &m_origin.m_floats[1], &m_origin.m_floats[2] ); diff --git a/src/org/atriasoft/phyligram/ColisionPoints.java b/src/org/atriasoft/phyligram/ColisionPoints.java new file mode 100644 index 0000000..7c97d06 --- /dev/null +++ b/src/org/atriasoft/phyligram/ColisionPoints.java @@ -0,0 +1,13 @@ +package org.atriasoft.phyligram; + +import org.atriasoft.etk.math.Vector3f; + +public class ColisionPoints { + public Vector3f position; + public Vector3f force; + + public ColisionPoints(Vector3f position, Vector3f force) { + this.position = position; + this.force = force; + } +} diff --git a/src/org/atriasoft/phyligram/Collision.java b/src/org/atriasoft/phyligram/Collision.java new file mode 100644 index 0000000..6248da5 --- /dev/null +++ b/src/org/atriasoft/phyligram/Collision.java @@ -0,0 +1,17 @@ +package org.atriasoft.phyligram; + +public class Collision { + public final ColisionPoints[] colisionPointLocal; + public final PhysicShape shapeRemote; + public final ColisionPoints[] colisionPointRemote; + public final boolean staticRemote; + public Collision(ColisionPoints[] colisionPointLocal, PhysicShape shapeRemote, + ColisionPoints[] colisionPointRemote, boolean staticRemote) { + super(); + this.colisionPointLocal = colisionPointLocal; + this.shapeRemote = shapeRemote; + this.colisionPointRemote = colisionPointRemote; + this.staticRemote = staticRemote; + } + +} diff --git a/src/org/atriasoft/phyligram/DebugDisplay.java b/src/org/atriasoft/phyligram/DebugDisplay.java new file mode 100644 index 0000000..abda111 --- /dev/null +++ b/src/org/atriasoft/phyligram/DebugDisplay.java @@ -0,0 +1,327 @@ +package org.atriasoft.phyligram; + +import java.util.ArrayList; +import java.util.List; + +import org.atriasoft.etk.Color; +import org.atriasoft.etk.math.Matrix4f; +import org.atriasoft.etk.math.Quaternion; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.gale.backend3d.OpenGL; +import org.atriasoft.gale.context.GaleContext; +import org.atriasoft.gale.resource.ResourceColored3DObject; + +public class DebugDisplay { +// public static ComponentPosition relativeTestPos; +// public static PhysicBox boxTest; + public static List testPoints = new ArrayList(); + public static List testPointsBox = new ArrayList(); + public static List testPointsCollide = new ArrayList(); + public static Vector3f testRpos; + public static Quaternion testQTransfert; + public static Vector3f box1HalfSize; + public static Vector3f box2HalfSize; + private ResourceColored3DObject debugDrawProperty; + public DebugDisplay(){ + + } + /* + @Override + public void onCreate(Context context) { + // set the system global max speed + ComponentPhysics.globalMaxSpeed = 3; + Gale.getContext().grabPointerEvents(true, new Vector2f(0,0)); + env = new Environement(); + this.canDraw = true; + setSize(new Vector2f(1500, 1500)); + setTitle("Loxel sample"); + map = new MapVoxel(this.env); +// this.env.addEngine(map); +// map.init(); + + // simple sun to have a global light ... + Entity globalGravity = new Entity(this.env); + globalGravity.addComponent(new ComponentGravityStatic(new Vector3f(0,0,-1))); + env.addEntity(globalGravity); + + // simple sun to have a global light ... + Entity sun = new Entity(this.env); + sun.addComponent(new ComponentPosition(new Transform3D(new Vector3f(1000,1000,1000)))); + sun.addComponent(new ComponentLightSun(new Light(new Vector3f(0.4f,0.4f,0.4f), new Vector3f(0,0,0), new Vector3f(0.8f,0,0)))); + env.addEntity(sun); + + // add a cube to show where in the light ... + Entity localLight = new Entity(this.env); + 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 ... + Entity localBox = new Entity(this.env); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-2,-2,14)))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + 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); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(1,1,1)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } + { + // add a cube to test collision ... + Entity localBox = new Entity(this.env); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0,4,12.5f)))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + 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); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(1,1,1)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } + { + // add a cube to test collision ... + Entity localBox = new Entity(this.env); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-2,2,14.5f)))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + localBox.addComponent(new ComponentRenderTexturedStaticMesh( + new Uri("DATA", "basic.vert"), + new Uri("DATA", "basic.frag"))); + ComponentPhysics physics2 = new ComponentPhysics(true); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(1,1,1)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } + + { + // add a cube to test collision ... + Entity localBox = new Entity(this.env); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(-5,-5,14)))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + localBox.addComponent(new ComponentRenderTexturedStaticMesh( + new Uri("DATA", "basic.vert"), + new Uri("DATA", "basic.frag"))); + ComponentPhysics physics2 = new ComponentPhysics(true); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(4,4,4)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } + { + // add a cube to test collision ... + Entity localBox = new Entity(this.env); + Quaternion transform = new Quaternion(0.5f,0.2f,0.4f,1); + transform.normalize(); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(15,15,14), transform))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + localBox.addComponent(new ComponentRenderTexturedStaticMesh( + new Uri("DATA", "basic.vert"), + new Uri("DATA", "basic.frag"))); + ComponentPhysics physics2 = new ComponentPhysics(true); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(8,8,8)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } + { + // add a cube to test collision ... + Entity localBox = new Entity(this.env); + Quaternion transform = new Quaternion(0.3f,0.3f,0.4f,1); + transform.normalize(); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(2,-2,14.2f),transform))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + localBox.addComponent(new ComponentRenderTexturedStaticMesh( + new Uri("DATA", "basic.vert"), + new Uri("DATA", "basic.frag"))); + ComponentPhysics physics2 = new ComponentPhysics(true); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(1,1,1)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } + { + // add a cube to test collision ... + Entity localBox = new Entity(this.env); + Quaternion transform = new Quaternion(0,0,1,1); + transform.normalize(); + localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(2,2,14.2f),transform))); + localBox.addComponent(new ComponentStaticMesh(new Uri("RES", "cube-one.obj"))); + localBox.addComponent(new ComponentTexture(new Uri("DATA", "blocks/clay.png"))); + localBox.addComponent(new ComponentRenderTexturedStaticMesh( + new Uri("DATA", "basic.vert"), + new Uri("DATA", "basic.frag"))); + ComponentPhysics physics2 = new ComponentPhysics(true); + PhysicBox box2 = new PhysicBox(); + box2.setSize(new Vector3f(1,1,1)); + box2.setOrigin(new Vector3f(0,0,0)); + box2.setMass(1); + physics2.addShape(box2); + localBox.addComponent(physics2); + env.addEntity(localBox); + } +// { +// // add a cube to test collision ... +// Entity localBox = new Entity(this.env); +// 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"))); +//// 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 PhysicBox(); +// 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"))); +// localBox.addComponent(new ComponentRenderTexturedStaticMesh( +// new Uri("DATA", "basic.vert"), +// new Uri("DATA", "basic.frag"))); +// env.addEntity(localBox); +// } + + Entity gird = new Entity(this.env); + gird.addComponent(new ComponentPosition(new Transform3D(new Vector3f(0,0,13)))); + gird.addComponent(new ComponentStaticMesh(MeshGenerator.createGrid(5))); + gird.addComponent(new ComponentRenderColoredStaticMesh( + new Uri("DATA_EGE", "wireColor.vert"), + new Uri("DATA_EGE", "wireColor.frag"))); + env.addEntity(gird); + + Entity player = new Entity(this.env); + objectPosition = new ComponentPositionPlayer(new Transform3D(new Vector3f(5,5,13))); + player.addComponent(objectPosition); + objectPlayer = new ComponentPlayer(); + player.addComponent(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"), + new Uri("DATA", "basicMaterial.frag"), + (EngineLight)env.getEngine(EngineLight.ENGINE_NAME))); + ComponentPhysics physics = new ComponentPhysics(true); + PhysicBox box = new PhysicBox(); + box.setSize(new Vector3f(0.6f,0.6f,1.8f)); + box.setOrigin(new Vector3f(0,0,0.9f)); + box.setMass(1); + physics.addShape(box); + player.addComponent(physics); + env.addEntity(player); + + + Camera mainView = new Camera(); + env.addCamera("default", mainView); + mainView.setPitch((float)Math.PI*-0.25f); + mainView.setPosition(new Vector3f(0,-5,5)); + + this.simpleControl = new ControlCameraPlayer(mainView, player); + env.addControlInterface(simpleControl); + + // start the engine. + env.setPropertyStatus(GameStatus.gameStart); + + basicRotation.setEulerAngles(new Vector3f(0.005f,0.005f,0.01f)); + basicRotation2.setEulerAngles(new Vector3f(0.003f,0.01f,0.001f)); + // ready to let Gale & Ege manage the display + Log.info("==> Init APPL (END)"); + creationDone = true; + } + */ + + public void onDraw(GaleContext context) { + if (this.debugDrawProperty == null) { + debugDrawProperty = ResourceColored3DObject.create(); + } + // now render the point test collision ... + for (int iii=0; iii tmp = new ArrayList<>(); + tmp.add(new Vector3f(0,0,0)); + tmp.add(force); + debugDrawProperty.drawLine(tmp, new Color(1, 0, 0, 1), Matrix4f.createMatrixTranslate(subPosition), true, false); + } + + @Override + public void renderDebug(Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) { + debugDrawProperty.drawSquare(this.size.multiply(0.5f), this.transform.getOpenGLMatrix().multiply(transformGlobal.getOpenGLMatrix()), new Color(0, 1, 0, 0.25f)); + Vector3f dimention = this.size.multiply(0.5f); + renderPoint2(new Vector3f(+dimention.x(), +dimention.y(), +dimention.z()), transformGlobal, debugDrawProperty); + renderPoint(new Vector3f(-dimention.x(), +dimention.y(), +dimention.z()), transformGlobal, debugDrawProperty); + renderPoint(new Vector3f(+dimention.x(), -dimention.y(), +dimention.z()), transformGlobal, debugDrawProperty); + renderPoint(new Vector3f(-dimention.x(), -dimention.y(), +dimention.z()), transformGlobal, debugDrawProperty); + renderPoint(new Vector3f(+dimention.x(), +dimention.y(), -dimention.z()), transformGlobal, debugDrawProperty); + renderPoint(new Vector3f(-dimention.x(), +dimention.y(), -dimention.z()), transformGlobal, debugDrawProperty); + renderPoint(new Vector3f(+dimention.x(), -dimention.y(), -dimention.z()), transformGlobal, debugDrawProperty); + renderPoint3(new Vector3f(-dimention.x(), -dimention.y(), -dimention.z()), transformGlobal, debugDrawProperty); + for (Collision elem: this.colisionPoints) { + if (elem != null) { + if (elem.colisionPointLocal == null) { + Log.error("colision point must be set !!!"); + continue; + } + for (int iii = 0; iii < elem.colisionPointLocal.length; iii++) { + renderPoint4(elem.colisionPointLocal[iii].position, elem.colisionPointLocal[iii].force, debugDrawProperty); + } + } + } + } + +} diff --git a/src/org/atriasoft/phyligram/PhysicCollisionAABB.java b/src/org/atriasoft/phyligram/PhysicCollisionAABB.java new file mode 100644 index 0000000..1348025 --- /dev/null +++ b/src/org/atriasoft/phyligram/PhysicCollisionAABB.java @@ -0,0 +1,77 @@ +package org.atriasoft.phyligram; + +import org.atriasoft.etk.math.Vector3f; + +public class PhysicCollisionAABB { + public float minX; + public float minY; + public float minZ; + public float maxX; + public float maxY; + public float maxZ; + public PhysicCollisionAABB(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) { + super(); + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + } + public boolean intersect(PhysicCollisionAABB other) { + if (this == other) { + return false; + } + if (minX > other.maxX) { + return false; + } + if (maxX < other.minX) { + return false; + } + if (minY > other.maxY) { + return false; + } + if (maxY < other.minY) { + return false; + } + if (minZ > other.maxZ) { + return false; + } + if (maxZ < other.minZ) { + return false; + } + return true; + } + public void update(Vector3f point) { + if (minX > point.x()) { + minX = point.x(); + } + if (maxX < point.x()) { + maxX = point.x(); + } + if (minY > point.y()) { + minY = point.y(); + } + if (maxY < point.y()) { + maxY = point.y(); + } + if (minZ > point.z()) { + minZ = point.z(); + } + if (maxZ < point.z()) { + maxZ = point.z(); + } + } + public Vector3f getMin() { + return new Vector3f(minX, minY, minZ); + } + public Vector3f getMax() { + return new Vector3f(maxX, maxY, maxZ); + } + public static PhysicCollisionAABB beforeCalculated() { + // TODO Auto-generated method stub + return new PhysicCollisionAABB(999999,999999,999999,-999999,-999999,-999999); + } +} + + diff --git a/src/org/atriasoft/phyligram/PhysicMapVoxel.java b/src/org/atriasoft/phyligram/PhysicMapVoxel.java new file mode 100644 index 0000000..ec96f57 --- /dev/null +++ b/src/org/atriasoft/phyligram/PhysicMapVoxel.java @@ -0,0 +1,42 @@ +package org.atriasoft.phyligram; + +import org.atriasoft.etk.math.Transform3D; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.gale.resource.ResourceColored3DObject; +import org.atriasoft.ege.map.VoxelChunk; + +public class PhysicMapVoxel extends PhysicShape { + // Box size property in X, Y and Z + private VoxelChunk chunk; + public PhysicMapVoxel(VoxelChunk chunk) { + super(PhysicShapeType.MAP_VOXEL); + this.chunk = chunk; + } + @Override + public void updateAABB(Transform3D transform, PhysicCollisionAABB aabb) { + if (this.chunk == null) { + return; + } + this.colisionPoints.clear(); + aabb.update(new Vector3f(this.chunk.getPosition().x(),this.chunk.getPosition().y(),this.chunk.getPosition().z())); + aabb.update(new Vector3f( + this.chunk.getPosition().x() + VoxelChunk.VOXEL_CHUNK_SIZE, + this.chunk.getPosition().y() + VoxelChunk.VOXEL_CHUNK_SIZE, + this.chunk.getPosition().z() + VoxelChunk.VOXEL_CHUNK_SIZE)); + } + // only needed for the narrow phase calculation ... + private Vector3f narrowPhaseGlobalPos; + private Vector3f narrowPhaseAxisX = new Vector3f(1,0,0); + private Vector3f narrowPhaseAxisY = new Vector3f(1,0,0); + private Vector3f narrowPhaseAxisZ = new Vector3f(1,0,0); + private Vector3f narrowPhaseHalfSize = new Vector3f(0.5f,0.5f,0.5f); + @Override + public void updateForNarrowCollision(Transform3D transform) { + this.narrowPhaseGlobalPos = transform.multiply(this.transform.multiply(new Vector3f(0,0,0))); + } + @Override + public void renderDebug(Transform3D transform, ResourceColored3DObject debugDrawProperty) { + + + } +} diff --git a/src/org/atriasoft/phyligram/PhysicShape.java b/src/org/atriasoft/phyligram/PhysicShape.java new file mode 100644 index 0000000..3c90611 --- /dev/null +++ b/src/org/atriasoft/phyligram/PhysicShape.java @@ -0,0 +1,101 @@ +package org.atriasoft.phyligram; + +import java.util.ArrayList; +import java.util.List; + +import org.atriasoft.etk.math.Quaternion; +import org.atriasoft.etk.math.Transform3D; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.gale.resource.ResourceColored3DObject; + + + + +public abstract class PhysicShape { + + + + protected List colisionPoints = new ArrayList<>(); + // protected Quaternion quaternion; + // protected Vector3f origin; + protected Transform3D transform; + protected Transform3D transformGlobal; + protected float mass = 0; + protected final PhysicShapeType type; + + public PhysicShape(PhysicShapeType type) { + this.type = type; + this.transform = Transform3D.IDENTITY; + // this.quaternion = Quaternion.identity(); + // this.origin = Vector3f.zero(); + this.mass = 0; + } + + public PhysicShape(PhysicShapeType type, Quaternion quaternion, Vector3f origin, float mass) { + this.type = type; + this.transform = new Transform3D(origin, quaternion); + // this.quaternion = quaternion; + // this.origin = origin; + this.mass = mass; + } + + public Quaternion getQuaternionFull() { + return transformGlobal.getOrientation().multiply(transform.getOrientation()); + } + + public Quaternion getQuaternion() { + return transform.getOrientation(); + } + + public void setQuaternion(Quaternion quaternion) { + this.transform = this.transform.withOrientation(quaternion); + } + + public Vector3f getOrigin() { + return this.transform.getPosition(); + } + + public void setOrigin(Vector3f origin) { + this.transform = this.transform.withPosition(origin); + } + + public Transform3D getTransform() { + return transform; + } + + public void setTransform(Transform3D transform) { + this.transform = transform; + } + + public Transform3D getTransformGlobal() { + return transformGlobal; + } + + public void setTransformGlobal(Transform3D transform) { + this.transformGlobal = transform; + } + + public float getMass() { + return mass; + } + + public void setMass(float mass) { + this.mass = mass; + } + + public PhysicShapeType getType() { + return type; + } + + public void addColision(Collision colision) { + colisionPoints.add(colision); + } + + + public abstract void updateAABB(Transform3D transform, PhysicCollisionAABB aabb); + + public abstract void updateForNarrowCollision(Transform3D transform); + + public abstract void renderDebug(Transform3D transform, ResourceColored3DObject debugDrawProperty); + +} diff --git a/src/org/atriasoft/phyligram/PhysicShapeType.java b/src/org/atriasoft/phyligram/PhysicShapeType.java new file mode 100644 index 0000000..8f162cd --- /dev/null +++ b/src/org/atriasoft/phyligram/PhysicShapeType.java @@ -0,0 +1,13 @@ +package org.atriasoft.phyligram; + +public enum PhysicShapeType { + UNKNOWN, + BOX, + CAPSULE, + CONE, + CONVEXHULL, + CYLINDER, + SPHERE, + CONCAVE, + MAP_VOXEL +} diff --git a/src/org/atriasoft/phyligram/PhysicSphere.java b/src/org/atriasoft/phyligram/PhysicSphere.java new file mode 100644 index 0000000..8a6b8af --- /dev/null +++ b/src/org/atriasoft/phyligram/PhysicSphere.java @@ -0,0 +1,38 @@ +package org.atriasoft.phyligram; + +import org.atriasoft.etk.Color; +import org.atriasoft.etk.math.Transform3D; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.gale.resource.ResourceColored3DObject; + +public class PhysicSphere extends PhysicShape { + // Box size property in X, Y and Z + private float size; + public PhysicSphere() { + super(PhysicShapeType.SPHERE); + } + public float getSize() { + return size; + } + public void setSize(float size) { + this.size = size; + } + @Override + public void updateAABB(Transform3D transform, PhysicCollisionAABB aabb) { + aabb.update(transform.multiply(this.transform.getPosition()).add(this.size,0,0)); + aabb.update(transform.multiply(this.transform.getPosition()).add(-this.size,0,0)); + aabb.update(transform.multiply(this.transform.getPosition()).add(0,this.size,0)); + aabb.update(transform.multiply(this.transform.getPosition()).add(0,-this.size,0)); + aabb.update(transform.multiply(this.transform.getPosition()).add(0,0,this.size)); + aabb.update(transform.multiply(this.transform.getPosition()).add(0,0,-this.size)); + } + @Override + public void updateForNarrowCollision(Transform3D transform) { + + } + @Override + public void renderDebug(Transform3D transform, ResourceColored3DObject debugDrawProperty) { + debugDrawProperty.drawSphere(this.size, 9, 9, this.transform.getOpenGLMatrix().multiply(transform.getOpenGLMatrix()), new Color(0,1,0,1)); + + } +} \ No newline at end of file diff --git a/src/org/atriasoft/phyligram/ToolCollisionOBBWithOBB.java b/src/org/atriasoft/phyligram/ToolCollisionOBBWithOBB.java new file mode 100644 index 0000000..e7286eb --- /dev/null +++ b/src/org/atriasoft/phyligram/ToolCollisionOBBWithOBB.java @@ -0,0 +1,378 @@ +package org.atriasoft.phyligram; + +import org.atriasoft.etk.math.Quaternion; +import org.atriasoft.etk.math.Vector3f; +import org.atriasoft.phyligram.internal.Log; + +// set the relevant elements of our oriented bounding box +class OBB { + public Vector3f position; + public Vector3f axisX; + 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; + } +}; + +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); + Vector3f rPos2 = box2.narrowPhaseGlobalPos.less(box1.narrowPhaseGlobalPos); + Quaternion quat1 = box1.getQuaternionFull(); + Quaternion quat2 = box2.getQuaternionFull(); + // Step 1: set the Box 2 in the repere of the Box 1: + 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); + // DebugDisplay.relativeTestPos.getTransform().setOrientation(quatTransfer); + // DebugDisplay.boxTest.setSize(box1.getSize()); + // Log.info("" + rPos + quatTransfer1); + // /*res = */getCollidePointsAABBCenteredWithOBB(box1.narrowPhaseHalfSize, box2.narrowPhaseHalfSize, quatTransfer, rPos); + /* res = transfert in generic plan the new res ... */ + // test origin AABB with OBB collision + // Step 2: set the Box 1 in the repere of the Box 2: + // test origin AABB with OBB collision + // tmp = rPos.addNew(new Vector3f(0,0,14)); + DebugDisplay.testRpos = quat2.inverse().getMatrix4().multiply(rPos1); + 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()); + // foinctionne avec la box qui n'est pas orienter... + // getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer2, rPos1); + // fonctionne quand le block est trourner de 90% petit pb de positionnement en hauteur.... + // getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer2, quat2.multiply(rPos2)); + ColisionPoints[] collide1 = getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer2, quat2.inverse().getMatrix4().multiply(rPos1)); + // transfer detection point collision in global environement: + if (collide1 != null) { + for (int iii = 0; iii < collide1.length; iii++) { + collide1[iii].position = quat1.multiply(collide1[iii].position).add(box1.narrowPhaseGlobalPos); + collide1[iii].force = quat2.multiply(collide1[iii].force);//.add(box1.narrowPhaseGlobalPos); + } + } + /* res = trensfert in generic plan the new res ... */ + + DebugDisplay.testRpos = quat1.inverse().getMatrix4().multiply(rPos2); + DebugDisplay.testQTransfert = quatTransfer1; + DebugDisplay.box1HalfSize = box1.narrowPhaseHalfSize; + DebugDisplay.box2HalfSize = box2.narrowPhaseHalfSize; + ColisionPoints[] collide2 = getCollidePointsAABBCenteredWithOBB(box1.narrowPhaseHalfSize, box2.narrowPhaseHalfSize, quatTransfer1, quat1.inverse().getMatrix4().multiply(rPos2)); + if (collide2 != null) { + for (int iii = 0; iii < collide2.length; iii++) { + collide2[iii].position = quat2.multiply(collide2[iii].position).add(box2.narrowPhaseGlobalPos); + collide2[iii].force = quat1.multiply(collide2[iii].force);//.add(box2.narrowPhaseGlobalPos); + } + } + // add only if NOT static, when static no colision is performed + if (true) { //!isStatic1) { + Collision colision = new Collision(collide1, box2, collide2, isStatic2); + box1.addColision(colision); + } + if (true) { //!isStatic1) { + Collision colision = new Collision(collide2, box1, collide1, isStatic1); + box2.addColision(colision); + } + + } + + public static ColisionPoints[] 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); + Vector3f topFrontRight = box2Orientation.multiply(new Vector3f(+box2HalfSize.x(), -box2HalfSize.y(), +box2HalfSize.z())).add(box2Position); + Vector3f topFrontLeft = box2Orientation.multiply(new Vector3f(-box2HalfSize.x(), -box2HalfSize.y(), +box2HalfSize.z())).add(box2Position); + Vector3f bottomBackRight = box2Orientation.multiply(new Vector3f(+box2HalfSize.x(), +box2HalfSize.y(), -box2HalfSize.z())).add(box2Position); + Vector3f bottomBackLeft = box2Orientation.multiply(new Vector3f(-box2HalfSize.x(), +box2HalfSize.y(), -box2HalfSize.z())).add(box2Position); + Vector3f bottomFrontRight = box2Orientation.multiply(new Vector3f(+box2HalfSize.x(), -box2HalfSize.y(), -box2HalfSize.z())).add(box2Position); + Vector3f bottomFrontLeft = box2Orientation.multiply(new Vector3f(-box2HalfSize.x(), -box2HalfSize.y(), -box2HalfSize.z())).add(box2Position); + DebugDisplay.testPoints.clear(); + DebugDisplay.testPoints.add(topBackRight); + DebugDisplay.testPoints.add(topBackLeft); + DebugDisplay.testPoints.add(topFrontRight); + DebugDisplay.testPoints.add(topFrontLeft); + DebugDisplay.testPoints.add(bottomBackRight); + DebugDisplay.testPoints.add(bottomBackLeft); + DebugDisplay.testPoints.add(bottomFrontRight); + DebugDisplay.testPoints.add(bottomFrontLeft); + DebugDisplay.testPointsBox.clear(); + DebugDisplay.testPointsBox.add(new Vector3f(+box1HalfSize.x(), +box1HalfSize.y(), +box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(-box1HalfSize.x(), +box1HalfSize.y(), +box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(+box1HalfSize.x(), -box1HalfSize.y(), +box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(-box1HalfSize.x(), -box1HalfSize.y(), +box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(+box1HalfSize.x(), +box1HalfSize.y(), -box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(-box1HalfSize.x(), +box1HalfSize.y(), -box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(+box1HalfSize.x(), -box1HalfSize.y(), -box1HalfSize.z())); + DebugDisplay.testPointsBox.add(new Vector3f(-box1HalfSize.x(), -box1HalfSize.y(), -box1HalfSize.z())); + Vector3f insideTopBackRight = pointDistanceInAABB(box1HalfSize, topBackRight); + Vector3f insideTopBackLeft = pointDistanceInAABB(box1HalfSize, topBackLeft); + Vector3f insideTopFrontRight = pointDistanceInAABB(box1HalfSize, topFrontRight); + Vector3f insideTopFrontLeft = pointDistanceInAABB(box1HalfSize, topFrontLeft); + Vector3f insideBottomBackRight = pointDistanceInAABB(box1HalfSize, bottomBackRight); + Vector3f insideBottomBackLeft = pointDistanceInAABB(box1HalfSize, bottomBackLeft); + Vector3f insideBottomFrontRight = pointDistanceInAABB(box1HalfSize, bottomFrontRight); + Vector3f insideBottomFrontLeft = pointDistanceInAABB(box1HalfSize, bottomFrontLeft); + DebugDisplay.testPointsCollide.clear(); + DebugDisplay.testPointsCollide.add(insideTopBackRight == null ? false : true); + DebugDisplay.testPointsCollide.add(insideTopBackLeft == null ? false : true); + DebugDisplay.testPointsCollide.add(insideTopFrontRight == null ? false : true); + DebugDisplay.testPointsCollide.add(insideTopFrontLeft == null ? false : true); + DebugDisplay.testPointsCollide.add(insideBottomBackRight == null ? false : true); + DebugDisplay.testPointsCollide.add(insideBottomBackLeft == null ? false : true); + DebugDisplay.testPointsCollide.add(insideBottomFrontRight == null ? false : true); + DebugDisplay.testPointsCollide.add(insideBottomFrontLeft == null ? false : true); + int count = 0; + if (insideTopBackRight != null) { + count++; + } + if (insideTopBackLeft != null) { + count++; + } + if (insideTopFrontRight != null) { + count++; + } + if (insideTopFrontLeft != null) { + count++; + } + if (insideBottomBackRight != null) { + count++; + } + if (insideBottomBackLeft != null) { + count++; + } + if (insideBottomFrontRight != null) { + count++; + } + if (insideBottomFrontLeft != null) { + count++; + } + ColisionPoints[] out = new ColisionPoints[count]; + count = 0; + if (insideTopBackRight != null) { + out[count] = new ColisionPoints(new Vector3f(+box2HalfSize.x(), +box2HalfSize.y(), +box2HalfSize.z()), insideTopBackRight); + count++; + } + if (insideTopBackLeft != null) { + out[count] = new ColisionPoints(new Vector3f(-box2HalfSize.x(), +box2HalfSize.y(), +box2HalfSize.z()), insideTopBackLeft); + count++; + } + if (insideTopFrontRight != null) { + out[count] = new ColisionPoints(new Vector3f(+box2HalfSize.x(), -box2HalfSize.y(), +box2HalfSize.z()), insideTopFrontRight); + count++; + } + if (insideTopFrontLeft != null) { + out[count] = new ColisionPoints(new Vector3f(-box2HalfSize.x(), -box2HalfSize.y(), +box2HalfSize.z()), insideTopFrontLeft); + count++; + } + if (insideBottomBackRight != null) { + out[count] = new ColisionPoints(new Vector3f(+box2HalfSize.x(), +box2HalfSize.y(), -box2HalfSize.z()), insideBottomBackRight); + count++; + } + if (insideBottomBackLeft != null) { + out[count] = new ColisionPoints(new Vector3f(-box2HalfSize.x(), +box2HalfSize.y(), -box2HalfSize.z()), insideBottomBackLeft); + count++; + } + if (insideBottomFrontRight != null) { + out[count] = new ColisionPoints(new Vector3f(+box2HalfSize.x(), -box2HalfSize.y(), -box2HalfSize.z()), insideBottomFrontRight); + count++; + } + if (insideBottomFrontLeft != null) { + out[count] = new ColisionPoints(new Vector3f(-box2HalfSize.x(), -box2HalfSize.y(), -box2HalfSize.z()), insideBottomFrontLeft); + count++; + } + if (count != 0) { + // Find a point inside the BOX ... + /* + Log.info("Detect point inside ... " + insideTopBackRight + " " + insideTopBackLeft + " " + insideTopFrontRight + " " + insideTopFrontLeft + " " + insideBottomBackRight + " " + + insideBottomBackLeft + " " + insideBottomFrontRight + " " + insideBottomFrontLeft); + */ + return out; + } + // line in AABB + // 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; + } + + public static Vector3f pointDistanceInAABB(Vector3f halfSize, Vector3f point) { + float outX = 0; + float outY = 0; + float outZ = 0; + if (point.x() < 0) { + if (point.x() > -halfSize.x()) { + + outX = -(halfSize.x() + point.x()); + + //out.x = -halfSize.x - point.x; + //out.x = -halfSize.x + point.x; + //out.x = + point.x; + } else { + return null; + } + } else { + if (point.x() < halfSize.x()) { + //out.x = halfSize.x + point.x; + outX = halfSize.x() - point.x(); + //out.x = - point.x; + } else { + return null; + } + } + if (point.y() < 0) { + if (point.y() > -halfSize.y()) { + outY = -halfSize.y() - point.y(); + //out.y = -halfSize.y + point.y; + //out.y = point.y; + } else { + return null; + } + } else { + if (point.y() < halfSize.y()) { + //out.y = halfSize.y + point.y; + outY = halfSize.y() - point.y(); + //out.y = - point.y; + } else { + return null; + } + } + if (point.z() < 0) { + if (point.z() > -halfSize.z()) { + outZ = -halfSize.z() - point.z(); + //out.z = -halfSize.z + point.z; + //out.z = + point.z; + } else { + return null; + } + } else { + if (point.z() < halfSize.z()) { + //out.z = halfSize.z + point.z; + outZ = halfSize.z() - point.z(); + //out.z = - point.z; + } else { + return null; + } + } + if (Math.abs(outX) < Math.abs(outY)) { + outY = 0; + if (Math.abs(outX) < Math.abs(outZ)) { + outZ = 0; + return new Vector3f(outX, outY, outZ); + } + outX = 0; + return new Vector3f(outX, outY, outZ); + } + outX = 0; + if (Math.abs(outY) < Math.abs(outZ)) { + outZ = 0; + return new Vector3f(outX, outY, outZ); + } + outY = 0; + return new Vector3f(outX, outY, outZ); + } +} diff --git a/src/org/atriasoft/phyligram/internal/Log.java b/src/org/atriasoft/phyligram/internal/Log.java new file mode 100644 index 0000000..43eda0c --- /dev/null +++ b/src/org/atriasoft/phyligram/internal/Log.java @@ -0,0 +1,68 @@ +package org.atriasoft.phyligram.internal; + +import io.scenarium.logger.LogLevel; +import io.scenarium.logger.Logger; + +public class Log { + private static final String LIB_NAME = "ege"; + private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); + private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); + private static final boolean PRINT_ERROR = Logger.getNeedPrint(LIB_NAME, LogLevel.ERROR); + private static final boolean PRINT_WARNING = Logger.getNeedPrint(LIB_NAME, LogLevel.WARNING); + private static final boolean PRINT_INFO = Logger.getNeedPrint(LIB_NAME, LogLevel.INFO); + private static final boolean PRINT_DEBUG = Logger.getNeedPrint(LIB_NAME, LogLevel.DEBUG); + private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); + private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); + private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); + + public static void critical(final String data) { + if (PRINT_CRITICAL) { + Logger.critical(LIB_NAME_DRAW, data); + } + } + + public static void debug(final String data) { + if (PRINT_DEBUG) { + Logger.debug(LIB_NAME_DRAW, data); + } + } + + public static void error(final String data) { + if (PRINT_ERROR) { + Logger.error(LIB_NAME_DRAW, data); + } + } + + public static void info(final String data) { + if (PRINT_INFO) { + Logger.info(LIB_NAME_DRAW, data); + } + } + + public static void print(final String data) { + if (PRINT_PRINT) { + Logger.print(LIB_NAME_DRAW, data); + } + } + + public static void todo(final String data) { + if (PRINT_TODO) { + Logger.todo(LIB_NAME_DRAW, data); + } + } + + public static void verbose(final String data) { + if (PRINT_VERBOSE) { + Logger.verbose(LIB_NAME_DRAW, data); + } + } + + public static void warning(final String data) { + if (PRINT_WARNING) { + Logger.warning(LIB_NAME_DRAW, data); + } + } + + private Log() {} + +}