Saturday, July 28, 2012

River in Three.js

‹prev | My Chain | next›

As of last night, I have my sample avatar island, written in Three.js, all set up with an invisible fence keeping my avatar on the island:


Just to make sure I really understand this stuff, I am going to add a river running through the island that my avatar is also prevented from crossing. To start with, I switch my intersectObject() (singular) collision detection with the plural intersectObjects():
function detectCollision() {
  var x, z;
  if (controls.moveLeft) z = 1;
  if (controls.moveRight) z = -1;
  if (controls.moveBackward) x = 1;
  if (controls.moveForward) x = -1;

  var vector = new THREE.Vector3( x, 0, z );
  var ray = new THREE.Ray(controls.object.position, vector);
  var intersects = ray.intersectObjects(blockers);

  if (intersects.length > 0) {
    if (intersects[0].distance < 75) {
      if (controls.moveLeft) controls.moveLeft = false;
      if (controls.moveRight) controls.moveRight = false;
      if (controls.moveBackward) controls.moveBackward = false;
      if (controls.moveForward) controls.moveForward = false;
    }
  }
}
Instead of checking for the intersection of a single object like last night, I am now checking for an array of blockers.

Now I need a river:
function river() {
  var river = new THREE.Object3D()
    , riverMaterial = new THREE.MeshBasicMaterial({color: 0x483D8B})
    , wallMaterial = new THREE.MeshBasicMaterial()
    , width = 400;

  // actual river here...
}
I am going to build this as two separate pieces: the top and bottom. A small gap between the two segments will serve as a natural bridge over which the avatar can walk. The top segment is then:
  var top = new THREE.Object3D();

  waterShape = new THREE.PlaneGeometry(ISLAND_WIDTH/2, width);
  water = new THREE.Mesh(waterShape, riverMaterial);
  wallShape = new THREE.CubeGeometry(ISLAND_WIDTH/2, 10000, width);
  wall = new THREE.Mesh(wallShape, wallMaterial);
  wall.visible = false;
  top.add(water);
  top.add(wall);
  top.position.x = -ISLAND_WIDTH/3;
  top.position.z = ISLAND_WIDTH/4;

  // list of water that blocks avatar
  blockers.push(wall);

  river.add(top);
Here, I create two shapes, the visible blue water and the invisible wall. Both are half the distance of the entire island long and width (400) units wide. The wall is also 10,000 pixels tall, which should prevent the avatar from getting over without a really tall ladder.

Both the wall and the water are added to the top segment, placed to the left and top of the island and added to the river object. I also add the wall to the list of objects that will block the avatar.

After doing the same for the bottom segment, but shifting the X position accordingly, I have my river:


I am prevent from crossing the river, but I am, indeed, able to cross the "natural bridge":


It would be nice to be able to build the river planar object based on the intersection of the wall and the island (which is also a plane). This would make for an easy way to build arbitrary barrier shapes that project visibly onto the ground. Alas, there does not seem to be an easy way to do this.


Day #461

No comments:

Post a Comment