Last active
November 8, 2019 08:41
-
-
Save vkuchinov/53bb0fbd556c03f702c44fd48ab724eb to your computer and use it in GitHub Desktop.
MapboxGL | THREE.JS + GLSL Shader
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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