add a shader based 3d implementation of conways game of life to the ground, that interacts with the player, pushing the player up, and sideways. Allow the player object to interact with this infinitely. 

class Ground
{
  PVector pos;
  PShape ground;
  PImage tex;
  float w, h, d;
  
  Ground()
  {
    w = 50;
    d = 50;
    pos = new PVector(0, 0, 0);
    tex = loadImage("grid.png");
    textureMode(NORMAL);
    //ground = createShape();
    ground = createShape();
    ground.beginShape(QUADS);
    ground.texture(tex);
    ground.vertex(-w * 0.5, 0, -d * 0.5, 0, 0);
    ground.vertex(w * 0.5, 0, -d * 0.5, 0, w * 0.1);
    ground.vertex(w * 0.5, 0, d * 0.5, w * 0.1, w * 0.1);
    ground.vertex(-w * 0.5, 0, d * 0.5, w * 0.1, 0);
    ground.vertex(-w * 0.5, 0, -d * 0.5, 0, 0);
    ground.endShape();
  }
  
  void update() {}
  void draw()
  {
    pushMatrix();
    translate(pos.x, pos.y, pos.z);
    textureWrap(REPEAT);
    shape(ground);
    popMatrix();
    

  }
}


class Camera
{
  PVector eye, center, up;
  
  Camera()
  {
    eye = new PVector(0, -5, 10);
    center = new PVector(0, 0, 0);
    up = new PVector(0, 1, 0);
    perspective(PI/3.0, 16.0 / 9.0, 5, 1000);
  }
  
  void draw()
  {
    camera(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z);
  }
}


class Input
{
  // Keys
  int[] keys = new int[9];
  
  void keyPressed()
  {
    if (key == 'a' || key == 'A') { keys[0] = 1; }
    else if (key == 'd' || key == 'D') { keys[1] = 1; }
    else if (key == 'w' || key == 'W') { keys[2] = 1; }
    else if (key == 's' || key == 'S') { keys[3] = 1; }
    else if (key == ' ') { keys[4] = 1; }
  }
  
  void keyReleased()
  {
    if (key == 'a' || key == 'A') { keys[0] = 0; }
    else if (key == 'd' || key == 'D') { keys[1] = 0; }
    else if (key == 'w' || key == 'W') { keys[2] = 0; }
    else if (key == 's' || key == 'S') { keys[3] = 0; }
    else if (key == ' ') { keys[4] = 0; }
  }
  
  // Move inputs
  int getMoveLeft() { return keys[0]; }
  int getMoveRight() { return keys[1]; }
  int getMoveForward() { return keys[2]; }
  int getMoveBackward() { return keys[3]; }
  int getActionJump() { return keys[4]; }
}


import java.awt.*;

Input input;
Camera cam;
Player p;
Ground g;
Robot r;

void keyPressed()
{
  input.keyPressed();
}

void keyReleased()
{
  input.keyReleased();
}

void mouseMoved()
{
  p.mouseMovedAndDragged();
}

void mouseDragged()
{
  p.mouseMovedAndDragged();
}

void setup()
{
  // Init game
  fullScreen(P3D);
  noCursor();
  
  // Init objects
  input = new Input();
  cam = new Camera();
  p = new Player();
  g = new Ground();
  try {
  r = new Robot();
  }
  catch (AWTException e)
  {
    e.printStackTrace();
  }
}

void draw()
{
  // UPDATE
  p.update();
  
  // DRAW
  background(0);
  cam.draw();
  g.draw();
  p.draw();
  
  // DRAW GUI
  hint(DISABLE_DEPTH_TEST);
  camera();
  noLights();
  p.drawGui();
  hint(ENABLE_DEPTH_TEST);
}

class Player
{
  PShape hand;
  PImage tex;
  PVector pos, hVel, hDir, vDir;
  float yVel, jumpStrength, moveSpeed;
  float w, h, d;
  float camMinDist;
  float gravStrength;
  
