Player Collision on a TerrainGrid

Hi! I am fairly new to jMonkey, so please forgive my ignorance.



I was wondering how to make it so that my player collides with the terrain grid, which is being procedurally generated.

Here is the code that I am using, from this location: http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/test/jme3test/terrain/TerrainFractalGridTest.java



[java]mport com.bulletphysics.collision.broadphase.Dbvt.Node;

import com.bulletphysics.collision.shapes.CollisionShape;

import com.jme3.app.SimpleApplication;

import com.jme3.app.state.ScreenshotAppState;

import com.jme3.bullet.BulletAppState;

import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;

import com.jme3.bullet.control.CharacterControl;

import com.jme3.bullet.control.RigidBodyControl;

import com.jme3.bullet.util.CollisionShapeFactory;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.terrain.geomipmap.TerrainGrid;

import com.jme3.terrain.geomipmap.TerrainGridLodControl;

import com.jme3.terrain.geomipmap.TerrainLodControl;

import com.jme3.terrain.geomipmap.grid.FractalTileLoader;

import com.jme3.terrain.geomipmap.lodcalc.DistanceLodCalculator;

import com.jme3.terrain.noise.ShaderUtils;

import com.jme3.terrain.noise.basis.FilteredBasis;

import com.jme3.terrain.noise.filter.IterativeFilter;

import com.jme3.terrain.noise.filter.OptimizedErode;

import com.jme3.terrain.noise.filter.PerturbFilter;

import com.jme3.terrain.noise.filter.SmoothFilter;

import com.jme3.terrain.noise.fractal.FractalSum;

import com.jme3.terrain.noise.modulator.NoiseModulator;

import com.jme3.texture.Texture;

import com.jme3.texture.Texture.WrapMode;



public class Main extends SimpleApplication {



private Material mat_terrain;

private TerrainGrid terrain;

private float grassScale = 64;

private float dirtScale = 16;

private float rockScale = 128;



private BulletAppState bulletAppState;

private CharacterControl player;

private RigidBodyControl landscape;

private Vector3f walkDirection = new Vector3f();

private boolean left = false, right = false, up = false, down = false;



public static void main(final String[] args) {

Main app = new Main();

app.start();

}

private CharacterControl player3;

private FractalSum base;

private PerturbFilter perturb;

private OptimizedErode therm;

private SmoothFilter smooth;

private IterativeFilter iterate;



@Override

public void simpleInitApp() {

this.flyCam.setMoveSpeed(100f);

ScreenshotAppState state = new ScreenshotAppState();

this.stateManager.attach(state);



bulletAppState = new BulletAppState();

stateManager.attach(bulletAppState);



// TERRAIN TEXTURE material

this.mat_terrain = new Material(this.assetManager, “Common/MatDefs/Terrain/HeightBasedTerrain.j3md”);



// Parameters to material:

// regionXColorMap: X = 1…4 the texture that should be appliad to state X

// regionX: a Vector3f containing the following information:

// regionX.x: the start height of the region

// regionX.y: the end height of the region

// regionX.z: the texture scale for the region

// it might not be the most elegant way for storing these 3 values, but it packs the data nicely :slight_smile:

// slopeColorMap: the texture to be used for cliffs, and steep mountain sites

// slopeTileFactor: the texture scale for slopes

// terrainSize: the total size of the terrain (used for scaling the texture)

// GRASS texture

Texture grass = this.assetManager.loadTexture(“Textures/Terrain/splat/grass.jpg”);

grass.setWrap(WrapMode.Repeat);

this.mat_terrain.setTexture(“region1ColorMap”, grass);

this.mat_terrain.setVector3(“region1”, new Vector3f(15, 200, this.grassScale));



// DIRT texture

Texture dirt = this.assetManager.loadTexture(“Textures/Terrain/splat/dirt.jpg”);

dirt.setWrap(WrapMode.Repeat);

this.mat_terrain.setTexture(“region2ColorMap”, dirt);

this.mat_terrain.setVector3(“region2”, new Vector3f(0, 20, this.dirtScale));



// ROCK texture

Texture rock = this.assetManager.loadTexture(“Textures/Terrain/Rock2/rock.jpg”);

rock.setWrap(WrapMode.Repeat);

this.mat_terrain.setTexture(“region3ColorMap”, rock);

this.mat_terrain.setVector3(“region3”, new Vector3f(198, 260, this.rockScale));



this.mat_terrain.setTexture(“region4ColorMap”, rock);

this.mat_terrain.setVector3(“region4”, new Vector3f(198, 260, this.rockScale));



this.mat_terrain.setTexture(“slopeColorMap”, rock);

this.mat_terrain.setFloat(“slopeTileFactor”, 32);



this.mat_terrain.setFloat(“terrainSize”, 513);



this.base = new FractalSum();

this.base.setRoughness(0.7f);

this.base.setFrequency(1.0f);

this.base.setAmplitude(1.0f);

this.base.setLacunarity(2.12f);

this.base.setOctaves(8);

this.base.setScale(0.02125f);

this.base.addModulator(new NoiseModulator() {



@Override

public float value(float… in) {

return ShaderUtils.clamp(in[0] * 0.5f + 0.5f, 0, 1);

}

});



FilteredBasis ground = new FilteredBasis(this.base);



this.perturb = new PerturbFilter();

this.perturb.setMagnitude(0.119f);



this.therm = new OptimizedErode();

this.therm.setRadius(5);

this.therm.setTalus(0.011f);



this.smooth = new SmoothFilter();

this.smooth.setRadius(1);

this.smooth.setEffect(0.7f);



this.iterate = new IterativeFilter();

this.iterate.addPreFilter(this.perturb);

this.iterate.addPostFilter(this.smooth);

this.iterate.setFilter(this.therm);

this.iterate.setIterations(1);



ground.addPreFilter(this.iterate);



this.terrain = new TerrainGrid(“terrain”, 33, 129, new FractalTileLoader(ground, 256f));



this.terrain.setMaterial(this.mat_terrain);

this.terrain.setLocalTranslation(0, 0, 0);

this.terrain.setLocalScale(2f, 1f, 2f);

this.rootNode.attachChild(this.terrain);



TerrainLodControl control = new TerrainGridLodControl(this.terrain, this.getCamera());

control.setLodCalculator(new DistanceLodCalculator(33, 2.7f)); // patch size, and a multiplier

this.terrain.addControl(control);



// 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(-10, 10, 10));



// 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);



this.getCamera().setLocation(new Vector3f(0, 300, 0));



this.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));





}



@Override

public void simpleUpdate(final float tpf) {

}

}[/java]



I couldn’t use the method described in the Wiki’s Terrain collision tutorial, and I couldn’t figure out a different way.

Any help would be really great.



Thanks in advance!

I never see you attach a RigidBodyControl to the terrain?

Just do

[java]RigidBodyControl control = new RigidBodyControl(0);

terrain.addControl(control);

physicsSpace.add(control);[/java]

TerrainGridTest.java is hooked up with physics and terrain, so you can use the physics code from that and just generate the terrain procedurally, taking code from TerrainFractalGridTest.

1 Like
@Sploreg said:
TerrainGridTest.java is hooked up with physics and terrain, so you can use the physics code from that and just generate the terrain procedurally, taking code from TerrainFractalGridTest.


Thanks! This solution worked for me!