@deck.gl/experimental-layers
Version:
Experimental layers for deck.gl
397 lines (357 loc) • 13.1 kB
JavaScript
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
// Note: This file will either be moved back to deck.gl or reformatted to web-monorepo standards
// Disabling lint temporarily to facilitate copying code in and out of this repo
/* eslint-disable */
// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { Layer, COORDINATE_SYSTEM } from '@deck.gl/core';
import GL from 'luma.gl/constants';
import { Model, Geometry, loadTextures, Texture2D, fp64 } from 'luma.gl';
var fp64LowPart = fp64.fp64LowPart;
import vs from './mesh-layer-vertex.glsl';
import fs from './mesh-layer-fragment.glsl';
var RADIAN_PER_DEGREE = Math.PI / 180; // Replacement for the external assert method to reduce bundle size
function assert(condition, message) {
if (!condition) {
throw new Error("deck.gl: ".concat(message));
}
}
/*
* Load image data into luma.gl Texture2D objects
* @param {WebGLContext} gl
* @param {String|Texture2D|HTMLImageElement|Uint8ClampedArray} src - source of image data
* can be url string, Texture2D object, HTMLImageElement or pixel array
* @returns {Promise} resolves to an object with name -> texture mapping
*/
function getTexture(gl, src, opts) {
if (typeof src === 'string') {
// Url, load the image
return loadTextures(gl, Object.assign({
urls: [src]
}, opts)).then(function (textures) {
return textures[0];
}).catch(function (error) {
throw new Error("Could not load texture from ".concat(src, ": ").concat(error));
});
}
return new Promise(function (resolve) {
return resolve(getTextureFromData(gl, src, opts));
});
}
/*
* Convert image data into texture
* @returns {Texture2D} texture
*/
function getTextureFromData(gl, data, opts) {
if (data instanceof Texture2D) {
return data;
}
return new Texture2D(gl, Object.assign({
data: data
}, opts));
}
function validateGeometryAttributes(attributes) {
assert(attributes.positions && attributes.normals && attributes.texCoords);
}
/*
* Convert mesh data into geometry
* @returns {Geometry} geometry
*/
function getGeometry(data) {
if (data instanceof Geometry) {
validateGeometryAttributes(data.attributes);
return data;
} else if (data.positions) {
validateGeometryAttributes(data);
return new Geometry({
attributes: data
});
}
throw Error('Invalid mesh');
}
var DEFAULT_COLOR = [0, 0, 0, 255];
var defaultProps = {
mesh: null,
texture: null,
sizeScale: {
type: 'number',
value: 1,
min: 0
},
// TODO - parameters should be merged, not completely overridden
parameters: {
depthTest: true,
depthFunc: GL.LEQUAL
},
fp64: false,
// Optional settings for 'lighting' shader module
lightSettings: {},
getPosition: {
type: 'accessor',
value: function value(x) {
return x.position;
}
},
getColor: {
type: 'accessor',
value: DEFAULT_COLOR
},
// yaw, pitch and roll are in degrees
// https://en.wikipedia.org/wiki/Euler_angles
getYaw: {
type: 'accessor',
value: function value(x) {
return x.yaw || x.angle || 0;
}
},
getPitch: {
type: 'accessor',
value: function value(x) {
return x.pitch || 0;
}
},
getRoll: {
type: 'accessor',
value: function value(x) {
return x.roll || 0;
}
}
};
var MeshLayer =
/*#__PURE__*/
function (_Layer) {
_inherits(MeshLayer, _Layer);
function MeshLayer() {
_classCallCheck(this, MeshLayer);
return _possibleConstructorReturn(this, _getPrototypeOf(MeshLayer).apply(this, arguments));
}
_createClass(MeshLayer, [{
key: "getShaders",
value: function getShaders() {
var projectModule = this.use64bitProjection() ? 'project64' : 'project32';
return {
vs: vs,
fs: fs,
modules: [projectModule, 'lighting', 'picking']
};
}
}, {
key: "initializeState",
value: function initializeState() {
var attributeManager = this.getAttributeManager();
attributeManager.addInstanced({
instancePositions: {
size: 3,
accessor: 'getPosition'
},
instancePositions64xy: {
size: 2,
accessor: 'getPosition',
update: this.calculateInstancePositions64xyLow
},
instanceRotations: {
size: 3,
accessor: ['getYaw', 'getPitch', 'getRoll'],
update: this.calculateInstanceRotations
},
instanceColors: {
size: 4,
accessor: 'getColor',
defaultValue: [0, 0, 0, 255]
}
});
this.setState({
// Avoid luma.gl's missing uniform warning
// TODO - add feature to luma.gl to specify ignored uniforms?
emptyTexture: new Texture2D(this.context.gl, {
data: new Uint8Array(4),
width: 1,
height: 1
})
});
}
}, {
key: "updateState",
value: function updateState(_ref) {
var props = _ref.props,
oldProps = _ref.oldProps,
changeFlags = _ref.changeFlags;
var attributeManager = this.getAttributeManager(); // super.updateState({props, oldProps, changeFlags});
if (changeFlags.dataChanged) {
attributeManager.invalidateAll();
}
this._updateFP64(props, oldProps);
if (props.texture !== oldProps.texture) {
this.setTexture(props.texture);
}
}
}, {
key: "_updateFP64",
value: function _updateFP64(props, oldProps) {
if (props.fp64 !== oldProps.fp64) {
if (this.state.model) {
this.state.model.delete();
}
this.setState({
model: this.getModel(this.context.gl)
});
this.setTexture(this.state.texture);
var attributeManager = this.getAttributeManager();
attributeManager.invalidateAll();
}
}
}, {
key: "draw",
value: function draw(_ref2) {
var uniforms = _ref2.uniforms;
var sizeScale = this.props.sizeScale;
this.state.model.render(Object.assign({}, uniforms, {
sizeScale: sizeScale
}));
}
}, {
key: "getModel",
value: function getModel(gl) {
return new Model(gl, Object.assign({}, this.getShaders(), {
id: this.props.id,
geometry: getGeometry(this.props.mesh),
isInstanced: true,
shaderCache: this.context.shaderCache
}));
}
}, {
key: "setTexture",
value: function setTexture(src) {
var _this = this;
var gl = this.context.gl;
var _this$state = this.state,
model = _this$state.model,
emptyTexture = _this$state.emptyTexture;
if (src) {
getTexture(gl, src).then(function (texture) {
model.setUniforms({
sampler: texture,
hasTexture: 1
});
_this.setState({
texture: texture
});
});
} else {
// reset
this.state.model.setUniforms({
sampler: emptyTexture,
hasTexture: 0
});
this.setState({
texture: null
});
}
}
}, {
key: "calculateInstancePositions64xyLow",
value: function calculateInstancePositions64xyLow(attribute) {
var isFP64 = this.use64bitPositions();
attribute.constant = !isFP64;
if (!isFP64) {
attribute.value = new Float32Array(2);
return;
}
var _this$props = this.props,
data = _this$props.data,
getPosition = _this$props.getPosition;
var value = attribute.value;
var i = 0;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = data[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var point = _step.value;
var position = getPosition(point);
value[i++] = fp64LowPart(position[0]);
value[i++] = fp64LowPart(position[1]);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
} // yaw(z), pitch(y) and roll(x) in radians
}, {
key: "calculateInstanceRotations",
value: function calculateInstanceRotations(attribute) {
var _this$props2 = this.props,
data = _this$props2.data,
getYaw = _this$props2.getYaw,
getPitch = _this$props2.getPitch,
getRoll = _this$props2.getRoll;
var value = attribute.value,
size = attribute.size;
var i = 0;
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = data[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var point = _step2.value;
value[i++] = getRoll(point) * RADIAN_PER_DEGREE;
value[i++] = getPitch(point) * RADIAN_PER_DEGREE;
value[i++] = getYaw(point) * RADIAN_PER_DEGREE;
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
}]);
return MeshLayer;
}(Layer);
export { MeshLayer as default };
MeshLayer.layerName = 'MeshLayer';
MeshLayer.defaultProps = defaultProps;
//# sourceMappingURL=mesh-layer.js.map