  Player()
  {
    // Dimensions
    w = 2;
    h = 2;
    d = 2;
    
    // Movement
    pos = new PVector(0, 0, 0);
    hVel = new PVector(0, 0);
    yVel = 0;
    moveSpeed = 0.6;
    jumpStrength = 0.3;
    
    // Camera
    hDir = new PVector(0, 1);
    vDir = new PVector(0.7, -0.7);
    camMinDist = 20;
    
    // World
    gravStrength = 0.01;
    
    // Model
    hand = loadShape("hand.obj");
    hand.setFill(color(255));
    //tex = loadImage("grid.png");
    //hand.setTexture(tex);
  }
  
  void mouseMovedAndDragged()
  {
    // Rotate horizontally
    if (pmouseX == int(width * 0.5)) { hDir.rotate((mouseX - pmouseX) * 0.003); }
    
    // Rotate vertically
    if (pmouseY == int(height * 0.5))
    {
      // Clamp rotation
      float currAngle = vDir.heading();
      float goalDir = (mouseY - pmouseY) * 0.003;
      if ((goalDir > 0 && currAngle + goalDir < -0.2) || (goalDir < 0 && currAngle + goalDir > -1.3)) { vDir.rotate(goalDir); }
    }
    
    // Move mouse back to center
    r.mouseMove(int(width * 0.5), int(height * 0.5));
  }
  
  boolean checkOnGround()
  {
    if (pos.y >= 0) { return true; }
    return false;
  }
  
  void update()
  {
    // Movement
    hVel.x = 0;
    hVel.y = 0;
    if (input.getMoveForward() == 1)
    {
      hVel.x -= hDir.x;
      hVel.y -= hDir.y;
    }
    if (input.getMoveBackward() == 1)
    {
      hVel.x += hDir.x;
      hVel.y += hDir.y;
    }
    if (input.getMoveLeft() == 1)
    {
      hDir.rotate(PI * 0.5);
      hVel.x += hDir.x;
      hVel.y += hDir.y;
      hDir.rotate(-PI * 0.5);
    }
    if (input.getMoveRight() == 1)
    {
      hDir.rotate(-PI * 0.5);
      hVel.x += hDir.x;
      hVel.y += hDir.y;
      hDir.rotate(PI * 0.5);
    }
    hVel.mult(moveSpeed);
    //hVel.normalize();
    
    // Ground check
    if (checkOnGround())
    {
      // Jump check
      if (input.getActionJump() == 1)
      {
        // Jump
        yVel = -jumpStrength;
        println(yVel);
      }
    }
    // Gravity
    else
    {
      yVel += gravStrength;
      if (pos.y + yVel >= 0)
      {
        // Land
        yVel = 0;
        pos.y = 0;
      }
    }
    
    // Position
    pos.add(hVel.x, yVel, hVel.y);
    
    // Camera movement
    cam.eye.x = pos.x;
    cam.eye.z = pos.z;
    cam.eye.y = pos.y;
    cam.center.x = pos.x;
    cam.center.y = pos.y;
    cam.center.z = pos.z;
    
    // Camera rotation
    cam.eye.x += hDir.x * camMinDist;
    cam.eye.y -= vDir.x * camMinDist;
    cam.eye.z += hDir.y * camMinDist;
  }
  
  void draw()
  {
    // Model
    pushMatrix();
    translate(pos.x, pos.y - h * 0.5, pos.z);
    rotateX(-PI * 0.5);
    rotateZ(-hDir.heading() + PI * 0.5);
    rotateY(-PI * 0.5);
    shape(hand);
    popMatrix();
    
    // Collision box
    pushMatrix();
    translate(pos.x, pos.y - h * 0.5, pos.z);
    noFill();
    stroke(255);
    box(w, h, d);
    stroke(0);
    fill(255);
    popMatrix();
  }
  
  void drawGui()
  {
    fill(255);
    textSize(32);
    textAlign(LEFT, TOP);
    text("Pos: (" + int(pos.x) + ", " + int(pos.y) + ", " + int(pos.z) + ")", 0, 0);
  }
}