From bb9c65bb3eee9e13be790e11ebd8f7ed6da894f7 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Wed, 1 Jul 2020 00:52:30 +0200 Subject: [PATCH] [DEV] collision work well ==> need update but it start to be lovely --- src/org/atriaSoft/etk/math/Quaternion.java | 36 ++++++++++++ src/org/atriaSoft/etk/math/Vector3f.java | 5 +- .../resource/ResourceColored3DObject.java | 2 +- .../gale/resource/ResourceProgram.java | 2 +- .../gameEngine/physics/PhysicBox.java | 28 +++++++++ .../physics/ToolCollisionOBBWithOBB.java | 57 ++++++++++++++---- .../sample/LoxelEngine/LoxelApplication.java | 58 ++++++++++++++++--- 7 files changed, 163 insertions(+), 25 deletions(-) diff --git a/src/org/atriaSoft/etk/math/Quaternion.java b/src/org/atriaSoft/etk/math/Quaternion.java index 13b6cc6..0de1c26 100644 --- a/src/org/atriaSoft/etk/math/Quaternion.java +++ b/src/org/atriaSoft/etk/math/Quaternion.java @@ -595,6 +595,42 @@ public class Quaternion { yzs + wxs, 1.0f - xxs - yys); } + public Matrix4f getMatrix4() { + + float nQ = this.x*this.x + + this.y*this.y + + this.z*this.z + + this.w*this.w; + float sss = 0.0f; + if (nQ > 0.0f) { + sss = 2.0f / nQ; + } + float xs = this.x*sss; + float ys = this.y*sss; + float zs = this.z*sss; + float wxs = this.w*xs; + float wys = this.w*ys; + float wzs = this.w*zs; + float xxs = this.x*xs; + float xys = this.x*ys; + float xzs = this.x*zs; + float yys = this.y*ys; + float yzs = this.y*zs; + float zzs = this.z*zs; + return new Matrix4f(1.0f - yys - zzs, + xys - wzs, + xzs + wys, + 0, + xys + wzs, + 1.0f - xxs - zzs, + yzs - wxs, + 0, + xzs - wys, + yzs + wxs, + 1.0f - xxs - yys, + 0, + 0,0,0,1); + } /** * @brief Compute the spherical linear interpolation between two quaternions. * @param[in] obj1 First quaternion diff --git a/src/org/atriaSoft/etk/math/Vector3f.java b/src/org/atriaSoft/etk/math/Vector3f.java index f8852dc..c70580c 100644 --- a/src/org/atriaSoft/etk/math/Vector3f.java +++ b/src/org/atriaSoft/etk/math/Vector3f.java @@ -337,10 +337,7 @@ public class Vector3f { * @param obj The other vector */ public Vector3f multiply_new(Vector3f obj) { - this.x *= obj.x; - this.y *= obj.y; - this.z *= obj.z; - return this; + return new Vector3f(this.x * obj.x, this.y * obj.y, this.z * obj.z); } /** * @brief Set the x value diff --git a/src/org/atriaSoft/gale/resource/ResourceColored3DObject.java b/src/org/atriaSoft/gale/resource/ResourceColored3DObject.java index c5e952e..324613f 100644 --- a/src/org/atriaSoft/gale/resource/ResourceColored3DObject.java +++ b/src/org/atriaSoft/gale/resource/ResourceColored3DObject.java @@ -131,7 +131,7 @@ public class ResourceColored3DObject extends Resource { FloatBuffer buffer = storeDataInFloatBuffer(convertInFloat(vertices)); this.program.sendAttribute(this.GLPosition, 3, buffer, 3); // color : - Log.info("color= " + color + " " + this.GLPosition); + //Log.info("color= " + color + " " + this.GLPosition); this.program.uniformColor(this.GLColor, color); if (color.a < 1.0f) { OpenGL.enable(OpenGL.Flag.flag_blend); diff --git a/src/org/atriaSoft/gale/resource/ResourceProgram.java b/src/org/atriaSoft/gale/resource/ResourceProgram.java index 32f2088..f619180 100644 --- a/src/org/atriaSoft/gale/resource/ResourceProgram.java +++ b/src/org/atriaSoft/gale/resource/ResourceProgram.java @@ -296,7 +296,7 @@ public class ResourceProgram extends Resource { return; } //GL40.glBindVertexArray(this.elementList.get(idElem).elementId); - Log.error("[" + this.elementList.get(idElem).name + "] send " + 3 + " element"); + //Log.error("[" + this.elementList.get(idElem).name + "] send " + 3 + " element"); GL40.glVertexAttribPointer( this.elementList.get(idElem).elementId, nbElement, diff --git a/src/org/atriaSoft/gameEngine/physics/PhysicBox.java b/src/org/atriaSoft/gameEngine/physics/PhysicBox.java index 9e9e1a7..f9a5fc3 100644 --- a/src/org/atriaSoft/gameEngine/physics/PhysicBox.java +++ b/src/org/atriaSoft/gameEngine/physics/PhysicBox.java @@ -1,9 +1,12 @@ package org.atriaSoft.gameEngine.physics; import org.atriaSoft.etk.Color; +import org.atriaSoft.etk.math.Matrix4f; +import org.atriaSoft.etk.math.Quaternion; import org.atriaSoft.etk.math.Transform3D; import org.atriaSoft.etk.math.Vector3f; import org.atriaSoft.gale.resource.ResourceColored3DObject; +import org.atriaSoft.gameEngine.sample.LoxelEngine.LoxelApplication; public class PhysicBox extends PhysicShape { // Box size property in X, Y and Z @@ -45,8 +48,33 @@ public class PhysicBox extends PhysicShape { this.narrowPhaseAxisZ = transformGlobal.multiply(this.transform.multiply(new Vector3f(0,0,1))).less(this.narrowPhaseGlobalPos); this.narrowPhaseHalfSize = this.size.multiply_new(0.5f); } + + private void renderPoint(Vector3f subPosition, Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) { + Matrix4f transformation = transformGlobal.getOpenGLMatrix().multiply_new(this.transform.getOpenGLMatrix()).multiply(Matrix4f.createMatrixTranslate(subPosition)); + + debugDrawProperty.drawSquare(new Vector3f(0.1f,0.1f,0.1f), transformation, new Color(0,0,1,1)); + } + private void renderPoint2(Vector3f subPosition, Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) { + Matrix4f transformation = transformGlobal.getOpenGLMatrix().multiply_new(this.transform.getOpenGLMatrix()).multiply(Matrix4f.createMatrixTranslate(subPosition)); + debugDrawProperty.drawSquare(new Vector3f(0.05f,0.05f,0.05f), transformation, new Color(0,1,0,1)); + + } + private void renderPoint3(Vector3f subPosition, Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) { + Matrix4f transformation = transformGlobal.getOpenGLMatrix().multiply_new(this.transform.getOpenGLMatrix()).multiply(Matrix4f.createMatrixTranslate(subPosition)); + debugDrawProperty.drawSquare(new Vector3f(0.05f,0.05f,0.05f), transformation, new Color(1,1,0,1)); + + } @Override public void renderDebug(Transform3D transformGlobal, ResourceColored3DObject debugDrawProperty) { debugDrawProperty.drawSquare(this.size.multiply_new(0.5f), this.transform.getOpenGLMatrix().multiply_new(transformGlobal.getOpenGLMatrix()), new Color(0,1,0,0.25f)); + Vector3f dimention = this.size.multiply_new(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); } } diff --git a/src/org/atriaSoft/gameEngine/physics/ToolCollisionOBBWithOBB.java b/src/org/atriaSoft/gameEngine/physics/ToolCollisionOBBWithOBB.java index a4d4239..bd6dfe1 100644 --- a/src/org/atriaSoft/gameEngine/physics/ToolCollisionOBBWithOBB.java +++ b/src/org/atriaSoft/gameEngine/physics/ToolCollisionOBBWithOBB.java @@ -1,5 +1,6 @@ package org.atriaSoft.gameEngine.physics; +import org.atriaSoft.etk.math.Matrix4f; import org.atriaSoft.etk.math.Quaternion; import org.atriaSoft.etk.math.Vector3f; import org.atriaSoft.gale.test.sample2.Log; @@ -58,7 +59,7 @@ public class ToolCollisionOBBWithOBB { public static void main(String[] args) { // create two obbs OBB A = new OBB(); - OBB B = new OBB();; + OBB B = new OBB(); // set the first obb's properties A.Pos = new Vector3f(0.0f, 0.0f, 0.0f); // set its center position @@ -127,12 +128,13 @@ public class ToolCollisionOBBWithOBB { } public static void getCollidePoints(PhysicBox box1, PhysicBox box2) { //Log.info("Try to calculare reverse force ........"); - Vector3f RPos = box2.narrowPhaseGlobalPos.less_new(box1.narrowPhaseGlobalPos); + Vector3f RPos1 = box1.narrowPhaseGlobalPos.less_new(box2.narrowPhaseGlobalPos); + Vector3f RPos2 = box2.narrowPhaseGlobalPos.less_new(box1.narrowPhaseGlobalPos); Quaternion quat1 = box1.getQuaternionFull(); Quaternion quat2 = box2.getQuaternionFull(); // Step 1: set the Box 2 in the repere of the Box 1: - //Quaternion quatTransfer = Quaternion.diff(quat2, quat1); - Quaternion quatTransfer = Quaternion.diff(quat1, quat2); + Quaternion quatTransfer1 = Quaternion.diff(quat1, quat2); + Quaternion quatTransfer2 = Quaternion.diff(quat2, quat1); //quatTransfer.normalize(); //LoxelApplication.relativeTest = quatTransfer; @@ -140,30 +142,64 @@ public class ToolCollisionOBBWithOBB { // LoxelApplication.relativeTestPos.getTransform().setPosition(tmp); // LoxelApplication.relativeTestPos.getTransform().setOrientation(quatTransfer); // LoxelApplication.boxTest.setSize(box1.getSize()); - Log.info("" + RPos + quatTransfer); + //Log.info("" + RPos + quatTransfer1); // /*res = */getCollidePointsAABBCenteredWithOBB(box1.narrowPhaseHalfSize, box2.narrowPhaseHalfSize, quatTransfer, RPos); /* res = trenasfert 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 - RPos = box1.narrowPhaseGlobalPos.less_new(box2.narrowPhaseGlobalPos); //tmp = RPos.add_new(new Vector3f(0,0,14)); - quatTransfer = Quaternion.diff(quat2, quat1); - LoxelApplication.testRpos = RPos; - LoxelApplication.testQTransfert = quatTransfer; + LoxelApplication.testRpos = quat2.inverse_new().getMatrix4().multiply(RPos1); + LoxelApplication.testQTransfert = quatTransfer2; LoxelApplication.box1HalfSize = box2.narrowPhaseHalfSize; LoxelApplication.box2HalfSize = box1.narrowPhaseHalfSize; // LoxelApplication.relativeTestPos.getTransform().setPosition(tmp); // LoxelApplication.relativeTestPos.getTransform().setOrientation(quatTransfer); // LoxelApplication.boxTest.setSize(box1.getSize()); - /*res = */getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer, RPos); + // 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)); + /*res = */getCollidePointsAABBCenteredWithOBB(box2.narrowPhaseHalfSize, box1.narrowPhaseHalfSize, quatTransfer2, quat2.inverse_new().getMatrix4().multiply(RPos1)); /* res = trenasfert in generic plan the new res ...*/ } public static void getCollidePointsAABBCenteredWithOBB(Vector3f box1HalfSize, Vector3f box2HalfSize, Quaternion box2Orientation, Vector3f box2Position) { // point in AABB + // toune autour de la box ... +// Matrix4f tmp = box2Orientation.getMatrix4(); +// Vector3f topBackRight = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(+ box2HalfSize.x, + box2HalfSize.y, + box2HalfSize.z))).multiply(box2Position); +// Vector3f topBackLeft = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(- box2HalfSize.x, + box2HalfSize.y, + box2HalfSize.z))).multiply(box2Position); +// Vector3f topFrontRight = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(+ box2HalfSize.x, - box2HalfSize.y, + box2HalfSize.z))).multiply(box2Position); +// Vector3f topFrontLeft = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(- box2HalfSize.x, - box2HalfSize.y, + box2HalfSize.z))).multiply(box2Position); +// Vector3f bottomBackRight = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(+ box2HalfSize.x, + box2HalfSize.y, - box2HalfSize.z))).multiply(box2Position); +// Vector3f bottomBackLeft = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(- box2HalfSize.x, + box2HalfSize.y, - box2HalfSize.z))).multiply(box2Position); +// Vector3f bottomFrontRight = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(+ box2HalfSize.x, - box2HalfSize.y, - box2HalfSize.z))).multiply(box2Position); +// Vector3f bottomFrontLeft = tmp.multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(- box2HalfSize.x, - box2HalfSize.y, - box2HalfSize.z))).multiply(box2Position); + + // toune autour de la box ... +// Matrix4f tmp = box2Orientation.getMatrix4().multiply(Matrix4f.createMatrixTranslate(box2Position)); +// Vector3f topBackRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, + box2HalfSize.y, + box2HalfSize.z)); +// Vector3f topBackLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, + box2HalfSize.y, + box2HalfSize.z)); +// Vector3f topFrontRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, - box2HalfSize.y, + box2HalfSize.z)); +// Vector3f topFrontLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, - box2HalfSize.y, + box2HalfSize.z)); +// Vector3f bottomBackRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, + box2HalfSize.y, - box2HalfSize.z)); +// Vector3f bottomBackLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, + box2HalfSize.y, - box2HalfSize.z)); +// Vector3f bottomFrontRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, - box2HalfSize.y, - box2HalfSize.z)); +// Vector3f bottomFrontLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, - box2HalfSize.y, - box2HalfSize.z)); + +// Matrix4f tmp = Matrix4f.createMatrixTranslate(box2Position).multiply(box2Orientation.getMatrix4()); +// Vector3f topBackRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, + box2HalfSize.y, + box2HalfSize.z)); +// Vector3f topBackLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, + box2HalfSize.y, + box2HalfSize.z)); +// Vector3f topFrontRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, - box2HalfSize.y, + box2HalfSize.z)); +// Vector3f topFrontLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, - box2HalfSize.y, + box2HalfSize.z)); +// Vector3f bottomBackRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, + box2HalfSize.y, - box2HalfSize.z)); +// Vector3f bottomBackLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, + box2HalfSize.y, - box2HalfSize.z)); +// Vector3f bottomFrontRight = tmp.multiply(new Vector3f(+ box2HalfSize.x, - box2HalfSize.y, - box2HalfSize.z)); +// Vector3f bottomFrontLeft = tmp.multiply(new Vector3f(- box2HalfSize.x, - box2HalfSize.y, - box2HalfSize.z)); + // Vector3f topBackRight = box2Orientation.multiply(new Vector3f(box2Position.x + box2HalfSize.x, box2Position.y + box2HalfSize.y, box2Position.z + box2HalfSize.z)); // Vector3f topBackLeft = box2Orientation.multiply(new Vector3f(box2Position.x - box2HalfSize.x, box2Position.y + box2HalfSize.y, box2Position.z + box2HalfSize.z)); // Vector3f topFrontRight = box2Orientation.multiply(new Vector3f(box2Position.x + box2HalfSize.x, box2Position.y - box2HalfSize.y, box2Position.z + box2HalfSize.z)); @@ -172,6 +208,7 @@ public class ToolCollisionOBBWithOBB { // Vector3f bottomBackLeft = box2Orientation.multiply(new Vector3f(box2Position.x - box2HalfSize.x, box2Position.y + box2HalfSize.y, box2Position.z - box2HalfSize.z)); // Vector3f bottomFrontRight = box2Orientation.multiply(new Vector3f(box2Position.x + box2HalfSize.x, box2Position.y - box2HalfSize.y, box2Position.z - box2HalfSize.z)); // Vector3f bottomFrontLeft = box2Orientation.multiply(new Vector3f(box2Position.x - box2HalfSize.x, box2Position.y - box2HalfSize.y, box2Position.z - box2HalfSize.z)); + 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); diff --git a/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java b/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java index 4c586d9..2b937fa 100644 --- a/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java +++ b/src/org/atriaSoft/gameEngine/sample/LoxelEngine/LoxelApplication.java @@ -77,7 +77,7 @@ public class LoxelApplication extends Application { Gale.getContext().grabPointerEvents(true, new Vector2f(0,0)); env = new Environement(); this.canDraw = true; - setSize(new Vector2f(800, 600)); + setSize(new Vector2f(1500, 1500)); setTitle("Loxel sample"); map = new MapVoxel(this.env); // this.env.addEngine(map); @@ -127,7 +127,7 @@ public class LoxelApplication extends Application { { // add a cube to test collision ... Entity localBox = new Entity(this.env); - localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(2,-2,12.5f)))); + 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)))); @@ -185,7 +185,27 @@ public class LoxelApplication extends Application { Entity localBox = new Entity(this.env); Quaternion transform = new Quaternion(0.5f,0.2f,0.4f,1); transform.normalize(); - localBox.addComponent(new ComponentPosition(new Transform3D(new Vector3f(5,-5,14),transform))); + 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( @@ -331,17 +351,37 @@ public class LoxelApplication extends Application { if (collide == true) { debugDrawProperty.drawSquare(new Vector3f(0.1f,0.1f,0.1f), Matrix4f.identity().multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(elem.x,elem.y,elem.z+14))), new Color(1,0,0,1)); } else { - debugDrawProperty.drawSquare(new Vector3f(0.1f,0.1f,0.1f), Matrix4f.identity().multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(elem.x,elem.y,elem.z+14))), new Color(1,1,1,1)); + if (iii==0) { + debugDrawProperty.drawSquare(new Vector3f(0.05f,0.05f,0.05f), Matrix4f.identity().multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(elem.x,elem.y,elem.z+14))), new Color(0,1,0,1)); + } else if (iii==7) { + debugDrawProperty.drawSquare(new Vector3f(0.05f,0.05f,0.05f), Matrix4f.identity().multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(elem.x,elem.y,elem.z+14))), new Color(1,1,0,1)); + } else { + debugDrawProperty.drawSquare(new Vector3f(0.1f,0.1f,0.1f), Matrix4f.identity().multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(elem.x,elem.y,elem.z+14))), new Color(1,1,1,1)); + } } } - for (Vector3f elem : LoxelApplication.testPointsBox) { - debugDrawProperty.drawSquare(new Vector3f(0.1f,0.1f,0.1f), Matrix4f.identity().multiply_new(Matrix4f.createMatrixTranslate(new Vector3f(elem.x,elem.y,elem.z+14))), new Color(0,0,1,1)); + for (int iii=0; iii