"use strict";

var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = computeBuffers;
var THREE = _interopRequireWildcard(require("three"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function computeBuffers(params) {
  // Create output buffers.
  var outBuffers = {
    index: null,
    position: null,
    normal: null,
    // 2 UV set per tile: wgs84 (uv_0) and pm (uv_1)
    //    - wgs84: 1 texture per tile because tiles are using wgs84 projection
    //    - pm: use multiple textures per tile.
    //      +-------------------------+
    //      |                         |
    //      |     Texture 0           |
    //      +-------------------------+
    //      |                         |
    //      |     Texture 1           |
    //      +-------------------------+
    //      |                         |
    //      |     Texture 2           |
    //      +-------------------------+
    //        * u = wgs84.u
    //        * v = textureid + v in builder texture
    uvs: []
  };
  var computeUvs = [];
  var builder = params.builder;
  var nSeg = params.segment || 8;
  // segments count :
  // Tile : (nSeg + 1) * (nSeg + 1)
  // Skirt : 8 * (nSeg - 1)
  var nVertex = (nSeg + 1) * (nSeg + 1) + (params.disableSkirt ? 0 : 4 * nSeg);
  if (nVertex > Math.pow(2, 32)) {
    throw new Error('Tile segments count is too big');
  }
  var triangles = nSeg * nSeg * 2 + (params.disableSkirt ? 0 : 4 * nSeg * 2);
  outBuffers.position = new Float32Array(nVertex * 3);
  outBuffers.normal = new Float32Array(nVertex * 3);
  var uvCount = params.builder.uvCount;
  if (uvCount > 1) {
    outBuffers.uvs[1] = new Float32Array(nVertex);
  }
  computeUvs[0] = function () {};
  if (params.buildIndexAndUv_0) {
    if (nVertex < Math.pow(2, 8)) {
      outBuffers.index = new Uint8Array(triangles * 3);
    } else if (nVertex < Math.pow(2, 16)) {
      outBuffers.index = new Uint16Array(triangles * 3);
    } else if (nVertex < Math.pow(2, 32)) {
      outBuffers.index = new Uint32Array(triangles * 3);
    }
    outBuffers.uvs[0] = new Float32Array(nVertex * 2);
    computeUvs[0] = function (id, u, v) {
      outBuffers.uvs[0][id * 2 + 0] = u;
      outBuffers.uvs[0][id * 2 + 1] = v;
    };
  }
  var widthSegments = Math.max(2, Math.floor(nSeg) || 2);
  var heightSegments = Math.max(2, Math.floor(nSeg) || 2);
  var idVertex = 0;
  var vertices = [];
  var skirt = [];
  var skirtEnd = [];
  builder.prepare(params);
  var _loop = function _loop() {
    var verticesRow = [];
    var v = y / heightSegments;
    builder.vProjecte(v, params);
    if (uvCount > 1) {
      var u = builder.computeUvs[1](params);
      computeUvs[1] = function (id) {
        outBuffers.uvs[1][id] = u;
      };
    }
    for (var _x = 0; _x <= widthSegments; _x++) {
      var _u = _x / widthSegments;
      var _id_m = idVertex * 3;
      builder.uProjecte(_u, params);
      var vertex = builder.vertexPosition(params, params.projected);
      var normal = builder.vertexNormal(params);

      // move geometry to center world
      vertex.sub(params.center);

      // align normal to z axis
      if (params.quatNormalToZ) {
        vertex.applyQuaternion(params.quatNormalToZ);
        normal.applyQuaternion(params.quatNormalToZ);
      }
      vertex.toArray(outBuffers.position, _id_m);
      normal.toArray(outBuffers.normal, _id_m);
      for (var _i = 0, _computeUvs = computeUvs; _i < _computeUvs.length; _i++) {
        var computeUv = _computeUvs[_i];
        computeUv(idVertex, _u, v);
      }
      if (!params.disableSkirt) {
        if (y !== 0 && y !== heightSegments) {
          if (_x === widthSegments) {
            skirt.push(idVertex);
          } else if (_x === 0) {
            skirtEnd.push(idVertex);
          }
        }
      }
      verticesRow.push(idVertex);
      idVertex++;
    }
    vertices.push(verticesRow);
    if (y === 0) {
      skirt = skirt.concat(verticesRow);
    } else if (y === heightSegments) {
      skirt = skirt.concat(verticesRow.slice().reverse());
    }
  };
  for (var y = 0; y <= heightSegments; y++) {
    _loop();
  }
  if (!params.disableSkirt) {
    skirt = skirt.concat(skirtEnd.reverse());
  }
  function bufferize(va, vb, vc, idVertex) {
    outBuffers.index[idVertex + 0] = va;
    outBuffers.index[idVertex + 1] = vb;
    outBuffers.index[idVertex + 2] = vc;
    return idVertex + 3;
  }
  var idVertex2 = 0;
  if (params.buildIndexAndUv_0) {
    for (var _y = 0; _y < heightSegments; _y++) {
      for (var x = 0; x < widthSegments; x++) {
        var v1 = vertices[_y][x + 1];
        var v2 = vertices[_y][x];
        var v3 = vertices[_y + 1][x];
        var v4 = vertices[_y + 1][x + 1];
        idVertex2 = bufferize(v4, v2, v1, idVertex2);
        idVertex2 = bufferize(v4, v3, v2, idVertex2);
      }
    }
  }
  var iStart = idVertex;

  // TODO: WARNING beware skirt's size influences performance
  // The size of the skirt is now a ratio of the size of the tile.
  // To be perfect it should depend on the real elevation delta but too heavy to compute
  if (!params.disableSkirt) {
    // We compute the actual size of tile segment to use later for the skirt.
    var segmentSize = new THREE.Vector3().fromArray(outBuffers.position).distanceTo(new THREE.Vector3().fromArray(outBuffers.position, 3));
    var buildIndexSkirt = function buildIndexSkirt() {};
    var buildUVSkirt = function buildUVSkirt() {};
    if (params.buildIndexAndUv_0) {
      buildIndexSkirt = function buildIndexSkirt(id, v1, v2, v3, v4) {
        id = bufferize(v1, v2, v3, id);
        id = bufferize(v1, v3, v4, id);
        return id;
      };
      buildUVSkirt = function buildUVSkirt(id) {
        outBuffers.uvs[0][idVertex * 2 + 0] = outBuffers.uvs[0][id * 2 + 0];
        outBuffers.uvs[0][idVertex * 2 + 1] = outBuffers.uvs[0][id * 2 + 1];
      };
    }
    for (var i = 0; i < skirt.length; i++) {
      var id = skirt[i];
      var id_m3 = idVertex * 3;
      var id2_m3 = id * 3;
      outBuffers.position[id_m3 + 0] = outBuffers.position[id2_m3 + 0] - outBuffers.normal[id2_m3 + 0] * segmentSize;
      outBuffers.position[id_m3 + 1] = outBuffers.position[id2_m3 + 1] - outBuffers.normal[id2_m3 + 1] * segmentSize;
      outBuffers.position[id_m3 + 2] = outBuffers.position[id2_m3 + 2] - outBuffers.normal[id2_m3 + 2] * segmentSize;
      outBuffers.normal[id_m3 + 0] = outBuffers.normal[id2_m3 + 0];
      outBuffers.normal[id_m3 + 1] = outBuffers.normal[id2_m3 + 1];
      outBuffers.normal[id_m3 + 2] = outBuffers.normal[id2_m3 + 2];
      buildUVSkirt(id);
      if (uvCount > 1) {
        outBuffers.uvs[1][idVertex] = outBuffers.uvs[1][id];
      }
      var idf = (i + 1) % skirt.length;
      var _v = id;
      var _v2 = idVertex;
      var _v3 = idf === 0 ? iStart : idVertex + 1;
      var _v4 = skirt[idf];
      idVertex2 = buildIndexSkirt(idVertex2, _v, _v2, _v3, _v4);
      idVertex++;
    }
  }
  return outBuffers;
}