Created
November 28, 2022 15:32
-
-
Save HarryStevens/87f0df7cc8ddf5daa3fd0ebf600f0083 to your computer and use it in GitHub Desktop.
THREE.js Globe
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
license: gpl-3.0 |
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> | |
<style> | |
body { | |
margin: 0; | |
overflow: hidden; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="scene"></div> | |
<div id="stats"></div> | |
<script src="https://unpkg.com/[email protected]/build/three.js"></script> | |
<script src="https://unpkg.com/[email protected]/examples/js/libs/stats.min.js"></script> | |
<script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script> | |
<script> | |
const stats = (_ => { | |
const stats = new Stats(); | |
stats.domElement.style.position = "absolute"; | |
stats.domElement.style.left = "0px"; | |
stats.domElement.style.top = "0px"; | |
document.getElementById("stats").appendChild(stats.domElement); | |
return stats; | |
})(); | |
const scene = new THREE.Scene(); | |
const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.1, 1000); | |
const renderer = (_ => { | |
const renderer = new THREE.WebGLRenderer(); | |
renderer.setClearColor("#fff"); | |
renderer.setPixelRatio(devicePixelRatio); | |
document.getElementById("scene").appendChild(renderer.domElement); | |
return renderer; | |
})(); | |
const loader = new THREE.TextureLoader(); | |
const globe = (_ => { | |
const geo = new THREE.SphereGeometry(4, 64, 64); | |
const mat = new THREE.MeshBasicMaterial({ | |
map: loader.load("./earth.png") | |
}); | |
const globe = new THREE.Mesh(geo, mat); | |
scene.add(globe); | |
return globe; | |
})(); | |
const controls = (_ => { | |
const controls = new THREE.OrbitControls(camera, renderer.domElement); | |
controls.enableDamping = true; | |
controls.dampingFactor = 0.1; | |
controls.autoRotate = true; | |
return controls; | |
})(); | |
function animate(){ | |
requestAnimationFrame(animate); | |
stats.update(); | |
controls.update(); | |
renderer.render(scene, camera); | |
} | |
animate(); | |
function size(){ | |
camera.aspect = innerWidth / innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize(innerWidth, innerHeight); | |
camera.position.z = cameraZ(camera, globe); | |
// Disable zooming | |
controls.maxDistance = camera.position.z; | |
controls.minDistance = camera.position.z; | |
} | |
size(); | |
onresize = size; | |
// Adapted from https://wejn.org/2020/12/cracking-the-threejs-object-fitting-nut/ | |
function cameraZ(camera, object){ | |
const boundingBox = new THREE.Box3(); | |
boundingBox.setFromObject(object); | |
const fov = camera.fov * (Math.PI / 180); | |
const fovh = 2 * Math.atan(Math.tan(fov / 2) * camera.aspect); | |
const size = new THREE.Vector3(); | |
boundingBox.getSize(size); | |
const dx = Math.abs(size.x / 2 / Math.tan(fovh / 2)); | |
const dy = Math.abs(size.y / 2 / Math.tan(fov / 2)); | |
const zDenominator = 10; // used to be 2 | |
return size.z / zDenominator + Math.max(dx, dy); | |
}; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment