GImpactShape Test Added (#1117)
* GImpactShape Test Added * GImpactShape Test Updates (WIP) * Minor tweaks based on feedback * Minor corrections + documentation added * Final tweaks
This commit is contained in:
parent
cff4dec57d
commit
8856ba7d25
@ -36,6 +36,7 @@ import com.jme3.asset.AssetManager;
|
|||||||
import com.jme3.asset.TextureKey;
|
import com.jme3.asset.TextureKey;
|
||||||
import com.jme3.bullet.PhysicsSpace;
|
import com.jme3.bullet.PhysicsSpace;
|
||||||
import com.jme3.bullet.collision.shapes.CollisionShape;
|
import com.jme3.bullet.collision.shapes.CollisionShape;
|
||||||
|
import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
|
||||||
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
|
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
|
||||||
import com.jme3.bullet.control.RigidBodyControl;
|
import com.jme3.bullet.control.RigidBodyControl;
|
||||||
import com.jme3.input.MouseInput;
|
import com.jme3.input.MouseInput;
|
||||||
@ -44,13 +45,18 @@ import com.jme3.input.controls.MouseButtonTrigger;
|
|||||||
import com.jme3.light.AmbientLight;
|
import com.jme3.light.AmbientLight;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Mesh;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.VertexBuffer;
|
||||||
import com.jme3.scene.shape.Box;
|
import com.jme3.scene.shape.Box;
|
||||||
import com.jme3.scene.shape.Sphere;
|
import com.jme3.scene.shape.Sphere;
|
||||||
import com.jme3.scene.shape.Sphere.TextureMode;
|
import com.jme3.scene.shape.Sphere.TextureMode;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
|
import com.jme3.util.BufferUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -59,8 +65,7 @@ import com.jme3.texture.Texture;
|
|||||||
public class PhysicsTestHelper {
|
public class PhysicsTestHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a simple physics test world with a floor, an obstacle and some
|
* creates a simple physics test world with a floor, an obstacle and some test boxes
|
||||||
* test boxes
|
|
||||||
*
|
*
|
||||||
* @param rootNode where lights and geometries should be added
|
* @param rootNode where lights and geometries should be added
|
||||||
* @param assetManager for loading assets
|
* @param assetManager for loading assets
|
||||||
@ -211,8 +216,7 @@ public class PhysicsTestHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates the necessary inputlistener and action to shoot balls from the
|
* creates the necessary inputlistener and action to shoot balls from the camera
|
||||||
* camera
|
|
||||||
*
|
*
|
||||||
* @param app the application that's running
|
* @param app the application that's running
|
||||||
* @param rootNode where ball geometries should be added
|
* @param rootNode where ball geometries should be added
|
||||||
@ -246,4 +250,116 @@ public class PhysicsTestHelper {
|
|||||||
app.getInputManager().addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
|
app.getInputManager().addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
|
||||||
app.getInputManager().addListener(actionListener, "shoot");
|
app.getInputManager().addListener(actionListener, "shoot");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a curved "floor" with a GImpactCollisionShape provided as the RigidBodyControl's collision
|
||||||
|
* shape. Surface has four slightly concave corners to allow for multiple tests and minimize falling off
|
||||||
|
* the edge of the floor.
|
||||||
|
*
|
||||||
|
* @param assetManager for loading assets
|
||||||
|
* @param floorDimensions width/depth of the "floor" (X/Z)
|
||||||
|
* @param position sets the floor's local translation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Geometry createGImpactTestFloor(AssetManager assetManager, float floorDimensions, Vector3f position) {
|
||||||
|
Geometry floor = createTestFloor(assetManager, floorDimensions, position, ColorRGBA.Red);
|
||||||
|
RigidBodyControl floorControl = new RigidBodyControl(new GImpactCollisionShape(floor.getMesh()), 0);
|
||||||
|
floor.addControl(floorControl);
|
||||||
|
return floor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a curved "floor" with a MeshCollisionShape provided as the RigidBodyControl's collision shape.
|
||||||
|
* Surface has four slightly concave corners to allow for multiple tests and minimize falling off the edge
|
||||||
|
* of the floor.
|
||||||
|
*
|
||||||
|
* @param assetManager for loading assets
|
||||||
|
* @param floorDimensions width/depth of the "floor" (X/Z)
|
||||||
|
* @param position sets the floor's local translation
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Geometry createMeshTestFloor(AssetManager assetManager, float floorDimensions, Vector3f position) {
|
||||||
|
Geometry floor = createTestFloor(assetManager, floorDimensions, position, new ColorRGBA(0.5f, 0.5f, 0.9f, 1));
|
||||||
|
RigidBodyControl floorControl = new RigidBodyControl(new MeshCollisionShape(floor.getMesh()), 0);
|
||||||
|
floor.addControl(floorControl);
|
||||||
|
return floor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Geometry createTestFloor(AssetManager assetManager, float floorDimensions, Vector3f position, ColorRGBA color) {
|
||||||
|
Geometry floor = new Geometry("floor", createFloorMesh(20, floorDimensions));
|
||||||
|
Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
|
material.getAdditionalRenderState().setWireframe(true);
|
||||||
|
material.setColor("Color", color);
|
||||||
|
floor.setMaterial(material);
|
||||||
|
floor.setLocalTranslation(position);
|
||||||
|
return floor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Mesh createFloorMesh(int meshDetail, float floorDimensions) {
|
||||||
|
if (meshDetail < 10) {
|
||||||
|
meshDetail = 10;
|
||||||
|
}
|
||||||
|
int numVertices = meshDetail * meshDetail * 2 * 3;//width * depth * two tris * 3 verts per tri
|
||||||
|
|
||||||
|
int[] indexBuf = new int[numVertices];
|
||||||
|
int i = 0;
|
||||||
|
for (int x = 0; x < meshDetail; x++) {
|
||||||
|
for (int z = 0; z < meshDetail; z++) {
|
||||||
|
indexBuf[i] = i++;
|
||||||
|
indexBuf[i] = i++;
|
||||||
|
indexBuf[i] = i++;
|
||||||
|
indexBuf[i] = i++;
|
||||||
|
indexBuf[i] = i++;
|
||||||
|
indexBuf[i] = i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] vertBuf = new float[numVertices * 3];
|
||||||
|
float xIncrement = floorDimensions / meshDetail;
|
||||||
|
float zIncrement = floorDimensions / meshDetail;
|
||||||
|
int j = 0;
|
||||||
|
for (int x = 0; x < meshDetail; x++) {
|
||||||
|
float xPos = x * xIncrement;
|
||||||
|
for (int z = 0; z < meshDetail; z++) {
|
||||||
|
float zPos = z * zIncrement;
|
||||||
|
//First tri
|
||||||
|
vertBuf[j++] = xPos;
|
||||||
|
vertBuf[j++] = getY(xPos, zPos, floorDimensions);
|
||||||
|
vertBuf[j++] = zPos;
|
||||||
|
vertBuf[j++] = xPos;
|
||||||
|
vertBuf[j++] = getY(xPos, zPos + zIncrement, floorDimensions);
|
||||||
|
vertBuf[j++] = zPos + zIncrement;
|
||||||
|
vertBuf[j++] = xPos + xIncrement;
|
||||||
|
vertBuf[j++] = getY(xPos + xIncrement, zPos, floorDimensions);
|
||||||
|
vertBuf[j++] = zPos;
|
||||||
|
//Second tri
|
||||||
|
vertBuf[j++] = xPos;
|
||||||
|
vertBuf[j++] = getY(xPos, zPos + zIncrement, floorDimensions);
|
||||||
|
vertBuf[j++] = zPos + zIncrement;
|
||||||
|
vertBuf[j++] = xPos + xIncrement;
|
||||||
|
vertBuf[j++] = getY(xPos + xIncrement, zPos + zIncrement, floorDimensions);
|
||||||
|
vertBuf[j++] = zPos + zIncrement;
|
||||||
|
vertBuf[j++] = xPos + xIncrement;
|
||||||
|
vertBuf[j++] = getY(xPos + xIncrement, zPos, floorDimensions);
|
||||||
|
vertBuf[j++] = zPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh m = new Mesh();
|
||||||
|
m.setBuffer(VertexBuffer.Type.Index, 1, BufferUtils.createIntBuffer(indexBuf));
|
||||||
|
m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertBuf));
|
||||||
|
m.updateBound();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getY(float x, float z, float max) {
|
||||||
|
float yMaxHeight = 8;
|
||||||
|
float xv = FastMath.unInterpolateLinear(FastMath.abs(x - (max / 2)), 0, max) * FastMath.TWO_PI;
|
||||||
|
float zv = FastMath.unInterpolateLinear(FastMath.abs(z - (max / 2)), 0, max) * FastMath.TWO_PI;
|
||||||
|
|
||||||
|
float xComp = (FastMath.sin(xv) + 1) * 0.5f;
|
||||||
|
float zComp = (FastMath.sin(zv) + 1) * 0.5f;
|
||||||
|
|
||||||
|
return -yMaxHeight * xComp * zComp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,342 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2019 jMonkeyEngine
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package jme3test.bullet.shape;
|
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication;
|
||||||
|
import com.jme3.bullet.BulletAppState;
|
||||||
|
import com.jme3.bullet.PhysicsSpace;
|
||||||
|
import com.jme3.bullet.collision.shapes.GImpactCollisionShape;
|
||||||
|
import com.jme3.bullet.control.RigidBodyControl;
|
||||||
|
import com.jme3.bullet.debug.BulletDebugAppState;
|
||||||
|
import com.jme3.font.BitmapFont;
|
||||||
|
import com.jme3.font.BitmapText;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.controls.ActionListener;
|
||||||
|
import com.jme3.input.controls.KeyTrigger;
|
||||||
|
import com.jme3.light.DirectionalLight;
|
||||||
|
import com.jme3.material.Material;
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Geometry;
|
||||||
|
import com.jme3.scene.Mesh;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.scene.shape.PQTorus;
|
||||||
|
import com.jme3.scene.shape.Torus;
|
||||||
|
import com.jme3.system.AppSettings;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import jme3test.bullet.PhysicsTestHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test demonstrates various GImpactCollisionShapes colliding against two identical curved surfaces. The
|
||||||
|
* left surface is a MeshCollisionShape, right surface is another GImpactCollisionShape. An ideal result is
|
||||||
|
* for all objects to land and change to a blue colored mesh indicating they are inactive. Falling through the
|
||||||
|
* floor, or never going inactive (bouncing forever) are failure conditions.
|
||||||
|
* <p>
|
||||||
|
* Observations as of June 2019 (JME v3.3.0-alpha2):
|
||||||
|
* <ol>
|
||||||
|
* <li>
|
||||||
|
* With default starting parameters, Native Bullet should pass the test parameters above. JBullet fails due to
|
||||||
|
* the rocket/MeshCollisionShape never going inactive.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Native Bullet behaves better than JBullet. JBullet sometimes allows objects to "gain too much energy" after
|
||||||
|
* a collision, such as the rocket or teapot. Native also does this, to a lesser degree. This generally
|
||||||
|
* appears to happen at larger object scales.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* JBullet allows some objects to get "stuck" inside the floor, which usually results in a fall-through
|
||||||
|
* eventually, generally a larger scales for this test.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Some shapes such as PQTorus & signpost never go inactive at larger scales for both Native and JBullet (test
|
||||||
|
* at 1.5 and 1.9 scale)
|
||||||
|
* </li>
|
||||||
|
* </ol>
|
||||||
|
*
|
||||||
|
* @author lou
|
||||||
|
*/
|
||||||
|
public class TestGimpactShape extends SimpleApplication {
|
||||||
|
|
||||||
|
private static TestGimpactShape test;
|
||||||
|
private BulletAppState bulletAppState;
|
||||||
|
private int solverNumIterations = 10;
|
||||||
|
private BitmapFont font;
|
||||||
|
private final BitmapText[] testInfo = new BitmapText[2];
|
||||||
|
private BitmapText timeElapsedTxt;
|
||||||
|
private BitmapText solverNumIterationsTxt;
|
||||||
|
private BitmapText testScale;
|
||||||
|
private final List<Spatial> testObjects = new ArrayList<>();
|
||||||
|
private float testTimer = 0;
|
||||||
|
private float scaleMod = 1;
|
||||||
|
private boolean restart = true;
|
||||||
|
private static final boolean SKIP_SETTINGS = false;//Used for repeated runs of this test during dev
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
test = new TestGimpactShape();
|
||||||
|
test.setSettings(new AppSettings(true));
|
||||||
|
test.settings.setFrameRate(60);
|
||||||
|
if (SKIP_SETTINGS) {
|
||||||
|
test.settings.setWidth(1920);
|
||||||
|
test.settings.setHeight(1150);
|
||||||
|
test.showSettings = !SKIP_SETTINGS;
|
||||||
|
}
|
||||||
|
test.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleInitApp() {
|
||||||
|
getCamera().setLocation(new Vector3f(40, 30, 160));
|
||||||
|
getCamera().lookAt(new Vector3f(40, -5, 0), Vector3f.UNIT_Y);
|
||||||
|
getFlyByCamera().setMoveSpeed(25);
|
||||||
|
|
||||||
|
DirectionalLight dl = new DirectionalLight();
|
||||||
|
dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
|
||||||
|
dl.setColor(ColorRGBA.Green);
|
||||||
|
rootNode.addLight(dl);
|
||||||
|
|
||||||
|
//Setup test instructions
|
||||||
|
guiNode = getGuiNode();
|
||||||
|
font = assetManager.loadFont("Interface/Fonts/Default.fnt");
|
||||||
|
testInfo[0] = new BitmapText(font);
|
||||||
|
testInfo[1] = new BitmapText(font);
|
||||||
|
timeElapsedTxt = new BitmapText(font);
|
||||||
|
solverNumIterationsTxt = new BitmapText(font);
|
||||||
|
testScale = new BitmapText(font);
|
||||||
|
|
||||||
|
float lineHeight = testInfo[0].getLineHeight();
|
||||||
|
testInfo[0].setText("Camera move:W/A/S/D/Q/Z Solver iterations: 1=10, 2=20, 3=30");
|
||||||
|
testInfo[0].setLocalTranslation(5, test.settings.getHeight(), 0);
|
||||||
|
guiNode.attachChild(testInfo[0]);
|
||||||
|
testInfo[1].setText("P: Toggle pause Inc/Dec object scale: +, - Space: Restart test");
|
||||||
|
testInfo[1].setLocalTranslation(5, test.settings.getHeight() - lineHeight, 0);
|
||||||
|
guiNode.attachChild(testInfo[1]);
|
||||||
|
|
||||||
|
timeElapsedTxt.setLocalTranslation(202, lineHeight * 1, 0);
|
||||||
|
guiNode.attachChild(timeElapsedTxt);
|
||||||
|
solverNumIterationsTxt.setLocalTranslation(202, lineHeight * 2, 0);
|
||||||
|
guiNode.attachChild(solverNumIterationsTxt);
|
||||||
|
testScale.setLocalTranslation(202, lineHeight * 3, 0);
|
||||||
|
guiNode.attachChild(testScale);
|
||||||
|
|
||||||
|
//Setup interactive test controls
|
||||||
|
inputManager.addMapping("restart", new KeyTrigger(KeyInput.KEY_SPACE));
|
||||||
|
inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
|
||||||
|
restart = true;
|
||||||
|
}, "restart");
|
||||||
|
|
||||||
|
inputManager.addMapping("pause", new KeyTrigger(KeyInput.KEY_P));
|
||||||
|
inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
|
||||||
|
if (!isPressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bulletAppState.setSpeed(bulletAppState.getSpeed() > 0.1 ? 0 : 1);
|
||||||
|
}, "pause");
|
||||||
|
|
||||||
|
inputManager.addMapping("1", new KeyTrigger(KeyInput.KEY_1));
|
||||||
|
inputManager.addMapping("2", new KeyTrigger(KeyInput.KEY_2));
|
||||||
|
inputManager.addMapping("3", new KeyTrigger(KeyInput.KEY_3));
|
||||||
|
inputManager.addMapping("+", new KeyTrigger(KeyInput.KEY_ADD), new KeyTrigger(KeyInput.KEY_EQUALS));
|
||||||
|
inputManager.addMapping("-", new KeyTrigger(KeyInput.KEY_SUBTRACT), new KeyTrigger(KeyInput.KEY_MINUS));
|
||||||
|
inputManager.addListener((ActionListener) (String name, boolean isPressed, float tpf) -> {
|
||||||
|
if (!isPressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (name) {
|
||||||
|
case "1":
|
||||||
|
solverNumIterations = 10;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
solverNumIterations = 20;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
solverNumIterations = 30;
|
||||||
|
break;
|
||||||
|
case "+":
|
||||||
|
scaleMod += scaleMod < 1.9f ? 0.1f : 0;
|
||||||
|
break;
|
||||||
|
case "-":
|
||||||
|
scaleMod -= scaleMod > 0.5f ? 0.1f : 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
restart = true;
|
||||||
|
}, "1", "2", "3", "+", "-");
|
||||||
|
|
||||||
|
initializeNewTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeNewTest() {
|
||||||
|
testScale.setText("Object scale: " + String.format("%.1f", scaleMod));
|
||||||
|
solverNumIterationsTxt.setText("Solver Iterations: " + solverNumIterations);
|
||||||
|
|
||||||
|
bulletAppState = new BulletAppState();
|
||||||
|
bulletAppState.setDebugEnabled(true);
|
||||||
|
stateManager.attach(bulletAppState);
|
||||||
|
bulletAppState.getPhysicsSpace().setSolverNumIterations(solverNumIterations);
|
||||||
|
|
||||||
|
float floorSize = 80;
|
||||||
|
//Left side test - GImpact objects collide with MeshCollisionShape floor
|
||||||
|
Vector3f leftFloorPos = new Vector3f(-41, -5, -10);
|
||||||
|
Vector3f leftFloorCenter = leftFloorPos.add(floorSize / 2, 0, floorSize / 2);
|
||||||
|
|
||||||
|
dropTest1(leftFloorCenter);
|
||||||
|
dropTest2(leftFloorCenter);
|
||||||
|
dropPot(leftFloorCenter);
|
||||||
|
dropSword(leftFloorCenter);
|
||||||
|
dropSign(leftFloorCenter);
|
||||||
|
dropRocket(leftFloorCenter);
|
||||||
|
|
||||||
|
Geometry leftFloor = PhysicsTestHelper.createMeshTestFloor(assetManager, floorSize, leftFloorPos);
|
||||||
|
addObject(leftFloor);
|
||||||
|
|
||||||
|
//Right side test - GImpact objects collide with GImpact floor
|
||||||
|
Vector3f rightFloorPos = new Vector3f(41, -5, -10);
|
||||||
|
Vector3f rightFloorCenter = rightFloorPos.add(floorSize / 2, 0, floorSize / 2);
|
||||||
|
|
||||||
|
dropTest1(rightFloorCenter);
|
||||||
|
dropTest2(rightFloorCenter);
|
||||||
|
dropPot(rightFloorCenter);
|
||||||
|
dropSword(rightFloorCenter);
|
||||||
|
dropSign(rightFloorCenter);
|
||||||
|
dropRocket(rightFloorCenter);
|
||||||
|
|
||||||
|
Geometry rightFloor = PhysicsTestHelper.createGImpactTestFloor(assetManager, floorSize, rightFloorPos);
|
||||||
|
addObject(rightFloor);
|
||||||
|
|
||||||
|
//Hide physics debug visualization for floors
|
||||||
|
BulletDebugAppState bulletDebugAppState = stateManager.getState(BulletDebugAppState.class);
|
||||||
|
bulletDebugAppState.setFilter((Object obj) -> {
|
||||||
|
return !(obj.equals(rightFloor.getControl(RigidBodyControl.class))
|
||||||
|
|| obj.equals(leftFloor.getControl(RigidBodyControl.class)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addObject(Spatial s) {
|
||||||
|
testObjects.add(s);
|
||||||
|
rootNode.attachChild(s);
|
||||||
|
physicsSpace().add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropTest1(Vector3f offset) {
|
||||||
|
offset = offset.add(-18, 6, -18);
|
||||||
|
attachTestObject(new Torus(16, 16, 0.15f, 0.5f), new Vector3f(-12f, 0f, 5f).add(offset), 1);
|
||||||
|
attachTestObject(new PQTorus(2f, 3f, 0.6f, 0.2f, 48, 16), new Vector3f(0, 0, 0).add(offset), 5);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropTest2(Vector3f offset) {
|
||||||
|
offset = offset.add(18, 6, -18);
|
||||||
|
attachTestObject(new Torus(16, 16, 0.3f, 0.8f), new Vector3f(12f, 0f, 5f).add(offset), 3);
|
||||||
|
attachTestObject(new PQTorus(3f, 5f, 0.8f, 0.2f, 96, 16), new Vector3f(0, 0, 0).add(offset), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropPot(Vector3f offset) {
|
||||||
|
drop(offset.add(-12, 7, 15), "Models/Teapot/Teapot.mesh.xml", 1.0f, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropSword(Vector3f offset) {
|
||||||
|
drop(offset.add(-10, 5, 3), "Models/Sinbad/Sword.mesh.xml", 1.0f, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropSign(Vector3f offset) {
|
||||||
|
drop(offset.add(9, 15, 5), "Models/Sign Post/Sign Post.mesh.xml", 1.0f, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropRocket(Vector3f offset) {
|
||||||
|
RigidBodyControl c = drop(offset.add(26, 4, 7), "Models/SpaceCraft/Rocket.mesh.xml", 4.0f, 3);
|
||||||
|
c.setAngularDamping(0.5f);
|
||||||
|
c.setLinearDamping(0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RigidBodyControl drop(Vector3f offset, String model, float scale, float mass) {
|
||||||
|
scale *= scaleMod;
|
||||||
|
Node n = (Node) assetManager.loadModel(model);
|
||||||
|
n.setLocalTranslation(offset);
|
||||||
|
n.rotate(0, 0, -FastMath.HALF_PI);
|
||||||
|
|
||||||
|
Geometry tp = ((Geometry) n.getChild(0));
|
||||||
|
tp.scale(scale);
|
||||||
|
Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
|
||||||
|
tp.setMaterial(mat);
|
||||||
|
|
||||||
|
Mesh mesh = tp.getMesh();
|
||||||
|
GImpactCollisionShape shape = new GImpactCollisionShape(mesh);
|
||||||
|
shape.setScale(new Vector3f(scale, scale, scale));
|
||||||
|
|
||||||
|
RigidBodyControl control = new RigidBodyControl(shape, mass);
|
||||||
|
n.addControl(control);
|
||||||
|
addObject(n);
|
||||||
|
return control;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void attachTestObject(Mesh mesh, Vector3f position, float mass) {
|
||||||
|
Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
|
||||||
|
material.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
|
||||||
|
Geometry g = new Geometry("mesh", mesh);
|
||||||
|
g.scale(scaleMod);
|
||||||
|
g.setLocalTranslation(position);
|
||||||
|
g.setMaterial(material);
|
||||||
|
|
||||||
|
GImpactCollisionShape shape = new GImpactCollisionShape(mesh);
|
||||||
|
shape.setScale(new Vector3f(scaleMod, scaleMod, scaleMod));
|
||||||
|
RigidBodyControl control = new RigidBodyControl(shape, mass);
|
||||||
|
g.addControl(control);
|
||||||
|
addObject(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PhysicsSpace physicsSpace() {
|
||||||
|
return bulletAppState.getPhysicsSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void simpleUpdate(float tpf) {
|
||||||
|
testTimer += tpf * bulletAppState.getSpeed();
|
||||||
|
|
||||||
|
if (restart) {
|
||||||
|
cleanup();
|
||||||
|
initializeNewTest();
|
||||||
|
restart = false;
|
||||||
|
testTimer = 0;
|
||||||
|
}
|
||||||
|
timeElapsedTxt.setText("Time Elapsed: " + String.format("%.3f", testTimer));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanup() {
|
||||||
|
stateManager.detach(bulletAppState);
|
||||||
|
stateManager.detach(stateManager.getState(BulletDebugAppState.class));
|
||||||
|
for (Spatial s : testObjects) {
|
||||||
|
rootNode.detachChild(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user