Skip to content

Instantly share code, notes, and snippets.

@vkuchinov
Last active November 8, 2019 08:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vkuchinov/53bb0fbd556c03f702c44fd48ab724eb to your computer and use it in GitHub Desktop.
Save vkuchinov/53bb0fbd556c03f702c44fd48ab724eb to your computer and use it in GitHub Desktop.
MapboxGL | THREE.JS + GLSL Shader
var sparkData64 =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGvmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCkiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTA3LTA3VDE3OjU5OjI4KzAzOjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wNy0wN1QxODowMDo1MSswMzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNy0wN1QxODowMDo1MSswMzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5NjEwMmQxNC05MDRhLTQyMGQtYTllZi01ZDllZTJlYTYxMDgiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo3YjZiYzBkNS1iNzkzLWFlNDUtOTYyNC0zOGE1ZDQ1NzU0NzYiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo1M2Y1MDc0MS1jNGUyLTQ1MTAtODJjYi1kNTlhMDE3YjQ4NDYiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjUzZjUwNzQxLWM0ZTItNDUxMC04MmNiLWQ1OWEwMTdiNDg0NiIgc3RFdnQ6d2hlbj0iMjAxOS0wNy0wN1QxNzo1OToyOCswMzowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiN2RlMjBkNC05OTIzLTQ1YTQtYTJkYi0wMzVhZTUxMTk1MjYiIHN0RXZ0OndoZW49IjIwMTktMDctMDdUMTg6MDA6NTErMDM6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAoTWFjaW50b3NoKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OTYxMDJkMTQtOTA0YS00MjBkLWE5ZWYtNWQ5ZWUyZWE2MTA4IiBzdEV2dDp3aGVuPSIyMDE5LTA3LTA3VDE4OjAwOjUxKzAzOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+gLYGQgAABW5JREFUeJztW9lyozAQbIxxjv3/X93E+NoH1KumGSec1oM9VSowMZam5x4p1e12wzPTrvQCStMLgNILKE0vAEovoDS9ACi9gNL09ADsC81b3Xn+8KzskQBUaeyQAeD1JtcbgCseBMYjAKjRMc0rAXAtcOYvaWwKxlYAVOgYrtMcO/lc2QAyg1fEAJzlflXaAoAaQJN+u5brb1pA6V+Rmeeo0/WUrqtpxJoAVOn3yDzvG2Tpc0QAXDEE4JzGKV3rdH/CStqwFgA7ZGb3AA7BZ9cGZb5CLH0y2wBo0z2BozYsojUA2CEzfLhzr2CoKagPULsn82d0jLfoaxBBaLEQhKUAVBgy/Q7gTZ47COoPlFQDqPYtMnCtvMu5gYUgLAGgQmaKjJL5aLh/8ChADaDdk/kWfdMBhiH0iJk+YQkAZFwlTwA+0AfjHbEW7NCP/yr9EzrGjugDxuGhs8WM6DAXADq0BkNJfyKDoUCoOdAXUKJq/2S+te868xo2VXsm0RwAVPU5VNLv6ED4QAaAQ52hqnSk/kf7njtNZ76RZ6NpDgCUvsZ5NQEy/gcZAF6pBRoNyBABoNfX/CFi/iJXhsRLenc0zQXATeCAvgaQ4U/0TYIgqCMkadLzjaGWeIKk/qKRzztM0IKpAGgspiprFHAQCICag/oB2rQ6QHp9agnQV3nWBmS8SfcErN4SAKotJ1M/oGFQtUDNgX9TMyCDVN9vDP2DAkSQDsgOU5mf1OSZAoBWeAqE+oLIIVL6agrMC2jblKraPTBUe40OB2RHqQBwjEqOpgKgZa1Wew6CJkYOBAFoAgAcFA2N/vvqJxyAex2nRQBoKIq0IALB8wQ1gzf0Jd2i7+lV6p5S7214ib06AJ6FqTa4X9CFeWGkpkEzQGJWbZdSP2DILOdUxjcHgHQPiJ3duz1qHaAa0CBLu0I/qXFAHXDtL3q/0dPlVQDQRmZln/V5JJEImCYBUaFzZuz8uFQVXF59HZOkrrR0X8AnjRbx08J84VMZWdwam6IBN7vyXj8zN9ec/BY8p4M7pu8ws9MusA997uuKno+iqT4g6t5qQaI5OkObpq1MYqjOjNVMgpjY+HsXm0Pn9z2FSFB3aSwAkURcolFHR/N7prga6ujM6PW/0GmFguGAKNB672sbRVNNIOrcRt1bbWpoaeuhrpYFswHybVetEPX3FRDXjE1qAVX5e8yTYQ5ma1Hzo7FnZ3nHR2u/z/I3Mo9NNcA3LBQAVfUjho0PTW9ZwHgqzFLYB1tjLfog6LyuDasDAJsgkrozHjF/Rt4ncK1wM/iLzi9EQLjTnLWXOBUA9+5u51FhogxqYeMAeEOE4wsdEAqCmplGC4I8muaEQW5RKQCUnG6GaidHpc+CJvIL6vCoCV8y1EGqFhAIgjGa5rTEovrcd4BV7b3b470+IDtX9yOqBQoC/+7MP6QrfE0TU4L7tCg//OCdHHZx1Ed4+RtpgfoA1wR3hpN3iObuC9AMomKFDDlTWs/ru/y+g6UbI2oOGhrdEU6mJTtDbGD4Tq8mTJTMGzom6P3VQep7blruD9T+Ccyi7fIlADB784pS83Tf5/OzAkqa1qoWMCooGBz8XpHNUaSJj/ZMM0a2rN32f9rp8RxDEx8FgMzPUn3SGucDCELEhPftNVqMPSBBJr1AWsw8sN4JEYLgB5w0uYkOR/ghKa/0vMhSABafDgHWPSPEzq5qgZ7tiU54eNTQfEBPh51trHZarNroX2a8ZR4dk3PnGfUYtO6YFed/o60AIHl2OPWgpAKxCW0NwP950Jf8vean9w83X9yjAAjnts9FFlLqtDhQiGGnp/9/gRcApRdQml4AlF5AaXoBUHoBpenpAfgHHssPzgTkF+sAAAAASUVORK5CYII="
var HUD = function() {
this.daytime = 8;
this.semantic = "8:00am";
};
var routes = [
{ id: "commute1", colors: ["#1A4C81", "#FFFFFF"], size: 8, t: 6.0, geo : [
[-0.03775, 51.474773],
[-0.03816, 51.474768],
[-0.038598, 51.474669],
[-0.038942, 51.47524],
[-0.039022, 51.475224],
[-0.039521, 51.475089],
[-0.039861, 51.474998],
[-0.040129, 51.474931]
],
times: [{t: 0, s: 2.0}, {t: 8, s: 10.0}, {t: 9, s: 15}, {t: 11, s: 50}, {t: 13, s: 5.0}, {t: 17, s: -5.0}, {t: 19, s: -15}, {t: 22, s: 5.0}, {t: 24, s: 0}]
},
{ id: "commute2", colors: ["#D06B15", "#FFFFFF"], size: 16, t: 1.0, geo : [
[-0.03775, 51.474773],
[-0.037428, 51.47482],
[-0.03739, 51.474754],
[-0.037366, 51.474701],
[-0.037071, 51.474709],
[-0.036941, 51.47469],
[-0.037046, 51.475632],
[-0.036814, 51.475633],
[-0.036585, 51.475614],
[-0.036506, 51.475608],
[-0.036332, 51.475563],
[-0.036313, 51.475585],
[-0.036291, 51.475616],
[-0.036237, 51.475609],
[-0.036172, 51.475604],
[-0.036149, 51.475637],
[-0.036053, 51.475683],
[-0.035974, 51.475695],
[-0.035012, 51.47575],
[-0.034158, 51.475815],
[-0.03313, 51.475877],
[-0.033045, 51.475883],
[-0.032768, 51.475926],
[-0.032592, 51.47592],
[-0.032267, 51.475891]
]
}
];
var count = 0;
var center = { LngLat : [-0.037891, 51.475139], altidute: 0, rotation : new THREE.Vector3(Math.PI / 2, 0, 0), scale: 5.4184E-8 };
center.transform = {
translateX: mapboxgl.MercatorCoordinate.fromLngLat(center.LngLat, center.altitude).x,
translateY: mapboxgl.MercatorCoordinate.fromLngLat(center.LngLat, center.altitude).y,
translateZ: mapboxgl.MercatorCoordinate.fromLngLat(center.LngLat, center.altitude).z,
rotateX: center.rotation.x,
rotateY: center.rotation.y,
rotateZ: center.rotation.z,
scale: center.scale
};
mapboxgl.accessToken = getKey("cGsuZXlKMUlqb2laMlZ1ZG5acklpd2lZU0k2SW1OcVpUY3hNelp6TnpBMWRtVXlkMjFyTm5rM2FIY3pNVElpZlEuMmZGVkNsOG4zaHIxQkN4a3l4czFsdw==");
var map = window.map = new mapboxgl.Map({
container: "map",
style: "mapbox://styles/mapbox/dark-v9",
zoom: 16.75,
center: center.LngLat,
pitch: 36,
bearing: 158
});
var THREE = window.THREE;
var building3D = {
"id": "3d-buildings",
"source": "composite",
"source-layer": "building",
"filter": ["==", "extrude", "true"],
"type": "fill-extrusion",
"minzoom": 15,
"paint": {
"fill-extrusion-color": "#AAAAAA",
"fill-extrusion-height": [
"interpolate", ["linear"], ["zoom"],
15, 0,
15.05, ["get", "height"]
],
"fill-extrusion-base": [
"interpolate", ["linear"], ["zoom"],
15, 0,
15.05, ["get", "min_height"]
],
"fill-extrusion-opacity": 1.0
}
}
var threejsLayer = {
id: "threejs",
type: "custom",
renderingMode: "3d",
onAdd: function(map_, gl_) {
var ui = new HUD();
var gui = new dat.GUI();
var slider = gui.add(ui, "daytime", 8, 22, 0.16666).onChange(function(v_){
var h = Math.floor(v_ % 12);
var suffix = Math.floor(v_) < 12 ? "am" : "pm";
var m = Math.ceil((v_ - Math.floor(v_)) * 60 / 10) * 10;
if(m == 60){ m = "00"; h++; }
if(h == 0) { h = 12; }
ui.semantic = h + ":" + m + suffix;
var domain = [];
for(var i = 0; i < routes[0].times.length - 2; i++){
if(Number(v_).between([routes[0].times[i].t, routes[0].times[i + 1].t])){
console.log(routes[0].times[i + 1].t)
domain = [routes[0].times[i], routes[0].times[i + 1]];
}
}
routes[0].t = remapFloat(v_, domain[0].t, domain[1].t, domain[0].s, domain[1].s);
}).listen();
var ampm = gui.add(ui, "semantic").listen();
slider.domElement.getElementsByTagName("input")[0].remove();
slider.domElement.getElementsByClassName("slider")[0].style.marginLeft = "-6px";
slider.domElement.getElementsByClassName("slider")[0].style.width = ampm.domElement.getElementsByTagName("input")[0].clientWidth + "px";
this.camera = new THREE.Camera();
this.scene = new THREE.Scene();
const NUM = 512, radius = 10, kofStep = 12 / radius, w = document.body.clientWidth,h = document.body.clientHeight;
var shaderPoint = THREE.ShaderLib.points;
var uniforms = THREE.UniformsUtils.clone(shaderPoint.uniforms);
uniforms.size.value = radius * 1.5;
uniforms.scale.value = h * 0.5
var spark = new Image();
uniforms.map.value = new THREE.Texture(spark);
spark.onload = () => {
uniforms.map.value.needsUpdate = true;
};
spark.src = sparkData64;
var shaderMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
defines: {
USE_COLOR: "",
USE_MAP: "",
USE_SIZEATTENUATION: ""
},
transparent: true,
depthWrite: false,
blending: THREE.AdditiveBlending,
vertexShader: shaderPoint.vertexShader,
fragmentShader: shaderPoint.fragmentShader
})
for(var i = 0; i < routes.length; i++){
pointsGeometry = new THREE.BufferGeometry();
pointsGeometry.addAttribute("position", new THREE.BufferAttribute(new Float32Array(NUM * 3), 3));
pointsGeometry.addAttribute("color", new THREE.BufferAttribute(new Float32Array(NUM * 3), 3));
var geometry = new THREE.BufferGeometry();
var range = getVerticesFromRoute(routes[i].geo)
var poss = new THREE.BufferAttribute(new Float32Array(NUM * 3), 3);
var color = new THREE.Color(0xFFFF00);
geometry.color = color;
poss.setDynamic(true).copyVector3sArray(range);
geometry.setDrawRange(0, range.length);
geometry.addAttribute("position", poss);
geometry.lPos = geometry.attributes.position;
var line = geometry;
var material = new THREE.LineBasicMaterial({ color: color, blending: THREE.AdditiveBlending });
var attrs = generatePoints(line, kofStep);
pointsGeometry.attributes.position.setDynamic(true).copyArray(attrs.positions);
pointsGeometry.attributes.color.setDynamic(true).copyArray(attrs.colors);
pointsGeometry.attributes.color.array = setColors(pointsGeometry.attributes.color.array, routes[i].colors);
pointsGeometry.attributes.color.needsUpdate = true;
pointsGeometry.setDrawRange(0, attrs.positions.length / 3);
pointsGeometry.computeBoundingSphere();
points = new THREE.Points(pointsGeometry, shaderMaterial);
points.name = routes[i].id;
this.scene.add(points);
}
this.map = map_;
this.renderer = new THREE.WebGLRenderer({ canvas: map.getCanvas(), context: gl_ });
this.renderer.autoClear = false;
},
render: function(gl_, matrix_) {
var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), center.rotation.x);
var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), center.rotation.y);
var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), center.rotation.z);
var m = new THREE.Matrix4().fromArray(matrix_);
var l = new THREE.Matrix4().makeTranslation(center.transform.translateX, center.transform.translateY, center.transform.translateZ)
.scale(new THREE.Vector3(center.scale, -center.scale, center.scale))
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix.elements = matrix_;
this.camera.projectionMatrix = m.multiply(l);
updateShift(this.scene);
count++;
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
};
function update(){
for(var i = 0; i < points.geometry.attributes.color.count * 3; i += 3){
points.geometry.attributes.color.array[i + 1] += 0.01;
points.geometry.attributes.color.array[i + 2] += 0.01;
if(points.geometry.attributes.color.array[i + 1] >= 1.0) { points.geometry.attributes.color.array[i + 1] = points.geometry.attributes.color.array[i + 1] - Math.floor(points.geometry.attributes.color.array[i + 1]); }
if(points.geometry.attributes.color.array[i + 2] >= 1.0) { points.geometry.attributes.color.array[i + 2] = points.geometry.attributes.color.array[i + 2] - Math.floor(points.geometry.attributes.color.array[i + 2]); }
}
points.geometry.attributes.color.needsUpdate = true;
}
function updateShift(scene_){
for(var i = 0; i < routes.length; i++){
var dir = routes[i].t > 0 ? "left" : "right";
var obj = scene_.getObjectByName(routes[i].id);
if(dir == "left"){
//left shift
var l0 = obj.geometry.attributes.color.array[obj.geometry.attributes.color.array.length - 3];
var l1 = obj.geometry.attributes.color.array[obj.geometry.attributes.color.array.length - 2];
var l2 = obj.geometry.attributes.color.array[obj.geometry.attributes.color.array.length - 1];
for(var j = obj.geometry.attributes.color.array.length - 3; j >= 0; j -= 3){
obj.geometry.attributes.color.array[j] = obj.geometry.attributes.color.array[j - 3];
obj.geometry.attributes.color.array[j + 1] = obj.geometry.attributes.color.array[j - 2];
obj.geometry.attributes.color.array[j + 2] = obj.geometry.attributes.color.array[j - 1];
}
obj.geometry.attributes.color.array[0] = l0;
obj.geometry.attributes.color.array[1] = l1;
obj.geometry.attributes.color.array[2] = l2;
obj.geometry.attributes.color.needsUpdate = true;
}
else if(dir == "right"){
//right shift
var r0 = obj.geometry.attributes.color.array[0];
var r1 = obj.geometry.attributes.color.array[1];
var r2 = obj.geometry.attributes.color.array[2];
for(var j = 3; j < obj.geometry.attributes.color.array.length; j += 3){
obj.geometry.attributes.color.array[j - 3] = obj.geometry.attributes.color.array[j];
obj.geometry.attributes.color.array[j - 2] = obj.geometry.attributes.color.array[j + 1];
obj.geometry.attributes.color.array[j - 1] = obj.geometry.attributes.color.array[j + 2];
}
obj.geometry.attributes.color.array[obj.geometry.attributes.color.array.length - 3] = r0;
obj.geometry.attributes.color.array[obj.geometry.attributes.color.array.length - 2] = r1;
obj.geometry.attributes.color.array[obj.geometry.attributes.color.array.length - 1] = r2;
obj.geometry.attributes.color.needsUpdate = true;
}
}
}
function setColors(array_, colors_){
var colorA = HexToFloat(colors_[0]);
var colorB = HexToFloat(colors_[1]);
for(var i = 0; i < array_.length; i += 3){
const step = 32;
var hash = (i / 3) % step;
if(hash < step / 2){
array_[i] = lerpFloat(colorA.r, colorB.r, 1.0 / step / 2 * hash);
array_[i + 1] = lerpFloat(colorA.g, colorB.g, 1.0 / step / 2 * hash);
array_[i + 2] = lerpFloat(colorA.b, colorB.b, 1.0 / step / 2 * hash);
}else{
array_[i] = lerpFloat(colorB.r, colorA.r, 1.0 / step / 2 * (step - hash));
array_[i + 1] = lerpFloat(colorB.g, colorA.g, 1.0 / step / 2 * (step - hash));
array_[i + 2] = lerpFloat(colorB.b, colorA.g, 1.0 / step / 2 * (step - hash));
}
}
return array_;
}
function HexToFloat(hex_) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex_);
return result ? {
r: parseInt(result[1], 16) / 255,
g: parseInt(result[2], 16) / 255,
b: parseInt(result[3], 16) / 255
} : null;
}
function getVerticesFromRoute(geo_){
var out = [];
for(var i = 0; i < geo_.length; i++){ out.push(getPositionFromLongLat(center, geo_[i], 1.0)); }
return out;
}
function getPositionFromLongLat(center_, LngLat_, z_){
var centerCoords = mapboxgl.MercatorCoordinate.fromLngLat(center_.LngLat, 0);
var objectCoords = mapboxgl.MercatorCoordinate.fromLngLat(LngLat_, 0);
var dx = centerCoords.x - objectCoords.x;
var dy = centerCoords.y - objectCoords.y;
dx /= center_.scale;
dy /= center_.scale;
return new THREE.Vector3(-dx, z_, -dy);
}
map.on("style.load", function() { map.addLayer(threejsLayer, "water-label") });
function getPositions(points_, count_, alpha_) {
var positions = [];
if (!points_) { return positions; }
var l = count_,
vec3s = new THREE.Vector3(),
vec3e = new THREE.Vector3(),
vec3n = new THREE.Vector3(),
dist, size, i;
while (l--) {
vec3s.set(points_.getX(l), points_.getY(l), points_.getZ(l));
vec3n.set(vec3s.x, vec3s.y, vec3s.z);
if (l < 1) {
positions.push(vec3n.x, vec3n.y, vec3n.z);
break;
}
vec3e.set(points_.getX(l - 1), points_.getY(l - 1), points_.getZ(l - 1));
dist = vec3n.distanceTo(vec3e);
size = dist * alpha_ | 0;
for (i = 0; i < size; i++) {
vec3n.set(vec3s.x, vec3s.y, vec3s.z);
vec3n.lerp(vec3e, i / size);
positions.push(vec3n.x, vec3n.y, vec3n.z);
}
}
return positions;
}
function generatePoints(line_, kof_) {
var positions = [];
var colors = [];
var result = {
positions,
colors
};
if (!line_) { return result; }
var vec3s, vec3e, vec3n, size, s, dist;
var pos = getPositions(line_.lPos, line_.drawRange.count, kof_);
positions.push.apply(positions, pos);
return result;
}
function getKey(_0x3fc717){return atob(_0x3fc717);}
function lerpFloat(v0_, v1_, t_) { return v0_ + (v1_ - v0_) * t_; }
function remapFloat(v_, min0_, max0_, min1_, max1_) { return min1_ + (v_ - min0_) / (max0_ - min0_) * (max1_ - min1_); }
Number.prototype.between = function (domain_) {
var min = Math.min.apply(Math, domain_);
var max = Math.max.apply(Math, domain_);
return this >= min && this <= max;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Goldsmith Student Commute Routes Mock-up</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<meta name="author" content="Vladimir V. KUCHINOV">
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.1.0/mapbox-gl.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/106/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
#map {
position:absolute;
width: 100%;
height: 100%;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="app.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment