Skip to content

Instantly share code, notes, and snippets.

@HarryStevens
Created November 28, 2022 15:32
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 HarryStevens/87f0df7cc8ddf5daa3fd0ebf600f0083 to your computer and use it in GitHub Desktop.
Save HarryStevens/87f0df7cc8ddf5daa3fd0ebf600f0083 to your computer and use it in GitHub Desktop.
THREE.js Globe
license: gpl-3.0
<!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/three@0.146.0/build/three.js"></script>
<script src="https://unpkg.com/three@0.146.0/examples/js/libs/stats.min.js"></script>
<script src="https://unpkg.com/three@0.146.0/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