Skip to content

Instantly share code, notes, and snippets.

@skapral
Created March 5, 2019 23:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skapral/73358cfcd4ddf48a132a5119020fece6 to your computer and use it in GitHub Desktop.
Save skapral/73358cfcd4ddf48a132a5119020fece6 to your computer and use it in GitHub Desktop.
public class Main extends SimpleApplication {
public static void main(String[] args){
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp() {
flyCam.setEnabled(false);
assetManager.addClassLoader(Main.class.getClassLoader());
stateManager.attach(new CameraControl(Vector3f.UNIT_Y, Vector3f.UNIT_X, Vector3f.UNIT_Z, 20));
stateManager.attach(new Scene(rootNode));
Arrow arrow = new Arrow(Vector3f.UNIT_X.mult(50));
putShape(arrow, ColorRGBA.Red);
arrow = new Arrow(Vector3f.UNIT_Y.mult(50));
putShape(arrow, ColorRGBA.Blue);
arrow = new Arrow(Vector3f.UNIT_Z.mult(50));
putShape(arrow, ColorRGBA.Green);
}
private Geometry putShape(Mesh shape, ColorRGBA color) {
Geometry g = new Geometry("coordinate axis", shape);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.getAdditionalRenderState().setLineWidth(4);
mat.setColor("Color", color);
g.setMaterial(mat);
rootNode.attachChild(g);
return g;
}
}
public class CameraControl extends AbstractAppState implements AnalogListener, ActionListener {
public static final String NORTH = "CC_N";
public static final String SOUTH = "CC_S";
public static final String WEST = "CC_W";
public static final String EAST = "CC_E";
public static final String UP = "CC_U";
public static final String DOWN = "CC_D";
private final Vector3f north;
private final Vector3f east;
private final Vector3f up;
private final float moveSpeed;
private float frustumSize;
private InputManager inputManager;
private Camera camera;
public CameraControl(Vector3f north, Vector3f east, Vector3f up, float moveSpeed) {
this.north = north;
this.east = east;
this.up = up;
this.moveSpeed = moveSpeed;
}
@Override
public void stateAttached(AppStateManager stateManager) {
super.stateAttached(stateManager);
inputManager = stateManager.getApplication().getInputManager();
camera = stateManager.getApplication().getCamera();
frustumSize = 5;
setupCamera();
setupInputManager();
}
@Override
public void stateDetached(AppStateManager stateManager) {
super.stateDetached(stateManager);
inputManager.removeListener(this);
}
private void setupCamera() {
float aspect = (float) camera.getWidth() / camera.getHeight();
camera.setFrustum(-1000, 1000, -aspect * frustumSize, aspect * frustumSize, frustumSize, -frustumSize);
camera.setParallelProjection(true);
//camera.setLocation(new Vector3f(0f, 200f, 0f));
//camera.lookAt(new Vector3f(0f, 0f, 0f), new Vector3f(0f, 0f, 1f));
camera.setLocation(new Vector3f(0f, 0f, 200f));
camera.lookAt(new Vector3f(0f, 0f, 0f), new Vector3f(0f, 0f, 1f));
}
private void setupInputManager() {
inputManager.addMapping(NORTH, new KeyTrigger(KeyInput.KEY_W));
inputManager.addMapping(SOUTH, new KeyTrigger(KeyInput.KEY_S));
inputManager.addMapping(WEST, new KeyTrigger(KeyInput.KEY_A));
inputManager.addMapping(EAST, new KeyTrigger(KeyInput.KEY_D));
inputManager.addMapping(UP, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
inputManager.addMapping(DOWN, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
inputManager.setCursorVisible(true);
inputManager.addListener(this, new String[]{
NORTH, SOUTH, WEST, EAST, UP, DOWN
});
}
private void moveNorth(float v) {
Vector3f pos = camera.getLocation().clone();
camera.setLocation(pos.addLocal(north.mult(v * moveSpeed * frustumSize)));
}
private void moveEast(float v) {
Vector3f pos = camera.getLocation().clone();
camera.setLocation(pos.addLocal(east.mult(v * moveSpeed * frustumSize)));
}
private void moveUp(float v) {
frustumSize += moveSpeed * v;
frustumSize = frustumSize < 1 ? 1 : frustumSize;
frustumSize = frustumSize > 100 ? 100 : frustumSize;
setupCamera();
}
@Override
public void onAnalog(String name, float value, float tpf) {
System.out.println(name + " " + value + " " + tpf);
switch (name) {
case NORTH: {
moveNorth(value);
break;
}
case SOUTH: {
moveNorth(-value);
break;
}
case WEST: {
moveEast(-value);
break;
}
case EAST: {
moveEast(value);
break;
}
case UP: {
moveUp(value);
break;
}
case DOWN: {
moveUp(-value);
break;
}
default: {
}
}
}
@Override
public void onAction(String name, boolean value, float tpf) {
System.out.println(name + " " + value + " " + tpf);
}
}
public class Scene extends AbstractAppState implements AnalogListener {
public static final String SELECT = "SC_SEL";
public static final String CMD = "SC_CMD";
private Camera camera;
private InputManager inputManager;
private AssetManager assetManager;
private Node sceneNode;
private final Node rootNode;
public Scene(Node rootNode) {
this.rootNode = rootNode;
}
@Override
public void stateAttached(AppStateManager stateManager) {
super.stateAttached(stateManager);
inputManager = stateManager.getApplication().getInputManager();
assetManager = stateManager.getApplication().getAssetManager();
camera = stateManager.getApplication().getCamera();
sceneNode = new Node("Scene");
createTerrain();
rootNode.attachChild(sceneNode);
inputManager.addMapping(SELECT, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addMapping(CMD, new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
inputManager.addListener(this, new String[] { SELECT, CMD });
}
@Override
public void stateDetached(AppStateManager stateManager) {
super.stateDetached(stateManager);
rootNode.detachChild(sceneNode);
inputManager.removeListener(this);
}
@Override
public void onAnalog(String name, float value, float tpf) {
if (name.equals(SELECT)) {
CollisionResults results = new CollisionResults();
Vector2f click2d = inputManager.getCursorPosition();
Vector3f click3d = camera.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).clone();
System.out.println(click3d);
Vector3f dir = camera.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).subtractLocal(click3d).normalizeLocal();
System.out.println(dir);
Ray ray = new Ray(click3d, dir);
sceneNode.collideWith(ray, results);
System.out.println(results.size());
for (int i = 0; i < results.size(); i++) {
// (For each “hit”, we know distance, impact point, geometry.)
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String target = results.getCollision(i).getGeometry().getName();
System.out.println("Selection #" + i + ": " + target + " at " + pt + ", " + dist + " WU away.");
}
}
}
private void createTerrain() {
Material mat_terrain = new Material(assetManager,"Common/MatDefs/Terrain/Terrain.j3md");
mat_terrain.setTexture("Alpha", new Texture2D(generateImage(16, 16)));
Texture grass = assetManager.loadTexture("JME/Textures/grass.jpg");
grass.setWrap(Texture.WrapMode.Repeat);
mat_terrain.setTexture("Tex1", grass);
mat_terrain.setFloat("Tex1Scale", 16f);
Texture dirt = assetManager.loadTexture("JME/Textures/dirt.jpg");
dirt.setWrap(Texture.WrapMode.Repeat);
mat_terrain.setTexture("Tex2", dirt);
mat_terrain.setFloat("Tex2Scale", 16f);
Texture rock = assetManager.loadTexture("JME/Textures/road.jpg");
rock.setWrap(Texture.WrapMode.Repeat);
mat_terrain.setTexture("Tex3", rock);
mat_terrain.setFloat("Tex3Scale", 16f);
HeightMap heightmap = new RawHeightMap(new float[1025]);
TerrainQuad terrain = new TerrainQuad("my terrain", 5, 129, heightmap.getHeightMap());
terrain.rotate(FastMath.HALF_PI, 0, 0);
terrain.setMaterial(mat_terrain);
sceneNode = terrain;
}
private Image generateImage(int width, int height) {
ByteBuffer bb = ByteBuffer.allocateDirect(width*height*4);
bb.position(0);
bb.put(ColorRGBA.Green.asBytesRGBA());
for(int i=4; i < width*height*4; i+=4)
{
ColorRGBA color = i % 8 != 0 ? ColorRGBA.Blue : ColorRGBA.Red;
bb.position(i);
bb.put(color.asBytesRGBA());
}
bb.rewind();
return new Image(Image.Format.RGBA8, width, height, bb, ColorSpace.sRGB);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment