-
-
Save jcfandino/21b08cf733a60c9e521234dae17b7f24 to your computer and use it in GitHub Desktop.
jme bcc hops
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package jc.workbench.bullet; | |
import com.jme3.anim.AnimComposer; | |
import com.jme3.anim.tween.action.Action; | |
import com.jme3.app.SimpleApplication; | |
import com.jme3.bullet.BulletAppState; | |
import com.jme3.bullet.PhysicsSpace; | |
import com.jme3.bullet.collision.shapes.CollisionShape; | |
import com.jme3.bullet.control.BetterCharacterControl; | |
import com.jme3.bullet.control.RigidBodyControl; | |
import com.jme3.bullet.util.CollisionShapeFactory; | |
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.AmbientLight; | |
import com.jme3.light.DirectionalLight; | |
import com.jme3.material.Material; | |
import com.jme3.material.Materials; | |
import com.jme3.material.RenderState.BlendMode; | |
import com.jme3.math.ColorRGBA; | |
import com.jme3.math.FastMath; | |
import com.jme3.math.Quaternion; | |
import com.jme3.math.Vector3f; | |
import com.jme3.renderer.queue.RenderQueue; | |
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.Box; | |
import com.jme3.scene.shape.Cylinder; | |
import com.jme3.scene.shape.Quad; | |
import com.jme3.shadow.DirectionalLightShadowRenderer; | |
import com.jme3.shadow.EdgeFilteringMode; | |
import com.jme3.system.AppSettings; | |
import com.jme3.terrain.geomipmap.TerrainQuad; | |
import com.jme3.terrain.heightmap.HeightMap; | |
import com.jme3.terrain.heightmap.ImageBasedHeightMap; | |
import com.jme3.texture.Image; | |
import com.jme3.texture.Texture; | |
/** | |
* An example of character physics using Oto and BetterCharacterControl. | |
* | |
* Press the U/H/J/K keys to walk. | |
* | |
* @author Stephen Gold sgold@sonic.net | |
*/ | |
public class TestOtoBcc | |
extends SimpleApplication | |
implements ActionListener { | |
// ************************************************************************* | |
// fields | |
private Action standAction; | |
private Action walkAction; | |
private AnimComposer composer; | |
private BetterCharacterControl character; | |
/** | |
* true when the U key is pressed, otherwise false | |
*/ | |
private volatile boolean walkAway; | |
/** | |
* true when the H key is pressed, otherwise false | |
*/ | |
private volatile boolean walkLeft; | |
/** | |
* true when the K key is pressed, otherwise false | |
*/ | |
private volatile boolean walkRight; | |
/** | |
* true when the J key is pressed, otherwise false | |
*/ | |
private volatile boolean walkToward; | |
final private Node translationNode = new Node("translation node"); | |
// ************************************************************************* | |
// new methods exposed | |
private float maxHeight = - Float.MIN_VALUE; | |
private BitmapText text = null; | |
/** | |
* Main entry point for the application. | |
* | |
* @param ignored array of command-line arguments (not null) | |
*/ | |
public static void main(String[] ignored) { | |
TestOtoBcc application = new TestOtoBcc(); | |
// Enable gamma correction for accurate lighting. | |
boolean loadDefaults = true; | |
AppSettings settings = new AppSettings(loadDefaults); | |
settings.setGammaCorrection(true); | |
application.setSettings(settings); | |
application.start(); | |
} | |
// ************************************************************************* | |
// SimpleApplication methods | |
/** | |
* Initialize this application. | |
*/ | |
@Override | |
public void simpleInitApp() { | |
addLighting(rootNode); | |
configureCamera(); | |
configureInput(); | |
PhysicsSpace physicsSpace = configurePhysics(); | |
// Load the Oto model and find its animation actions. | |
// Spatial oto = assetManager.loadModel("Models/Oto/Oto.mesh.xml"); | |
// composer = oto.getControl(AnimComposer.class); | |
// standAction = composer.action("stand"); | |
// walkAction = composer.action("Walk"); | |
Spatial oto = new Geometry("oto", new Box(0.5f, 1f,0.5f)); | |
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); | |
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); | |
mat.setColor("Color", ColorRGBA.Brown); | |
oto.setMaterial(mat); | |
// Attach the model model to a translation node. | |
rootNode.attachChild(translationNode); | |
translationNode.attachChild(oto); | |
oto.move(0f, 0.5f, 0f); | |
// Create the PhysicsControl and add it to the scene and space. | |
float characterRadius = 0.5f; | |
float characterHeight = 2f; | |
float characterMass = 100f; | |
character = new BetterCharacterControl(characterRadius, characterHeight, | |
characterMass); | |
translationNode.addControl(character); | |
physicsSpace.add(character); | |
character.warp(new Vector3f(-73.6f, 14.09f, -45.58f)); | |
addGround(physicsSpace, "notterrain"); | |
BitmapFont font = assetManager.loadFont("Interface/Fonts/Default.fnt"); | |
text = new BitmapText(font, false); | |
text.setLocalTranslation(cam.getWidth() / 2f, cam.getHeight()/2f, 0f); | |
guiNode.attachChild(text); | |
flyCam.setDragToRotate(true); | |
} | |
/** | |
* Callback invoked once per frame. | |
* | |
* @param tpf the time interval between frames (in seconds, ≥0) | |
*/ | |
@Override | |
public void simpleUpdate(float tpf) { | |
// Determine horizontal directions relative to the camera orientation. | |
Vector3f away = cam.getDirection(); | |
away.y = 0; | |
away.normalizeLocal(); | |
Vector3f left = cam.getLeft(); | |
left.y = 0; | |
left.normalizeLocal(); | |
// Determine the walk velocity from keyboard inputs. | |
Vector3f direction = new Vector3f(); | |
if (walkAway) { | |
direction.addLocal(away); | |
} | |
if (walkLeft) { | |
direction.addLocal(left); | |
} | |
if (walkRight) { | |
direction.subtractLocal(left); | |
} | |
if (walkToward) { | |
direction.subtractLocal(away); | |
} | |
direction.normalizeLocal(); | |
float walkSpeed = 50f; | |
Vector3f walkVelocity = direction.mult(walkSpeed); | |
character.setWalkDirection(walkVelocity); | |
float current = character.getRigidBody().getPhysicsLocation().getY(); | |
maxHeight = Math.max(maxHeight, current); | |
text.setText(String.format("Current height: %f\nMax registered: %f", current, maxHeight)); | |
// Update the animation action. | |
// Action action = composer.getCurrentAction(); | |
// if (walkVelocity.length() < 0.001f) { | |
// if (action != standAction) { | |
// composer.setCurrentAction("stand"); | |
// } | |
// } else { | |
// character.setViewDirection(direction); | |
// if (action != walkAction) { | |
// composer.setCurrentAction("Walk"); | |
// } | |
// } | |
} | |
// ************************************************************************* | |
// ActionListener methods | |
/** | |
* Callback to handle keyboard input events. | |
* | |
* @param action the name of the input event | |
* @param ongoing true → pressed, false → released | |
* @param tpf the time per frame (in seconds, ≥0) | |
*/ | |
@Override | |
public void onAction(String action, boolean ongoing, float tpf) { | |
switch (action) { | |
case "walk away": | |
walkAway = ongoing; | |
return; | |
case "walk left": | |
walkLeft = ongoing; | |
return; | |
case "walk right": | |
walkRight = ongoing; | |
return; | |
case "walk toward": | |
walkToward = ongoing; | |
return; | |
default: | |
System.out.println("Unknown action: " + action); | |
} | |
} | |
// ************************************************************************* | |
// private methods | |
/** | |
* Add lighting and shadows to the specified scene. | |
*/ | |
private void addLighting(Spatial scene) { | |
scene.setShadowMode(RenderQueue.ShadowMode.CastAndReceive); | |
ColorRGBA ambientColor = new ColorRGBA(0.03f, 0.03f, 0.03f, 1f); | |
AmbientLight ambient = new AmbientLight(ambientColor); | |
scene.addLight(ambient); | |
ambient.setName("ambient"); | |
ColorRGBA directColor = new ColorRGBA(0.3f, 0.3f, 0.3f, 1f); | |
Vector3f direction = new Vector3f(-7f, -3f, -5f).normalizeLocal(); | |
DirectionalLight sun = new DirectionalLight(direction, directColor); | |
scene.addLight(sun); | |
sun.setName("sun"); | |
// Render shadows based on the directional light. | |
viewPort.clearProcessors(); | |
int shadowMapSize = 2_048; // in pixels | |
int numSplits = 3; | |
DirectionalLightShadowRenderer dlsr | |
= new DirectionalLightShadowRenderer(assetManager, | |
shadowMapSize, numSplits); | |
dlsr.setEdgeFilteringMode(EdgeFilteringMode.PCFPOISSON); | |
dlsr.setEdgesThickness(5); | |
dlsr.setLight(sun); | |
dlsr.setShadowIntensity(0.4f); | |
viewPort.addProcessor(dlsr); | |
// Set the viewport's background color to light blue. | |
ColorRGBA skyColor = new ColorRGBA(0.1f, 0.2f, 0.4f, 1f); | |
viewPort.setBackgroundColor(skyColor); | |
} | |
/** | |
* Add a heightfield body to the specified PhysicsSpace. | |
* | |
* @param physicsSpace (not null) | |
*/ | |
private void addGround(PhysicsSpace physicsSpace, String groundType) { | |
Spatial ground; | |
if (groundType.equalsIgnoreCase("terrain")) { | |
String assetPath = "Textures/Terrain/splat/mountains512.png"; | |
Texture texture = assetManager.loadTexture(assetPath); | |
Image image = texture.getImage(); | |
HeightMap heightMap = new ImageBasedHeightMap(image); | |
heightMap.setHeightScale(0.2f); | |
heightMap.load(); | |
ground = new TerrainQuad("terrain", 65, 513, heightMap.getHeightMap()); | |
} else { | |
Mesh quad = new Quad(999f, 999f); | |
ground = new Geometry("terrain", quad); | |
ground.move(-500f, 14f, 500f); | |
ground.rotate(-FastMath.HALF_PI, 0f, 0f); | |
} | |
rootNode.attachChild(ground); | |
Material greenMaterial = createLitMaterial(0f, 0.5f, 0f); | |
ground.setMaterial(greenMaterial); | |
// Construct a static RigidBodyControl based on the ground spatial. | |
CollisionShape shape = CollisionShapeFactory.createMeshShape(ground); | |
RigidBodyControl rbc = new RigidBodyControl(shape, 0f); | |
rbc.setPhysicsSpace(physicsSpace); | |
ground.addControl(rbc); | |
} | |
/** | |
* Configure the Camera during startup. | |
*/ | |
private void configureCamera() { | |
flyCam.setMoveSpeed(10f); | |
cam.setLocation(new Vector3f(-39f, 34f, -47f)); | |
cam.setRotation(new Quaternion(0.183f, -0.68302f, 0.183f, 0.68302f)); | |
} | |
/** | |
* Configure keyboard input during startup. | |
*/ | |
private void configureInput() { | |
inputManager.addMapping("walk away", new KeyTrigger(KeyInput.KEY_U)); | |
inputManager.addMapping("walk left", new KeyTrigger(KeyInput.KEY_H)); | |
inputManager.addMapping("walk right", new KeyTrigger(KeyInput.KEY_K)); | |
inputManager.addMapping("walk toward", new KeyTrigger(KeyInput.KEY_J)); | |
inputManager.addListener(this, | |
"walk away", "walk left", "walk right", "walk toward"); | |
} | |
/** | |
* Configure physics during startup. | |
*/ | |
private PhysicsSpace configurePhysics() { | |
BulletAppState bulletAppState = new BulletAppState(); | |
bulletAppState.setDebugEnabled(true); | |
stateManager.attach(bulletAppState); | |
PhysicsSpace result = bulletAppState.getPhysicsSpace(); | |
result.setGravity(new Vector3f(0f, -60f, 0f)); | |
return result; | |
} | |
/** | |
* Create a single-sided lit material with the specified reflectivities. | |
* | |
* @param red the desired reflectivity for red light (≥0, ≤1) | |
* @param green the desired reflectivity for green light (≥0, ≤1) | |
* @param blue the desired reflectivity for blue light (≥0, ≤1) | |
* @return a new instance (not null) | |
*/ | |
private Material createLitMaterial(float red, float green, float blue) { | |
Material result = new Material(assetManager, Materials.LIGHTING); | |
result.setBoolean("UseMaterialColors", true); | |
float opacity = 1f; | |
result.setColor("Ambient", new ColorRGBA(red, green, blue, opacity)); | |
result.setColor("Diffuse", new ColorRGBA(red, green, blue, opacity)); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment