Why not try the Shapes3D library. The following code uses this library and is fairly self explanatory.
Code:/*
To move
w = forward s = stop x = slow down/revrse
Travel direction and tilt is determind by the
mouse position
*/
import processing.opengl.*;
import shapes3d.utils.*;
import shapes3d.*;
Terrain terrain;
Box[] boxes;
TerrainCam cam;
long time;
final int NBRBOXES = 15;
// terrain data
float terrainSize = 1000;
float horizon = 1000;
// Camera data
float camSpeed;
int camHoversAt = 6;
float camTurnBy;
float camTilt;
final float camMinSpeed = -10;
final float camMaxSpeed = 50;
// Mouse sensitivity
final int deadZoneX = 4, deadZoneY = 3;
final float mouseXfactor = 1.8f, mouseYfactor = 1.1f;
void setup(){
size(400,320, OPENGL);
cursor(CROSS);
terrain = new Terrain(this, 60, terrainSize, horizon);
terrain.drawMode(Shape3D.WIRE);
terrain.stroke(color(255,255,0));
terrain.strokeWeight(1.25);
terrain.tag = "Ground";
terrain.tagNo = -1;
boxes = new Box[NBRBOXES];
for(int i = 0; i < NBRBOXES; i++){
float size = random(20,40);
boxes[i] = new Box(this, 10,size,10);
boxes[i].fill(color(random(50,70),random(160,255),random(50,70)));
boxes[i].drawMode(Shape3D.SOLID);
PVector pos = getRandomPosOnTerrain(terrain, terrainSize, size/2);
boxes[i].moveTo(pos);
terrain.addShape(boxes[i]);
}
camSpeed = 10;
cam = new TerrainCam(this);
cam.adjustToTerrain(terrain, Terrain.WRAP, camHoversAt);
cam.camera();
cam.speed(camSpeed);
cam.forward.set(cam.lookDir);
// Tell the terrain what camera to use
terrain.cam = cam;
time = millis();
}
void draw(){
background(32);
ambientLight(220, 220, 220);
directionalLight(255,255,255,-100,-200,200);
// Get elapsed time
long t = millis() - time;
time = millis();
float esecs = t/1000.0;
// Update camera speed and direction
updateCamera(esecs);
// Set the camera view before drawing
cam.camera();
// Draw the terrain
terrain.draw();
}
void updateCamera(float secs){
// Update camera speed and direction
if(keyPressed){
if(key == 'w' || key =='W'){
camSpeed += (secs*10);
}
else if(key == 'x' || key =='X'){
camSpeed -= (secs*10);
}
else if(key == 's' || key =='S'){
camSpeed = 0;
}
}
camSpeed = constrain(camSpeed, camMinSpeed, camMaxSpeed);
cam.speed(camSpeed);
// Change direction and tilt
camTurnBy = 0;
if(mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height){
if(abs(mouseX - width/2) > deadZoneX){
int deltaX = abs(mouseX - width/2) - deadZoneX;
camTurnBy = mouseXfactor * deltaX * secs / (width * HALF_PI);
if(mouseX < width/2)
camTurnBy *= -1;
}
if(abs(mouseY - height/2) > deadZoneY){
int deltaY = abs(mouseY - height/2) - deadZoneY;
camTilt = mouseYfactor * deltaY / (height * HALF_PI);
if(mouseY < height/2)
camTilt *= -1;
cam.lookDir.y = camTilt;
cam.lookDir.normalize();
}
cam.rotateViewBy(camTurnBy);
cam.turnBy(camTurnBy);
}
// Calculate amount of movement based on velocity and time
cam.move(secs);
// Adjust the cameras position so we are over the terrain
// at the given height.
cam.adjustToTerrain(terrain, Terrain.WRAP, camHoversAt);
}
/**
* Get a random position on the terrain avoiding the edges
* @param t the terrain
* @param tsize the size of the terrain
* @param height height above terrain
* @return
*/
PVector getRandomPosOnTerrain(Terrain t, float tsize, float height){
PVector p = new PVector(random(-tsize/2.1f, tsize/2.1f), 0, random(-tsize/2.1f, tsize/2.1f));
p.y = t.getHeight(p.x, p.z) - height;
return p;
}