[READ-ONLY] Mirror of https://github.com/flo-bit/tiny-planets. procedurally generated tiny planets in the browsers flo-bit.dev/tiny-planets/
low-poly planets procedural-generation threejs
0

Configure Feed

Select the types of activity you want to include in your feed.

tiny-planets / src / script.ts
3.5 kB 141 lines
1import * as THREE from "three"; 2import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; 3import { Planet } from "./worlds/planet"; 4import { Stars } from "./worlds/stars"; 5import { planetPresets } from "./worlds/presets"; 6 7const presets = ["beach", "forest", "snowForest"]; 8 9const width = window.innerWidth, 10 height = window.innerHeight; 11 12const canvas = document.getElementById("root"); 13 14if (!canvas) { 15 throw new Error("Canvas not found"); 16} 17const scene = new THREE.Scene(); 18const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 30); 19camera.position.set(0, 0, 2.5); 20 21const renderer = new THREE.WebGLRenderer({ 22 antialias: true, 23 canvas, 24 alpha: true, 25}); 26 27renderer.toneMapping = THREE.ACESFilmicToneMapping; 28renderer.shadowMap.enabled = true; 29 30const _ = new OrbitControls(camera, renderer.domElement); 31 32let hasPlanet = false; 33 34let sphereGeometry = new THREE.IcosahedronGeometry(1, 20); 35let sphereMaterial = new THREE.MeshStandardMaterial({ 36 color: "white", 37 wireframe: true, 38 wireframeLinewidth: 10, 39}); 40let planetMesh: THREE.Mesh = new THREE.Mesh(sphereGeometry, sphereMaterial); 41scene.add(planetMesh); 42 43const light = new THREE.DirectionalLight(); 44light.intensity = 2; 45light.position.set(2, 1, 0); 46scene.add(light); 47light.castShadow = true; 48light.shadow.mapSize.width = 512; 49light.shadow.mapSize.height = 512; 50light.shadow.camera.far = 10; 51light.shadow.camera.near = 0.1; 52 53light.shadow.bias = 0.01; 54light.shadow.camera.top = 2; 55light.shadow.camera.right = 2; 56light.shadow.camera.bottom = -2; 57light.shadow.camera.left = -2; 58 59const ambientLight = new THREE.AmbientLight(0xffffff, 0.1); 60scene.add(ambientLight); 61 62let total = 0; 63let lastDelta = 0; 64 65let rotate = true; 66renderer.setAnimationLoop((delta) => { 67 renderer.render(scene, camera); 68 69 if (rotate) planetMesh.rotation.y += 0.001; 70 71 if (lastDelta > 0) { 72 total += delta - lastDelta; 73 } 74 lastDelta = delta; 75 76 if (!hasPlanet) { 77 console.log("Creating planet"); 78 createPlanet("beach"); 79 hasPlanet = true; 80 } 81}); 82 83let stars = new Stars(); 84 85scene.add(stars); 86 87// add keydown event listener 88document.addEventListener("keydown", (event) => { 89 if (event.key === "1") { 90 createPlanet("beach"); 91 } else if (event.key === "2") { 92 createPlanet("forest"); 93 } else if (event.key === "3") { 94 createPlanet("snowForest"); 95 } 96 97 if (event.key === " ") { 98 rotate = !rotate; 99 } 100}); 101 102// button press 103let button = document.getElementById("button"); 104if (button) { 105 console.log("Button found"); 106 button.addEventListener("click", () => { 107 let randomPreset = presets[Math.floor(Math.random() * presets.length)]; 108 createPlanet(randomPreset); 109 }); 110} 111 112async function createPlanet(preset: string | undefined = undefined) { 113 if (!preset) { 114 preset = presets[Math.floor(Math.random() * presets.length)]; 115 } 116 117 console.time("planet"); 118 const planet = new Planet({ 119 detail: 50, 120 ...planetPresets[preset], 121 }); 122 let mesh = await planet.create(); 123 scene.remove(planetMesh); 124 scene.add(mesh); 125 planetMesh = mesh; 126 127 // planetMesh.add(camera); 128 // planet.updatePosition(camera, new THREE.Vector3(0, 0, 1.1)); 129 130 console.timeEnd("planet"); 131} 132 133function updateSize() { 134 renderer.setSize(window.innerWidth, window.innerHeight); 135 renderer.setPixelRatio(window.devicePixelRatio); 136 camera.aspect = window.innerWidth / window.innerHeight; 137 camera.updateProjectionMatrix(); 138} 139 140updateSize(); 141window.addEventListener("resize", updateSize);