"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _typeof = require("@babel/runtime/helpers/typeof");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));

var THREE = _interopRequireWildcard(require("three"));

var _Capabilities = _interopRequireDefault(require("../Core/System/Capabilities"));

var _LayeredMaterial = require("./LayeredMaterial");

var _WebGL = _interopRequireDefault(require("../ThreeExtended/capabilities/WebGL"));

var _Label2DRenderer = _interopRequireDefault(require("./Label2DRenderer"));

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; }

/**
 * Generated On: 2015-10-5
 * Class: c3DEngine
 * Description: 3DEngine est l'interface avec le framework webGL.
 */
var depthRGBA = new THREE.Vector4();

var c3DEngine = /*#__PURE__*/function () {
  function c3DEngine(rendererOrDiv) {
    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
    (0, _classCallCheck2["default"])(this, c3DEngine);
    var NOIE = !_Capabilities["default"].isInternetExplorer(); // pick sensible default options

    if (options.antialias === undefined) {
      options.antialias = true;
    }

    if (options.alpha === undefined) {
      options.alpha = true;
    }

    if (options.logarithmicDepthBuffer === undefined) {
      options.logarithmicDepthBuffer = this.gLDebug || NOIE;
    }

    if (options.isWebGL2 === undefined) {
      options.isWebGL2 = true;
    } // If rendererOrDiv parameter is a domElement, we use it as support to display data.
    // If it is a renderer, we check the renderer.domElement parameter which can be :
    //    - a domElement, in this case we use this domElement as a support
    //    - a canvas, in this case we use the canvas parent (which should be a domElement) as a support


    var renderer;
    var viewerDiv;

    if (rendererOrDiv.domElement) {
      renderer = rendererOrDiv;
      viewerDiv = renderer.domElement instanceof HTMLDivElement ? renderer.domElement : renderer.domElement.parentElement;
    } else {
      viewerDiv = rendererOrDiv;
    }

    this.width = viewerDiv.clientWidth;
    this.height = viewerDiv.clientHeight;
    this.positionBuffer = null;
    this._nextThreejsLayer = 1;
    this.fullSizeRenderTarget = new THREE.WebGLRenderTarget(this.width, this.height);
    this.fullSizeRenderTarget.texture.minFilter = THREE.LinearFilter;
    this.fullSizeRenderTarget.texture.magFilter = THREE.NearestFilter;
    this.fullSizeRenderTarget.depthBuffer = true;
    this.fullSizeRenderTarget.depthTexture = new THREE.DepthTexture();
    this.fullSizeRenderTarget.depthTexture.type = THREE.UnsignedShortType;

    this.renderView = function (view) {
      this.renderer.clear();
      this.renderer.render(view.scene, view.camera.camera3D);

      if (view.tileLayer) {
        this.label2dRenderer.render(view.tileLayer.object3d, view.camera.camera3D);
      }
    }.bind(this);

    this.onWindowResize = function (w, h) {
      this.width = w;
      this.height = h;
      this.fullSizeRenderTarget.setSize(this.width, this.height);
      this.renderer.setSize(this.width, this.height);
      this.label2dRenderer.setSize(this.width, this.height);
    }.bind(this); // Create renderer


    try {
      this.label2dRenderer = new _Label2DRenderer["default"]();
      this.label2dRenderer.setSize(this.width, this.height);
      viewerDiv.appendChild(this.label2dRenderer.domElement);
      this.renderer = renderer || new (options.isWebGL2 ? THREE.WebGLRenderer : THREE.WebGL1Renderer)({
        canvas: document.createElement('canvas'),
        antialias: options.antialias,
        alpha: options.alpha,
        logarithmicDepthBuffer: options.logarithmicDepthBuffer
      });
      this.renderer.domElement.style.position = 'relative';
      this.renderer.domElement.style.zIndex = 0;
      this.renderer.domElement.style.top = 0;
    } catch (ex) {
      var versionWebGL = options.isWebGL2 ? '2' : '1';
      console.error("Failed to create WebGLRenderer webGL ".concat(versionWebGL, "."));
      this.renderer = null;
    }

    if (!this.renderer) {
      if (!_WebGL["default"].isWebGLAvailable()) {
        viewerDiv.appendChild(_WebGL["default"].getErrorMessage(1));
      } else if (!_WebGL["default"].isWebGL2Available()) {
        viewerDiv.appendChild(_WebGL["default"].getErrorMessage(2));
      }

      throw new Error('WebGL unsupported');
    }

    if (!renderer && options.logarithmicDepthBuffer) {
      // We don't support logarithmicDepthBuffer when EXT_frag_depth is missing.
      // So recreated a renderer if needed.
      if (!this.renderer.capabilities.isWebGL2 && !this.renderer.extensions.get('EXT_frag_depth')) {
        this.renderer.dispose();
        this.renderer = new (options.isWebGL2 ? THREE.WebGLRenderer : THREE.WebGL1Renderer)({
          canvas: document.createElement('canvas'),
          antialias: options.antialias,
          alpha: options.alpha,
          logarithmicDepthBuffer: false
        });
      }
    } // Let's allow our canvas to take focus
    // The condition below looks weird, but it's correct: querying tabIndex
    // returns -1 if not set, but we still need to explicitly set it to force
    // the tabindex focus flag to true (see
    // https://www.w3.org/TR/html5/editing.html#specially-focusable)


    if (this.renderer.domElement.tabIndex === -1) {
      this.renderer.domElement.tabIndex = -1;
    }

    _Capabilities["default"].updateCapabilities(this.renderer);

    this.renderer.setClearColor(0x030508);
    this.renderer.autoClear = false;
    this.renderer.sortObjects = true;
    this.renderer.debug.checkShaderErrors = false;

    if (!renderer) {
      this.renderer.setPixelRatio(viewerDiv.devicePixelRatio);
      this.renderer.setSize(viewerDiv.clientWidth, viewerDiv.clientHeight);
      viewerDiv.appendChild(this.renderer.domElement);
    }
  }

  (0, _createClass2["default"])(c3DEngine, [{
    key: "getWindowSize",
    value: function getWindowSize() {
      return new THREE.Vector2(this.width, this.height);
    }
    /**
     * return renderer THREE.js
     * @returns {undefined|THREE.WebGLRenderer}
     */

  }, {
    key: "getRenderer",
    value: function getRenderer() {
      return this.renderer;
    }
    /**
     * Render view to a Uint8Array.
     *
     * @param {View} view - The view to render
     * @param {object} [zone] - partial zone to render
     * @param {number} zone.x - x (in view coordinate)
     * @param {number} zone.y - y (in view coordinate)
     * @param {number} zone.width - width of area to render (in pixels)
     * @param {number} zone.height - height of area to render (in pixels)
     * @return {THREE.RenderTarget} - Uint8Array, 4 bytes per pixel. The first pixel in
     * the array is the bottom-left pixel.
     */

  }, {
    key: "renderViewToBuffer",
    value: function renderViewToBuffer(view, zone) {
      if (!zone) {
        zone = {
          x: 0,
          y: 0,
          width: this.width,
          height: this.height
        };
      }

      zone.buffer = zone.buffer || new Uint8Array(4 * zone.width * zone.height);
      this.renderViewToRenderTarget(view, this.fullSizeRenderTarget, zone);
      this.renderer.readRenderTargetPixels(this.fullSizeRenderTarget, zone.x, this.height - (zone.y + zone.height), zone.width, zone.height, zone.buffer);
      return zone.buffer;
    }
    /**
     * Render view to a THREE.RenderTarget.
     *
     * @param {View} view - The view to render
     * @param {THREE.RenderTarget} [target] - destination render target. Default value: full size render target owned by c3DEngine.
     * @param {object} [zone] - partial zone to render (zone x/y uses view coordinates) Note: target must contain complete zone
     * @return {THREE.RenderTarget} - the destination render target
     */

  }, {
    key: "renderViewToRenderTarget",
    value: function renderViewToRenderTarget(view, target, zone) {
      if (!target) {
        target = this.fullSizeRenderTarget;
      }

      var current = this.renderer.getRenderTarget(); // Don't use setViewport / setScissor on renderer because they would affect
      // on screen rendering as well. Instead set them on the render target.
      // Example : this.fullSizeRenderTarget.viewport.set(0, 0, target.width, target.height);

      if (zone) {
        this.fullSizeRenderTarget.scissor.set(zone.x, target.height - (zone.y + zone.height), zone.width, zone.height);
        this.fullSizeRenderTarget.scissorTest = true;
      }

      this.renderer.setRenderTarget(target);
      this.renderer.clear(true, true, false);
      this.renderer.render(view.scene, view.camera.camera3D);
      this.renderer.setRenderTarget(current);
      this.fullSizeRenderTarget.scissorTest = false;
      return target;
    }
  }, {
    key: "bufferToImage",
    value: function bufferToImage(pixelBuffer, width, height) {
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d', {
        willReadFrequently: true
      }); // size the canvas to your desired image

      canvas.width = width;
      canvas.height = height;
      var imgData = ctx.getImageData(0, 0, width, height);
      imgData.data.set(pixelBuffer);
      ctx.putImageData(imgData, 0, 0); // create a new img object

      var image = new Image(); // set the img.src to the canvas data url

      image.src = canvas.toDataURL();
      return image;
    }
  }, {
    key: "depthBufferRGBAValueToOrthoZ",
    value: function depthBufferRGBAValueToOrthoZ(depthBufferRGBA, camera) {
      depthRGBA.fromArray(depthBufferRGBA).divideScalar(255.0);

      if (_Capabilities["default"].isLogDepthBufferSupported() && camera.type == 'PerspectiveCamera') {
        var gl_FragDepthEXT = (0, _LayeredMaterial.unpack1K)(depthRGBA);
        var logDepthBufFC = 2.0 / (Math.log(camera.far + 1.0) / Math.LN2); // invert function : gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;

        return Math.pow(2, 2 * gl_FragDepthEXT / logDepthBufFC);
      } else {
        var gl_FragCoord_Z = (0, _LayeredMaterial.unpack1K)(depthRGBA);
        gl_FragCoord_Z = gl_FragCoord_Z * 2.0 - 1.0;
        return gl_FragCoord_Z;
      }
    }
  }]);
  return c3DEngine;
}();

var _default = c3DEngine;
exports["default"] = _default;