'use strict';

var MeshGeometry = require('../mesh/shared/MeshGeometry.js');

"use strict";
const _RopeGeometry = class _RopeGeometry extends MeshGeometry.MeshGeometry {
  /**
   * @param options - Options to be applied to rope geometry
   */
  constructor(options) {
    const { width, points, textureScale } = { ..._RopeGeometry.defaultOptions, ...options };
    super({
      positions: new Float32Array(points.length * 4),
      uvs: new Float32Array(points.length * 4),
      indices: new Uint32Array((points.length - 1) * 6)
    });
    this.points = points;
    this._width = width;
    this.textureScale = textureScale;
    this._build();
  }
  /**
   * The width (i.e., thickness) of the rope.
   * @readonly
   */
  get width() {
    return this._width;
  }
  /** Refreshes Rope indices and uvs */
  _build() {
    const points = this.points;
    if (!points)
      return;
    const vertexBuffer = this.getBuffer("aPosition");
    const uvBuffer = this.getBuffer("aUV");
    const indexBuffer = this.getIndex();
    if (points.length < 1) {
      return;
    }
    if (vertexBuffer.data.length / 4 !== points.length) {
      vertexBuffer.data = new Float32Array(points.length * 4);
      uvBuffer.data = new Float32Array(points.length * 4);
      indexBuffer.data = new Uint16Array((points.length - 1) * 6);
    }
    const uvs = uvBuffer.data;
    const indices = indexBuffer.data;
    uvs[0] = 0;
    uvs[1] = 0;
    uvs[2] = 0;
    uvs[3] = 1;
    let amount = 0;
    let prev = points[0];
    const textureWidth = this._width * this.textureScale;
    const total = points.length;
    for (let i = 0; i < total; i++) {
      const index = i * 4;
      if (this.textureScale > 0) {
        const dx = prev.x - points[i].x;
        const dy = prev.y - points[i].y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        prev = points[i];
        amount += distance / textureWidth;
      } else {
        amount = i / (total - 1);
      }
      uvs[index] = amount;
      uvs[index + 1] = 0;
      uvs[index + 2] = amount;
      uvs[index + 3] = 1;
    }
    let indexCount = 0;
    for (let i = 0; i < total - 1; i++) {
      const index = i * 2;
      indices[indexCount++] = index;
      indices[indexCount++] = index + 1;
      indices[indexCount++] = index + 2;
      indices[indexCount++] = index + 2;
      indices[indexCount++] = index + 1;
      indices[indexCount++] = index + 3;
    }
    uvBuffer.update();
    indexBuffer.update();
    this.updateVertices();
  }
  /** refreshes vertices of Rope mesh */
  updateVertices() {
    const points = this.points;
    if (points.length < 1) {
      return;
    }
    let lastPoint = points[0];
    let nextPoint;
    let perpX = 0;
    let perpY = 0;
    const vertices = this.buffers[0].data;
    const total = points.length;
    const halfWidth = this.textureScale > 0 ? this.textureScale * this._width / 2 : this._width / 2;
    for (let i = 0; i < total; i++) {
      const point = points[i];
      const index = i * 4;
      if (i < points.length - 1) {
        nextPoint = points[i + 1];
      } else {
        nextPoint = point;
      }
      perpY = -(nextPoint.x - lastPoint.x);
      perpX = nextPoint.y - lastPoint.y;
      let ratio = (1 - i / (total - 1)) * 10;
      if (ratio > 1) {
        ratio = 1;
      }
      const perpLength = Math.sqrt(perpX * perpX + perpY * perpY);
      if (perpLength < 1e-6) {
        perpX = 0;
        perpY = 0;
      } else {
        perpX /= perpLength;
        perpY /= perpLength;
        perpX *= halfWidth;
        perpY *= halfWidth;
      }
      vertices[index] = point.x + perpX;
      vertices[index + 1] = point.y + perpY;
      vertices[index + 2] = point.x - perpX;
      vertices[index + 3] = point.y - perpY;
      lastPoint = point;
    }
    this.buffers[0].update();
  }
  /** Refreshes Rope indices and uvs */
  update() {
    if (this.textureScale > 0) {
      this._build();
    } else {
      this.updateVertices();
    }
  }
};
/** Default options for RopeGeometry constructor. */
_RopeGeometry.defaultOptions = {
  /** The width (i.e., thickness) of the rope. */
  width: 200,
  /** An array of points that determine the rope. */
  points: [],
  /** Rope texture scale, if zero then the rope texture is stretched. */
  textureScale: 0
};
let RopeGeometry = _RopeGeometry;

exports.RopeGeometry = RopeGeometry;
//# sourceMappingURL=RopeGeometry.js.map
