Saturday, March 30, 2013

Warping Three.js Planes

‹prev | My Chain | next›

I think that I am more or less done with material for 3D Game Programming for Kids. While I am reviewing material, I will root through “to be answered later” pile. First up is something that I arguably should have included in the book, but have not found room: Minecraft-like vistas.

The Three.js site already links to a nice demo, but I have not tried to build it myself yet. Actually, the river rafting game that will go into the last chapter uses techniques that are similar to what should work for Minecraft terrain, but I am not sure.

Being unsure is terrain ripe for learning so...

I build a simple plane:
  var ground = new THREE.Mesh(
    new THREE.PlaneGeometry(10000, 10000, 100, 100),
    new THREE.MeshNormalMaterial()
  );
  ground.rotation.x = -Math.PI/2;
  ground.position.y = -170;
Next I work through each vertex in the plane and push it up depending on how far from the center of the plane each vertex is. In the end, this should build three step in my plane:

  for (var i=0; i<ground.geometry.vertices.length; i++) {
    vertex = ground.geometry.vertices[i];
    if (Math.abs(vertex.x) > 1500 || Math.abs(vertex.y) > 1500) {
      ground.geometry.vertices[i].z = 500;
    }
    if (Math.abs(vertex.x) > 2000 || Math.abs(vertex.y) > 2000) {
      ground.geometry.vertices[i].z = 1000;
    }
    if (Math.abs(vertex.x) > 2500 || Math.abs(vertex.y) > 2500) {
      ground.geometry.vertices[i].z = 1500;
    }
  }
  ground.geometry.computeFaceNormals();
  ground.geometry.computeVertexNormals();

This results in:



That's close, but the sides look to be slanted. This may be partially due to my used of a perspective camera, but I am pretty sure that the slant is real. To get rid of the slant, I think that, in addition to moving the vertices up, I will need to move them back. Only that does not work. The vertices placement seems to go all wonky.

I break this down into larger chunks so that I dealing with fewer faces (a simpler case):
  var ground = new THREE.Mesh(
    new THREE.PlaneGeometry(10000, 10000, 10, 10),
    new THREE.MeshNormalMaterial()
  );
  ground.rotation.x = -Math.PI/2;
  ground.position.y = -170;
  for (var i=0; i<ground.geometry.vertices.length; i++) {
    vertex = ground.geometry.vertices[i];
    if (Math.abs(vertex.x) > 1500 || Math.abs(vertex.y) > 1500) {
      vertex.z = 500;
    }
  }
Take a bird's eye view of this, I spy:



Ah, I think that the corners are looking problematic. And, indeed, when I try to move the step back in to prevent the slant:
  var ground = new THREE.Mesh(
    new THREE.PlaneGeometry(10000, 10000, 10, 10),
    new THREE.MeshNormalMaterial()
  );
  ground.rotation.x = -Math.PI/2;
  ground.position.y = -170;
  for (var i=0; i<ground.geometry.vertices.length; i++) {
    vertex = ground.geometry.vertices[i];
    if (Math.abs(vertex.x) > 1500 || Math.abs(vertex.y) > 1500) {
      vertex.z = 500;
      if (vertex.y > 0 && vertex.y - 1500 <=  1000) vertex.y -= 1000;
      else if (vertex.y < 0 && vertex.y + 1500 >= -1000) vertex.y += 1000;
      if (vertex.x > 0 && vertex.x - 1500 <=  1000) vertex.x -= 1000;
      else if (vertex.x < 0 && vertex.x + 1500 >= -1000) vertex.x += 1000;
    }
  }
Then I end up with all kinds of crazy faces:



Ugh. This may not be possible, which might explain why the the Three.js Minecraft demo uses boxes assembled from individual sides to build up the scene. Pity, that approach would have lent itself nicely for later discussion.

Day #707

No comments:

Post a Comment