diff --git a/engine/src/test/jme3test/helloworld/HelloAssets.java b/engine/src/test/jme3test/helloworld/HelloAssets.java index 44336c9fb..7635abbc6 100644 --- a/engine/src/test/jme3test/helloworld/HelloAssets.java +++ b/engine/src/test/jme3test/helloworld/HelloAssets.java @@ -87,6 +87,5 @@ public class HelloAssets extends SimpleApplication { DirectionalLight sun = new DirectionalLight(); sun.setDirection(new Vector3f(-0.1f, -0.7f, -1.0f).normalizeLocal()); rootNode.addLight(sun); - } } diff --git a/engine/src/test/jme3test/helloworld/HelloAudio.java b/engine/src/test/jme3test/helloworld/HelloAudio.java index 13dcbeba7..b61439669 100644 --- a/engine/src/test/jme3test/helloworld/HelloAudio.java +++ b/engine/src/test/jme3test/helloworld/HelloAudio.java @@ -29,7 +29,8 @@ public class HelloAudio extends SimpleApplication { /** just a blue box floating in space */ Box box1 = new Box(Vector3f.ZERO, 1, 1, 1); player = new Geometry("Player", box1); - Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + Material mat1 = new Material(assetManager, + "Common/MatDefs/Misc/Unshaded.j3md"); mat1.setColor("Color", ColorRGBA.Blue); player.setMaterial(mat1); rootNode.attachChild(player); @@ -42,22 +43,22 @@ public class HelloAudio extends SimpleApplication { /** We create two audio nodes. */ private void initAudio() { /* gun shot sound is to be triggered by a mouse click. */ - audio_gun = new AudioNode(audioRenderer, assetManager, "Sound/Effects/Gun.wav", false); + audio_gun = new AudioNode(assetManager, "Sound/Effects/Gun.wav", false); audio_gun.setLooping(false); audio_gun.setVolume(2); + rootNode.attachChild(audio_gun); /* nature sound - keeps playing in a loop. */ - audio_nature = new AudioNode(audioRenderer, assetManager, "Sound/Environment/Nature.ogg", false); - audio_nature.setLooping(true); + audio_nature = new AudioNode(assetManager, "Sound/Environment/Nature.ogg", true); + audio_nature.setLooping(true); // activate continuous playing audio_nature.setPositional(true); audio_nature.setLocalTranslation(Vector3f.ZERO.clone()); audio_nature.setVolume(3); - audio_nature.updateGeometricState(); - audioRenderer.playSource(audio_nature); // play continuously! + rootNode.attachChild(audio_nature); + audio_nature.play(); // play continuously! } - /** Declaring the "Shoot" action, and - * mapping it to a trigger (mouse click). */ + /** Declaring "Shoot" action, mapping it to a trigger (mouse click). */ private void initKeys() { inputManager.addMapping("Shoot", new MouseButtonTrigger(0)); inputManager.addListener(actionListener, "Shoot"); @@ -68,7 +69,7 @@ public class HelloAudio extends SimpleApplication { @Override public void onAction(String name, boolean keyPressed, float tpf) { if (name.equals("Shoot") && !keyPressed) { - audioRenderer.playSource(audio_gun); // play once! + audio_gun.playInstance(); // play each instance once! } } }; diff --git a/engine/src/test/jme3test/helloworld/HelloCollision.java b/engine/src/test/jme3test/helloworld/HelloCollision.java index 2da6b5e95..35d91edc0 100644 --- a/engine/src/test/jme3test/helloworld/HelloCollision.java +++ b/engine/src/test/jme3test/helloworld/HelloCollision.java @@ -52,11 +52,11 @@ import com.jme3.scene.Spatial; /** * Example 9 - How to make walls and floors solid. - * This version uses Physics and a custom Action Listener. + * This collision code uses Physics and a custom Action Listener. * @author normen, with edits by Zathras */ public class HelloCollision extends SimpleApplication - implements ActionListener { + implements ActionListener { private Spatial sceneModel; private BulletAppState bulletAppState; @@ -74,9 +74,10 @@ public class HelloCollision extends SimpleApplication /** Set up Physics */ bulletAppState = new BulletAppState(); stateManager.attach(bulletAppState); + //bulletAppState.getPhysicsSpace().enableDebug(assetManager); // We re-use the flyby camera for rotation, while positioning is handled by physics - viewPort.setBackgroundColor(new ColorRGBA(0.7f,0.8f,1f,1f)); + viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f)); flyCam.setMoveSpeed(100); setUpKeys(); setUpLight(); @@ -87,15 +88,15 @@ public class HelloCollision extends SimpleApplication sceneModel.setLocalScale(2f); // We set up collision detection for the scene by creating a - // compound collision shape and a static physics node with mass zero. + // compound collision shape and a static RigidBodyControl with mass zero. CollisionShape sceneShape = - CollisionShapeFactory.createMeshShape((Node) sceneModel); + CollisionShapeFactory.createMeshShape((Node) sceneModel); landscape = new RigidBodyControl(sceneShape, 0); sceneModel.addControl(landscape); - + // We set up collision detection for the player by creating - // a capsule collision shape and a physics character node. - // The physics character node offers extra settings for + // a capsule collision shape and a CharacterControl. + // The CharacterControl offers extra settings for // size, stepheight, jumping, falling, and gravity. // We also put the player in its starting position. CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1); @@ -112,45 +113,45 @@ public class HelloCollision extends SimpleApplication bulletAppState.getPhysicsSpace().add(player); } - private void setUpLight() { - // We add light so we see the scene - AmbientLight al = new AmbientLight(); - al.setColor(ColorRGBA.White.mult(1.3f)); - rootNode.addLight(al); + private void setUpLight() { + // We add light so we see the scene + AmbientLight al = new AmbientLight(); + al.setColor(ColorRGBA.White.mult(1.3f)); + rootNode.addLight(al); - DirectionalLight dl = new DirectionalLight(); - dl.setColor(ColorRGBA.White); - dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal()); - rootNode.addLight(dl); - } + DirectionalLight dl = new DirectionalLight(); + dl.setColor(ColorRGBA.White); + dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal()); + rootNode.addLight(dl); + } /** We over-write some navigational key mappings here, so we can * add physics-controlled walking and jumping: */ private void setUpKeys() { - inputManager.addMapping("Lefts", new KeyTrigger(KeyInput.KEY_A)); - inputManager.addMapping("Rights", new KeyTrigger(KeyInput.KEY_D)); - inputManager.addMapping("Ups", new KeyTrigger(KeyInput.KEY_W)); - inputManager.addMapping("Downs", new KeyTrigger(KeyInput.KEY_S)); - inputManager.addMapping("Jumps", new KeyTrigger(KeyInput.KEY_SPACE)); - inputManager.addListener(this, "Lefts"); - inputManager.addListener(this, "Rights"); - inputManager.addListener(this, "Ups"); - inputManager.addListener(this, "Downs"); - inputManager.addListener(this, "Jumps"); + inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A)); + inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D)); + inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W)); + inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S)); + inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE)); + inputManager.addListener(this, "Left"); + inputManager.addListener(this, "Right"); + inputManager.addListener(this, "Up"); + inputManager.addListener(this, "Down"); + inputManager.addListener(this, "Jump"); } /** These are our custom actions triggered by key presses. * We do not walk yet, we just keep track of the direction the user pressed. */ public void onAction(String binding, boolean value, float tpf) { - if (binding.equals("Lefts")) { - if (value) { left = true; } else { left = false; } - } else if (binding.equals("Rights")) { + if (binding.equals("Left")) { + if (value) { left = true; } else { left = false; } + } else if (binding.equals("Right")) { if (value) { right = true; } else { right = false; } - } else if (binding.equals("Ups")) { - if (value) { up = true; } else { up = false; } - } else if (binding.equals("Downs")) { - if (value) { down = true; } else { down = false; } - } else if (binding.equals("Jumps")) { + } else if (binding.equals("Up")) { + if (value) { up = true; } else { up = false; } + } else if (binding.equals("Down")) { + if (value) { down = true; } else { down = false; } + } else if (binding.equals("Jump")) { player.jump(); } } diff --git a/engine/src/test/jme3test/helloworld/HelloEffects.java b/engine/src/test/jme3test/helloworld/HelloEffects.java index a7f033830..70e2e7824 100644 --- a/engine/src/test/jme3test/helloworld/HelloEffects.java +++ b/engine/src/test/jme3test/helloworld/HelloEffects.java @@ -49,52 +49,63 @@ public class HelloEffects extends SimpleApplication { @Override public void simpleInitApp() { - - ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30); - Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); - mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png")); + ParticleEmitter fire = + new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30); + Material mat_red = new Material(assetManager, + "Common/MatDefs/Misc/Particle.j3md"); + mat_red.setTexture("Texture", assetManager.loadTexture( + "Effects/Explosion/flame.png")); fire.setMaterial(mat_red); - fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation + fire.setImagesX(2); + fire.setImagesY(2); // 2x2 texture animation fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 1f)); // red fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow - fire.setInitialVelocity(new Vector3f(0, 2, 0)); + fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 2, 0)); fire.setStartSize(1.5f); fire.setEndSize(0.1f); fire.setGravity(0, 0, 0); fire.setLowLife(1f); fire.setHighLife(3f); - fire.setVelocityVariation(0.3f); + fire.getParticleInfluencer().setVelocityVariation(0.3f); rootNode.attachChild(fire); - ParticleEmitter debris = new ParticleEmitter("Debris", ParticleMesh.Type.Triangle, 10); - Material debris_mat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); - debris_mat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/Debris.png")); + ParticleEmitter debris = + new ParticleEmitter("Debris", ParticleMesh.Type.Triangle, 10); + Material debris_mat = new Material(assetManager, + "Common/MatDefs/Misc/Particle.j3md"); + debris_mat.setTexture("Texture", assetManager.loadTexture( + "Effects/Explosion/Debris.png")); debris.setMaterial(debris_mat); - debris.setImagesX(3); debris.setImagesY(3); // 3x3 texture animation - debris.setRotateSpeed(4); + debris.setImagesX(3); + debris.setImagesY(3); // 3x3 texture animation debris.setSelectRandomImage(true); - debris.setInitialVelocity(new Vector3f(0, 4, 0)); + debris.setRotateSpeed(4); + debris.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 4, 0)); debris.setStartColor(ColorRGBA.White); debris.setGravity(0, 6, 0); - debris.setVelocityVariation(.60f); + debris.getParticleInfluencer().setVelocityVariation(.60f); rootNode.attachChild(debris); debris.emitAllParticles(); -// ParticleEmitter water = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30); -// Material mat_blue = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); -// mat_blue.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png")); +// ParticleEmitter water = +// new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 20); +// Material mat_blue = new Material(assetManager, +// "Common/MatDefs/Misc/Particle.j3md"); +// mat_blue.setTexture("Texture", assetManager.loadTexture( +// "Effects/Explosion/flame.png")); // water.setMaterial(mat_blue); -// water.setImagesX(2); water.setImagesY(2); // 2x2 texture animation -// water.setStartColor(new ColorRGBA(0f, 0f, 1f, 1f)); // blue -// water.setEndColor( new ColorRGBA(0f, 1f, 1f, 1f)); // turquois -// water.setInitialVelocity(new Vector3f(0, -2, 0)); +// water.setImagesX(2); +// water.setImagesY(2); // 2x2 texture animation +// water.setStartColor( ColorRGBA.Blue); +// water.setEndColor( ColorRGBA.Cyan); +// water.getParticleInfluencer().setInitialVelocity(new Vector3f(0, -4, 0)); // water.setStartSize(1f); // water.setEndSize(1.5f); -// water.setGravity(1); +// water.setGravity(0,1,0); // water.setLowLife(1f); -// water.setHighLife(3f); -// water.setVelocityVariation(0.3f); -// water.setLocalTranslation(0, 5, 0); +// water.setHighLife(1f); +// water.getParticleInfluencer().setVelocityVariation(0.1f); +// water.setLocalTranslation(0, 6, 0); // rootNode.attachChild(water); } diff --git a/engine/src/test/jme3test/helloworld/HelloJME3.java b/engine/src/test/jme3test/helloworld/HelloJME3.java index 3a0414c9d..d59e73f8e 100644 --- a/engine/src/test/jme3test/helloworld/HelloJME3.java +++ b/engine/src/test/jme3test/helloworld/HelloJME3.java @@ -33,7 +33,6 @@ package jme3test.helloworld; import com.jme3.app.SimpleApplication; -import com.jme3.input.FlyByCamera; import com.jme3.material.Material; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; @@ -47,16 +46,16 @@ public class HelloJME3 extends SimpleApplication { public static void main(String[] args){ HelloJME3 app = new HelloJME3(); - app.start(); // start JME3 + app.start(); // start the game } @Override public void simpleInitApp() { - Box b = new Box(Vector3f.ZERO, 1, 1, 1); // create cube shape + Box b = new Box(Vector3f.ZERO, 1, 1, 1); // create cube shape at the origin Geometry geom = new Geometry("Box", b); // create cube geometry from the shape Material mat = new Material(assetManager, - "Common/MatDefs/Misc/Unshaded.j3md"); // create a simple material - mat.setColor("Color", ColorRGBA.Blue); // set color of material to blue + "Common/MatDefs/Misc/Unshaded.j3md"); // create a simple material + mat.setColor("Color", ColorRGBA.Blue); // set color of material to blue geom.setMaterial(mat); // set the cube's material rootNode.attachChild(geom); // make the cube appear in the scene } diff --git a/engine/src/test/jme3test/helloworld/HelloLoop.java b/engine/src/test/jme3test/helloworld/HelloLoop.java index ec0d5e816..0aa73ddcc 100644 --- a/engine/src/test/jme3test/helloworld/HelloLoop.java +++ b/engine/src/test/jme3test/helloworld/HelloLoop.java @@ -40,7 +40,8 @@ import com.jme3.scene.Geometry; import com.jme3.scene.shape.Box; /** Sample 4 - how to trigger repeating actions from the main event loop. - * In this example, we make the player character rotate. */ + * In this example, you use the loop to make the player character + * rotate continuously. */ public class HelloLoop extends SimpleApplication { public static void main(String[] args){ diff --git a/engine/src/test/jme3test/helloworld/HelloNode.java b/engine/src/test/jme3test/helloworld/HelloNode.java index 4bd853951..0206eb88a 100644 --- a/engine/src/test/jme3test/helloworld/HelloNode.java +++ b/engine/src/test/jme3test/helloworld/HelloNode.java @@ -56,14 +56,16 @@ public class HelloNode extends SimpleApplication { /** create a blue box at coordinates (1,-1,1) */ Box box1 = new Box( new Vector3f(1,-1,1), 1,1,1); Geometry blue = new Geometry("Box", box1); - Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + Material mat1 = new Material(assetManager, + "Common/MatDefs/Misc/Unshaded.j3md"); mat1.setColor("Color", ColorRGBA.Blue); blue.setMaterial(mat1); /** create a red box straight above the blue one at (1,3,1) */ Box box2 = new Box( new Vector3f(1,3,1), 1,1,1); Geometry red = new Geometry("Box", box2); - Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + Material mat2 = new Material(assetManager, + "Common/MatDefs/Misc/Unshaded.j3md"); mat2.setColor("Color", ColorRGBA.Red); red.setMaterial(mat2); @@ -76,8 +78,6 @@ public class HelloNode extends SimpleApplication { pivot.attachChild(red); /** Rotate the pivot node: Note that both boxes have rotated! */ pivot.rotate(.4f,.4f,0f); - - } } diff --git a/engine/src/test/jme3test/helloworld/HelloPhysics.java b/engine/src/test/jme3test/helloworld/HelloPhysics.java index 3c78b114d..7a30cb8cd 100644 --- a/engine/src/test/jme3test/helloworld/HelloPhysics.java +++ b/engine/src/test/jme3test/helloworld/HelloPhysics.java @@ -43,12 +43,10 @@ import com.jme3.input.controls.MouseButtonTrigger; import com.jme3.material.Material; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; -import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.scene.Geometry; import com.jme3.scene.shape.Box; import com.jme3.scene.shape.Sphere; import com.jme3.scene.shape.Sphere.TextureMode; -import com.jme3.shadow.BasicShadowRenderer; import com.jme3.texture.Texture; import com.jme3.texture.Texture.WrapMode; @@ -66,9 +64,6 @@ public class HelloPhysics extends SimpleApplication { /** Prepare the Physics Application State (jBullet) */ private BulletAppState bulletAppState; - /** Activate custom rendering of shadows */ - BasicShadowRenderer bsr; - /** Prepare Materials */ Material wall_mat; Material stone_mat; @@ -104,19 +99,23 @@ public class HelloPhysics extends SimpleApplication { /** Set up Physics Game */ bulletAppState = new BulletAppState(); stateManager.attach(bulletAppState); + //bulletAppState.getPhysicsSpace().enableDebug(assetManager); /** Configure cam to look at scene */ - cam.setLocation(new Vector3f(0, 6f, 6f)); - cam.lookAt(Vector3f.ZERO, new Vector3f(0, 1, 0)); - cam.setFrustumFar(15); - /** Add InputManager action: Left click triggers shooting. */ - inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); - inputManager.addListener(actionListener, "shoot"); - /** Initialize the scene, materials, and physics space */ + cam.setLocation(new Vector3f(0, 4f, 6f)); + cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y); + /** Initialize the scene, materials, inputs, and physics space */ + initInputs(); initMaterials(); initWall(); initFloor(); initCrossHairs(); - initShadows(); + } + + /** Add InputManager action: Left click triggers shooting. */ + private void initInputs() { + inputManager.addMapping("shoot", + new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); + inputManager.addListener(actionListener, "shoot"); } /** @@ -157,7 +156,6 @@ public class HelloPhysics extends SimpleApplication { public void initFloor() { Geometry floor_geo = new Geometry("Floor", floor); floor_geo.setMaterial(floor_mat); - floor_geo.setShadowMode(ShadowMode.Receive); floor_geo.setLocalTranslation(0, -0.1f, 0); this.rootNode.attachChild(floor_geo); /* Make the floor physical with mass 0.0f! */ @@ -171,7 +169,7 @@ public class HelloPhysics extends SimpleApplication { float startpt = brickLength / 4; float height = 0; for (int j = 0; j < 15; j++) { - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 6; i++) { Vector3f vt = new Vector3f(i * brickLength * 2 + startpt, brickHeight + height, 0); makeBrick(vt); @@ -181,24 +179,14 @@ public class HelloPhysics extends SimpleApplication { } } - /** Activate shadow casting and light direction */ - private void initShadows() { - bsr = new BasicShadowRenderer(assetManager, 256); - bsr.setDirection(new Vector3f(-1, -1, -1).normalizeLocal()); - viewPort.addProcessor(bsr); - // Default mode is Off -- Every node declares own shadow mode! - rootNode.setShadowMode(ShadowMode.Off); - } - /** This method creates one individual physical brick. */ public void makeBrick(Vector3f loc) { /** Create a brick geometry and attach to scene graph. */ Geometry brick_geo = new Geometry("brick", box); brick_geo.setMaterial(wall_mat); rootNode.attachChild(brick_geo); - /** Position the brick geometry and activate shadows */ + /** Position the brick geometry */ brick_geo.setLocalTranslation(loc); - brick_geo.setShadowMode(ShadowMode.CastAndReceive); /** Make brick physical with a mass > 0.0f. */ brick_phy = new RigidBodyControl(2f); /** Add physical brick to physics space. */ @@ -214,9 +202,8 @@ public class HelloPhysics extends SimpleApplication { Geometry ball_geo = new Geometry("cannon ball", sphere); ball_geo.setMaterial(stone_mat); rootNode.attachChild(ball_geo); - /** Position the cannon ball and activate shadows */ + /** Position the cannon ball */ ball_geo.setLocalTranslation(cam.getLocation()); - ball_geo.setShadowMode(ShadowMode.CastAndReceive); /** Make the ball physcial with a mass > 0.0f */ ball_phy = new RigidBodyControl(1f); /** Add physical ball to physics space. */ diff --git a/engine/src/test/jme3test/helloworld/HelloPicking.java b/engine/src/test/jme3test/helloworld/HelloPicking.java index 60815e7c6..5881cc0c6 100644 --- a/engine/src/test/jme3test/helloworld/HelloPicking.java +++ b/engine/src/test/jme3test/helloworld/HelloPicking.java @@ -33,7 +33,6 @@ package jme3test.helloworld; import com.jme3.app.SimpleApplication; -import com.jme3.bounding.BoundingBox; import com.jme3.collision.CollisionResult; import com.jme3.collision.CollisionResults; import com.jme3.font.BitmapText; diff --git a/engine/src/test/jme3test/helloworld/HelloTerrain.java b/engine/src/test/jme3test/helloworld/HelloTerrain.java index bffdb58b5..469f79c27 100644 --- a/engine/src/test/jme3test/helloworld/HelloTerrain.java +++ b/engine/src/test/jme3test/helloworld/HelloTerrain.java @@ -38,7 +38,7 @@ import com.jme3.renderer.Camera; import com.jme3.terrain.geomipmap.TerrainLodControl; import com.jme3.terrain.heightmap.AbstractHeightMap; import com.jme3.terrain.geomipmap.TerrainQuad; -import com.jme3.terrain.heightmap.HillHeightMap; +import com.jme3.terrain.heightmap.HillHeightMap; // for exercise 2 import com.jme3.terrain.heightmap.ImageBasedHeightMap; import com.jme3.texture.Texture; import com.jme3.texture.Texture.WrapMode; @@ -61,42 +61,49 @@ public class HelloTerrain extends SimpleApplication { flyCam.setMoveSpeed(50); /** 1. Create terrain material and load four textures into it. */ - mat_terrain = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md"); + mat_terrain = new Material(assetManager, + "Common/MatDefs/Terrain/Terrain.j3md"); /** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */ - mat_terrain.setTexture("Alpha", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png")); + mat_terrain.setTexture("Alpha", assetManager.loadTexture( + "Textures/Terrain/splat/alphamap.png")); /** 1.2) Add GRASS texture into the red layer (Tex1). */ - Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg"); + Texture grass = assetManager.loadTexture( + "Textures/Terrain/splat/grass.jpg"); grass.setWrap(WrapMode.Repeat); mat_terrain.setTexture("Tex1", grass); mat_terrain.setFloat("Tex1Scale", 64f); /** 1.3) Add DIRT texture into the green layer (Tex2) */ - Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg"); + Texture dirt = assetManager.loadTexture( + "Textures/Terrain/splat/dirt.jpg"); dirt.setWrap(WrapMode.Repeat); mat_terrain.setTexture("Tex2", dirt); mat_terrain.setFloat("Tex2Scale", 32f); /** 1.4) Add ROAD texture into the blue layer (Tex3) */ - Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg"); + Texture rock = assetManager.loadTexture( + "Textures/Terrain/splat/road.jpg"); rock.setWrap(WrapMode.Repeat); mat_terrain.setTexture("Tex3", rock); mat_terrain.setFloat("Tex3Scale", 128f); /** 2. Create the height map */ AbstractHeightMap heightmap = null; - Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png"); + Texture heightMapImage = assetManager.loadTexture( + "Textures/Terrain/splat/mountains512.png"); heightmap = new ImageBasedHeightMap( ImageToAwt.convert(heightMapImage.getImage(), false, true, 0)); heightmap.load(); - /** 3. We have prepared material and heightmap. Now we create the actual terrain: - * 3.1) We create a TerrainQuad and name it "my terrain". + /** 3. We have prepared material and heightmap. + * Now we create the actual terrain: + * 3.1) Create a TerrainQuad and name it "my terrain". * 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65. * 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513. * 3.4) As LOD step scale we supply Vector3f(1,1,1). - * 3.5) At last, we supply the prepared heightmap itself. + * 3.5) We supply the prepared heightmap itself. */ terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap()); @@ -111,6 +118,5 @@ public class HelloTerrain extends SimpleApplication { cameras.add(getCamera()); TerrainLodControl control = new TerrainLodControl(terrain, cameras); terrain.addControl(control); - } } diff --git a/engine/src/test/jme3test/helloworld/HelloTerrainCollision.java b/engine/src/test/jme3test/helloworld/HelloTerrainCollision.java new file mode 100644 index 000000000..9986de3c1 --- /dev/null +++ b/engine/src/test/jme3test/helloworld/HelloTerrainCollision.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2009-2010 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.helloworld; + +import com.jme3.app.SimpleApplication; +import com.jme3.bullet.BulletAppState; +import com.jme3.bullet.collision.shapes.CapsuleCollisionShape; +import com.jme3.bullet.collision.shapes.CollisionShape; +import com.jme3.bullet.control.CharacterControl; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.util.CollisionShapeFactory; +import com.jme3.input.KeyInput; +import com.jme3.input.controls.ActionListener; +import com.jme3.input.controls.KeyTrigger; +import com.jme3.material.Material; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.scene.Node; +import com.jme3.terrain.geomipmap.TerrainLodControl; +import com.jme3.terrain.heightmap.AbstractHeightMap; +import com.jme3.terrain.geomipmap.TerrainQuad; +import com.jme3.terrain.heightmap.ImageBasedHeightMap; +import com.jme3.texture.Texture; +import com.jme3.texture.Texture.WrapMode; +import java.util.ArrayList; +import java.util.List; +import jme3tools.converters.ImageToAwt; + +/** + * This demo shows a terrain with collision detection, + * that you can walk around in with a first-person perspective. + * This code combines HelloCollision and HelloTerrain. + */ +public class HelloTerrainCollision extends SimpleApplication + implements ActionListener { + + private BulletAppState bulletAppState; + private RigidBodyControl landscape; + private CharacterControl player; + private Vector3f walkDirection = new Vector3f(); + private boolean left = false, right = false, up = false, down = false; + private TerrainQuad terrain; + private Material mat_terrain; + + public static void main(String[] args) { + HelloTerrainCollision app = new HelloTerrainCollision(); + app.start(); + } + + @Override + public void simpleInitApp() { + /** Set up Physics */ + bulletAppState = new BulletAppState(); + stateManager.attach(bulletAppState); + //bulletAppState.getPhysicsSpace().enableDebug(assetManager); + + flyCam.setMoveSpeed(100); + setUpKeys(); + + /** 1. Create terrain material and load four textures into it. */ + mat_terrain = new Material(assetManager, + "Common/MatDefs/Terrain/Terrain.j3md"); + + /** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */ + mat_terrain.setTexture("Alpha", assetManager.loadTexture( + "Textures/Terrain/splat/alphamap.png")); + + /** 1.2) Add GRASS texture into the red layer (Tex1). */ + Texture grass = assetManager.loadTexture( + "Textures/Terrain/splat/grass.jpg"); + grass.setWrap(WrapMode.Repeat); + mat_terrain.setTexture("Tex1", grass); + mat_terrain.setFloat("Tex1Scale", 64f); + + /** 1.3) Add DIRT texture into the green layer (Tex2) */ + Texture dirt = assetManager.loadTexture( + "Textures/Terrain/splat/dirt.jpg"); + dirt.setWrap(WrapMode.Repeat); + mat_terrain.setTexture("Tex2", dirt); + mat_terrain.setFloat("Tex2Scale", 32f); + + /** 1.4) Add ROAD texture into the blue layer (Tex3) */ + Texture rock = assetManager.loadTexture( + "Textures/Terrain/splat/road.jpg"); + rock.setWrap(WrapMode.Repeat); + mat_terrain.setTexture("Tex3", rock); + mat_terrain.setFloat("Tex3Scale", 128f); + + /** 2. Create the height map */ + AbstractHeightMap heightmap = null; + Texture heightMapImage = assetManager.loadTexture( + "Textures/Terrain/splat/mountains512.png"); + heightmap = new ImageBasedHeightMap( + ImageToAwt.convert(heightMapImage.getImage(), false, true, 0)); + heightmap.load(); + + /** 3. We have prepared material and heightmap. + * Now we create the actual terrain: + * 3.1) Create a TerrainQuad and name it "my terrain". + * 3.2) A good value for terrain tiles is 64x64 -- so we supply 64+1=65. + * 3.3) We prepared a heightmap of size 512x512 -- so we supply 512+1=513. + * 3.4) As LOD step scale we supply Vector3f(1,1,1). + * 3.5) We supply the prepared heightmap itself. + */ + terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap()); + + /** 4. We give the terrain its material, position & scale it, and attach it. */ + terrain.setMaterial(mat_terrain); + terrain.setLocalTranslation(0, -100, 0); + terrain.setLocalScale(2f, 1f, 2f); + rootNode.attachChild(terrain); + + /** 5. The LOD (level of detail) depends on were the camera is: */ + List cameras = new ArrayList(); + cameras.add(getCamera()); + TerrainLodControl control = new TerrainLodControl(terrain, cameras); + terrain.addControl(control); + + /** 6. Add physics: */ + // We set up collision detection for the scene by creating a + // compound collision shape and a static RigidBodyControl with mass zero.*/ + CollisionShape terrainShape = + CollisionShapeFactory.createMeshShape((Node) terrain); + landscape = new RigidBodyControl(terrainShape, 0); + terrain.addControl(landscape); + + // We set up collision detection for the player by creating + // a capsule collision shape and a CharacterControl. + // The CharacterControl offers extra settings for + // size, stepheight, jumping, falling, and gravity. + // We also put the player in its starting position. + CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.5f, 6f, 1); + player = new CharacterControl(capsuleShape, 0.05f); + player.setJumpSpeed(20); + player.setFallSpeed(30); + player.setGravity(30); + player.setPhysicsLocation(new Vector3f(0, 10, 0)); + + // We attach the scene and the player to the rootnode and the physics space, + // to make them appear in the game world. + bulletAppState.getPhysicsSpace().add(terrain); + bulletAppState.getPhysicsSpace().add(player); + + } + /** We over-write some navigational key mappings here, so we can + * add physics-controlled walking and jumping: */ + private void setUpKeys() { + inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A)); + inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D)); + inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_W)); + inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_S)); + inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE)); + inputManager.addListener(this, "Left"); + inputManager.addListener(this, "Right"); + inputManager.addListener(this, "Up"); + inputManager.addListener(this, "Down"); + inputManager.addListener(this, "Jump"); + } + + /** These are our custom actions triggered by key presses. + * We do not walk yet, we just keep track of the direction the user pressed. */ + public void onAction(String binding, boolean value, float tpf) { + if (binding.equals("Left")) { + if (value) { left = true; } else { left = false; } + } else if (binding.equals("Right")) { + if (value) { right = true; } else { right = false; } + } else if (binding.equals("Up")) { + if (value) { up = true; } else { up = false; } + } else if (binding.equals("Down")) { + if (value) { down = true; } else { down = false; } + } else if (binding.equals("Jump")) { + player.jump(); + } + } + + /** + * This is the main event loop--walking happens here. + * We check in which direction the player is walking by interpreting + * the camera direction forward (camDir) and to the side (camLeft). + * The setWalkDirection() command is what lets a physics-controlled player walk. + * We also make sure here that the camera moves with player. + */ + @Override + public void simpleUpdate(float tpf) { + Vector3f camDir = cam.getDirection().clone().multLocal(0.6f); + Vector3f camLeft = cam.getLeft().clone().multLocal(0.4f); + walkDirection.set(0, 0, 0); + if (left) { walkDirection.addLocal(camLeft); } + if (right) { walkDirection.addLocal(camLeft.negate()); } + if (up) { walkDirection.addLocal(camDir); } + if (down) { walkDirection.addLocal(camDir.negate()); } + player.setWalkDirection(walkDirection); + cam.setLocation(player.getPhysicsLocation()); + } +} +