Overpass APIとthree.jsで地図を3D表示(2)

公開:2017-04-23 21:59
更新:2017-07-29 13:18
カテゴリ:three.js,overpass api,シューティングゲーム,overpass apiとthree.jsで地図を3d表示

スカイボックスを追加し、ビルにテクスチャを貼り付けてみた。リアルとは言えないが、雰囲気は出てきた。

大きい範囲を描画しようとすると相当に処理が重い。最適化しないといかんかな。。まあでも縦スクロールシューティングではかなり狭い範囲を描画するので、パフォーマンス的にはそんなに問題にはならなそうだが。

屋根の面には屋根用のテクスチャを貼らないといけないんだけど、どうやればいいかまだわかっていない。テクスチャの貼り方にはさらに工夫が必要だ。

デモ:(相当処理が重いので注意

https://bl.ocks.org/sfpgmr/raw/2aa0191626e975fbe7143a6b123c21e2/

ソースコード&デモ:(相当処理が重いので注意

https://bl.ocks.org/sfpgmr/2aa0191626e975fbe7143a6b123c21e2

ちょっとはまったのは、ShapeExtrudeGeometryで立体化しているのだけれども、ExtrudeGeometryで作成されたジオメトリに普通にテクスチャを貼り付けようとしてもできないというところ。

このことはThree.jsのISSUEにも載っていた。

https://github.com/mrdoob/three.js/issues/1824

回避策としては、UVGeneratorにBoundingUVGeneratorをセットしてExtrudeGeometryする。だがこの記事で載っているBoundingUVGeneratorは最新バージョンでは動作しないので、改良版を作った。


class BoundingUVGenerator {
  constructor(extrudedShape, extrudedOptions) {
    this.extrudedShape = extrudedShape;
    this.bb = new THREE.Box2();

    this.bb.setFromPoints(this.extrudedShape.extractAllPoints().shape);
    this.extrudedOptions = extrudedOptions;
  }
  generateTopUV(geometry, indexA, indexB, indexC) {
    var ax = geometry.vertices[indexA].x,
      ay = geometry.vertices[indexA].y,

      bx = geometry.vertices[indexB].x,
      by = geometry.vertices[indexB].y,

      cx = geometry.vertices[indexC].x,
      cy = geometry.vertices[indexC].y,

      bb = this.bb,//extrudedShape.getBoundingBox(),
      bbx = bb.max.x - bb.min.x,
      bby = bb.max.y - bb.min.y;

    return [
      new THREE.Vector2((ax - bb.min.x) / bbx, 1 - (ay - bb.min.y) / bby),
      new THREE.Vector2((bx - bb.min.x) / bbx, 1 - (by - bb.min.y) / bby),
      new THREE.Vector2((cx - bb.min.x) / bbx, 1 - (cy - bb.min.y) / bby)
    ];
  }

  generateBottomUV(geometry, indexA, indexB, indexC) {
    return this.generateTopUV(geometry, indexA, indexB, indexC);
  }

  generateSideWallUV(geometry, indexA, indexB, indexC, indexD) {
    var ax = geometry.vertices[indexA].x,
      ay = geometry.vertices[indexA].y,
      az = geometry.vertices[indexA].z,

      bx = geometry.vertices[indexB].x,
      by = geometry.vertices[indexB].y,
      bz = geometry.vertices[indexB].z,

      cx = geometry.vertices[indexC].x,
      cy = geometry.vertices[indexC].y,
      cz = geometry.vertices[indexC].z,

      dx = geometry.vertices[indexD].x,
      dy = geometry.vertices[indexD].y,
      dz = geometry.vertices[indexD].z;

    var amt = this.extrudedOptions.amount,
      bb = this.bb,//extrudedShape.getBoundingBox(),
      bbx = bb.max.x - bb.min.x,
      bby = bb.max.y - bb.min.y;

    if (Math.abs(ay - by) < 0.01) {
      return [
        new THREE.Vector2(ax / bbx, az / amt),
        new THREE.Vector2(bx / bbx, bz / amt),
        new THREE.Vector2(cx / bbx, cz / amt),
        new THREE.Vector2(dx / bbx, dz / amt)
      ];
    } else {
      return [
        new THREE.Vector2(ay / bby, az / amt),
        new THREE.Vector2(by / bby, bz / amt),
        new THREE.Vector2(cy / bby, cz / amt),
        new THREE.Vector2(dy / bby, dz / amt)
      ];
    }
  }
};