Last active
April 14, 2020 14:32
-
-
Save danvk/a1864cf1422ebc7958c8c76a2395db37 to your computer and use it in GitHub Desktop.
Repro of texture issue for MapboxGL and THREE.js
This file contains hidden or 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
token.js |
This file contains hidden or 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> | |
<body></body> | |
<script type="module" src="statue-three.js"></script> |
This file contains hidden or 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>Update a choropleth layer by zoom level</title> | |
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' /> | |
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.js'></script> | |
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.css' rel='stylesheet' /> | |
<style> | |
body { margin:0; padding:0; } | |
#map { position:absolute; top:0; bottom:0; width:100%; } | |
</style> | |
</head> | |
<body> | |
<div id='map'></div> | |
<script> | |
mapboxgl.accessToken = '<insert your token here>'; | |
</script> | |
<script src="token.js"></script> | |
<script src="statue-mapbox.js" type="module"></script> | |
</body> | |
</html> |
This file contains hidden or 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
import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js'; | |
import * as dat from 'https://unpkg.com/[email protected]/build/dat.gui.module.js'; | |
const {MercatorCoordinate} = mapboxgl; | |
const map = new mapboxgl.Map({ | |
container: 'map', | |
style: 'mapbox://styles/mapbox/light-v9', | |
center: [-74.0445, 40.6892], | |
zoom: 16, | |
pitch: 60, | |
bearing: 120, | |
}); | |
class DimensionGUIHelper { | |
constructor(obj, minProp, maxProp) { | |
this.obj = obj; | |
this.minProp = minProp; | |
this.maxProp = maxProp; | |
} | |
get value() { | |
return this.obj[this.maxProp] * 2; | |
} | |
set value(v) { | |
this.obj[this.maxProp] = v / 2; | |
this.obj[this.minProp] = v / -2; | |
} | |
} | |
class SpriteCustomLayer { | |
type = 'custom'; | |
renderingMode = '3d'; | |
constructor(id) { | |
this.id = id; | |
this.gui = new dat.GUI(); | |
THREE.Object3D.DefaultUp.set(0, 0, 1); | |
} | |
async onAdd(map, gl) { | |
this.camera = new THREE.Camera(); | |
const centerLngLat = map.getCenter(); | |
this.center = MercatorCoordinate.fromLngLat(centerLngLat, 0); | |
const {x, y, z} = this.center; | |
this.cameraTransform = new THREE.Matrix4() | |
.makeTranslation(x, y, z) | |
.scale(new THREE.Vector3(1, -1, 1)); | |
this.map = map; | |
this.scene = this.makeScene(); | |
// use the Mapbox GL JS map canvas for three.js | |
this.renderer = new THREE.WebGLRenderer({ | |
canvas: map.getCanvas(), | |
context: gl, | |
antialias: true, | |
}); | |
this.renderer.shadowMap.enabled = true; | |
this.renderer.autoClear = false; | |
} | |
makeScene() { | |
const scene = new THREE.Scene(); | |
scene.add(new THREE.AmbientLight(0xffffff, 0.25)); | |
const s = this.center.meterInMercatorCoordinateUnits(); | |
const light = new THREE.DirectionalLight(0xffffff, 1); | |
light.position.set(0.000002360847837325531, 0.000004566603480958114, 0.00000725142167844218); | |
light.target.position.set(0, 0, 0); | |
light.castShadow = true; | |
light.shadow.mapSize.width = 1024; | |
light.shadow.mapSize.height = 1024; | |
// light.shadow.radius *= s; | |
light.shadow.camera.left = -0.000002383416166278454 * 2; | |
light.shadow.camera.right = 0.000002383416166278454 * 2; | |
light.shadow.camera.bottom = -0.000002383416166278454 * 2; | |
light.shadow.camera.top = 0.000002383416166278454 * 2; | |
light.shadow.camera.near = 0.0000012388642793465356; | |
light.shadow.camera.far *= s; | |
console.log(light.shadow.camera.rotation.order); | |
// light.shadow.camera.zoom = s; | |
scene.add(light); | |
this.light = light; | |
const cameraHelper = new THREE.CameraHelper(light.shadow.camera); | |
scene.add(cameraHelper); | |
const lightHelper = new THREE.DirectionalLightHelper(light, 10 * s); | |
scene.add(lightHelper); | |
const update = () => { | |
light.target.updateMatrixWorld(); | |
lightHelper.update(); | |
light.shadow.camera.updateProjectionMatrix(); | |
cameraHelper.update(); | |
}; | |
let folder = this.gui.addFolder('light'); | |
folder.add(light.position, 'x', -1e-5, 1e-5).onChange(update); | |
folder.add(light.position, 'y', -1e-5, 1e-5).onChange(update); | |
folder.add(light.position, 'z', -1e-5, 1e-5).onChange(update); | |
folder.open(); | |
folder = this.gui.addFolder('shadow camera'); | |
folder | |
.add(new DimensionGUIHelper(light.shadow.camera, 'left', 'right'), 'value', s, 200 * s) | |
.name('width') | |
.onChange(update); | |
folder | |
.add(new DimensionGUIHelper(light.shadow.camera, 'bottom', 'top'), 'value', s, 200 * s) | |
.name('height') | |
.onChange(update); | |
folder.add(light.shadow.camera, 'zoom', 0.01, 1.5, 0.01).onChange(update); | |
folder.add(light.shadow.camera, 'near', 0, 1000 * s).onChange(update); | |
folder.add(light.shadow.camera, 'far', 0, 1000 * s).onChange(update); | |
folder.open(); | |
{ | |
const planeSize = 500; | |
const loader = new THREE.TextureLoader(); | |
const texture = loader.load('/checker.png'); | |
texture.wrapS = THREE.RepeatWrapping; | |
texture.wrapT = THREE.RepeatWrapping; | |
texture.magFilter = THREE.NearestFilter; | |
const repeats = 10; | |
texture.repeat.set(repeats, repeats); | |
const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize); | |
const planeMat = new THREE.MeshPhongMaterial({ | |
map: texture, | |
side: THREE.DoubleSide, | |
}); | |
const plane = new THREE.Mesh(planeGeo, planeMat); | |
plane.scale.setScalar(s); | |
plane.rotation.x = Math.PI; | |
plane.receiveShadow = true; | |
scene.add(plane); | |
} | |
{ | |
const sphereRadius = 5e-7; | |
const sphereGeo = new THREE.SphereBufferGeometry(sphereRadius, 32, 32); | |
const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'}); | |
const mesh = new THREE.Mesh(sphereGeo, sphereMat); | |
mesh.position.set(0, 0, 5e-6); | |
mesh.castShadow = true; | |
mesh.receiveShadow = false; | |
sphereMat.side = THREE.DoubleSide; | |
scene.add(mesh); | |
const folder = this.gui.addFolder('sphere'); | |
folder.add(mesh.position, 'x', -1e-5, 1e-5); | |
folder.add(mesh.position, 'y', -1e-5, 1e-5); | |
folder.add(mesh.position, 'z', -1e-5, 1e-5); | |
folder.open(); | |
} | |
return scene; | |
} | |
render(gl, matrix) { | |
this.camera.projectionMatrix = new THREE.Matrix4() | |
.fromArray(matrix) | |
.multiply(this.cameraTransform); | |
this.renderer.state.reset(); | |
this.renderer.render(this.scene, this.camera); | |
this.map.triggerRepaint(); | |
} | |
} | |
map.on('load', () => { | |
const layer = new SpriteCustomLayer('statue'); | |
map.addLayer(layer); | |
}); |
This file contains hidden or 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
import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js'; | |
import {OrbitControls} from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js'; | |
import {MTLLoader} from 'https://unpkg.com/[email protected]/examples/jsm/loaders/MTLLoader.js'; | |
import {MtlObjBridge} from 'https://unpkg.com/[email protected]/examples/jsm/loaders/obj2/bridge/MtlObjBridge.js'; | |
import {OBJLoader2} from 'https://unpkg.com/[email protected]/examples/jsm/loaders/OBJLoader2.js'; | |
var camera, scene, renderer; | |
init(); | |
animate(); | |
async function addOBJ(path, mtlPath) { | |
const loader = new OBJLoader2(); | |
const matLoader = new MTLLoader(); | |
matLoader.load(mtlPath, mtlParseResult => { | |
const materials = MtlObjBridge.addMaterialsFromMtlLoader(mtlParseResult); | |
loader.addMaterials(materials); | |
loader.load(path, group => { | |
scene.add(group); | |
}); | |
}); | |
} | |
function init() { | |
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.001, 1000 ); | |
camera.position.set(86, 100, -5); | |
scene = new THREE.Scene(); | |
scene.add(new THREE.AmbientLight( 0xffffff, 0.25 )); | |
for (const y of [-70, 70]) { | |
const directionalLight = new THREE.DirectionalLight(0xffffff); | |
directionalLight.position.set(0, y, 100).normalize(); | |
scene.add(directionalLight); | |
} | |
renderer = new THREE.WebGLRenderer( { antialias: true } ); | |
renderer.setSize( window.innerWidth, window.innerHeight ); | |
document.body.appendChild( renderer.domElement ); | |
const controls = new OrbitControls(camera, renderer.domElement); | |
controls.target.set(0, 0, 0); | |
controls.update(); | |
addOBJ('silo_p2.obj', 'silo_p2.mtl'); | |
} | |
function animate() { | |
requestAnimationFrame( animate ); | |
renderer.render( scene, camera ); | |
} |
This file contains hidden or 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> | |
<body></body> | |
<script type="module" src="statue-three.js"></script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment