Solar System Simulation STEM

Solar System Simulation STEM script details
Type
Typescript logo image
typescript
App Version
0.19.6
Visibility
public
Date Created
Mar 9, 2025, 9:21:44 AM
Last Edit Date
Mar 18, 2025, 12:09:17 PM

Script Details

The Code
async function start() { const scene = bitbybit.babylon.scene.getScene(); const engine = scene.getEngine(); // Setup point light with shadow generator const ptLight = new Bit.Inputs.BabylonScene.PointLightDto(); ptLight.intensity = 50000; ptLight.position = [0, 0, 0]; ptLight.shadowDarkness = 0; ptLight.radius = 0; ptLight.shadowMaxZ = 3000; ptLight.shadowMinZ = 0; const light = bitbybit.babylon.scene.drawPointLight(ptLight); // GUI Setup const advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI"); const hoverText = new BABYLON.GUI.TextBlock(); hoverText.text = ""; hoverText.color = "white"; hoverText.fontSize = 36; hoverText.fontFamily = "Arial"; hoverText.paddingTop = "15px"; hoverText.paddingBottom = "15px"; hoverText.paddingLeft = "20px"; hoverText.paddingRight = "20px"; hoverText.isVisible = false; advancedTexture.addControl(hoverText); const speedSlider = new BABYLON.GUI.Slider(); speedSlider.minimum = 0.05; speedSlider.maximum = 1.0; speedSlider.value = 0.05; speedSlider.step = 0.01; speedSlider.height = "30px"; speedSlider.width = "300px"; speedSlider.left = "30px"; speedSlider.top = "30px"; speedSlider.color = "#f0cebb"; speedSlider.background = "rgba(255, 255, 255, 0.2)"; speedSlider.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; speedSlider.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP; advancedTexture.addControl(speedSlider); const sliderLabel = new BABYLON.GUI.TextBlock(); sliderLabel.text = "Animation Speed: " + speedSlider.value.toFixed(2) + "x"; sliderLabel.color = "white"; sliderLabel.fontSize = 24; sliderLabel.left = "30px"; sliderLabel.top = "70px"; sliderLabel.textHorizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; sliderLabel.textVerticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP; advancedTexture.addControl(sliderLabel); // Language selection buttons const languagePanel = new BABYLON.GUI.StackPanel(); languagePanel.isVertical = true; languagePanel.width = "150px"; languagePanel.left = "30px"; languagePanel.top = "110px"; languagePanel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; languagePanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP; advancedTexture.addControl(languagePanel); let currentLanguage = "en"; const languages = [ { name: "English", code: "en" }, { name: "Lietuvių", code: "lt" }, { name: "Polski", code: "pl" }, { name: "Deutsch", code: "de" }, { name: "Español", code: "es" }, { name: "中文", code: "zh" } ]; const languageButtons = languages.map(lang => { const button = BABYLON.GUI.Button.CreateSimpleButton(`lang_${lang.code}`, lang.name); button.width = "150px"; button.height = "30px"; button.color = "white"; button.background = "rgba(255, 255, 255, 0.2)"; button.paddingBottom = "5px"; button.onPointerUpObservable.add(() => { currentLanguage = lang.code; // Update button visuals to show selection languageButtons.forEach(btn => { btn.background = "rgba(255, 255, 255, 0.2)"; btn.color = "#ffffff"; }); button.background = "#f0cebb"; // Highlight selected language button.color = "#000000"; // Highlight selected language }); if (lang.code === "en") button.background = "#f0cebb55"; // Default to English languagePanel.addControl(button); return button; }); createLogo(); speedSlider.onValueChangedObservable.add((value) => { sliderLabel.text = "Animation Speed: " + value.toFixed(2) + "x"; }); // Language translations const translations = { "en": { "Sun": "Sun", "Mercury": "Mercury", "Venus": "Venus", "Earth": "Earth", "Moon": "Moon", "Mars": "Mars", "Phobos": "Phobos", "Deimos": "Deimos", "Jupiter": "Jupiter", "Io": "Io", "Europa": "Europa", "Ganymede": "Ganymede", "Callisto": "Callisto", "Saturn": "Saturn", "Mimas": "Mimas", "Enceladus": "Enceladus", "Tethys": "Tethys", "Dione": "Dione", "Rhea": "Rhea", "Titan": "Titan", "Iapetus": "Iapetus", "Uranus": "Uranus", "Miranda": "Miranda", "Ariel": "Ariel", "Umbriel": "Umbriel", "Titania": "Titania", "Oberon": "Oberon", "Neptune": "Neptune", "Triton": "Triton", "Nereid": "Nereid" }, "lt": { "Sun": "Saulė", "Mercury": "Merkurijus", "Venus": "Venera", "Earth": "Žemė", "Moon": "Mėnulis", "Mars": "Marsas", "Phobos": "Fobas", "Deimos": "Deimas", "Jupiter": "Jupiteris", "Io": "Io", "Europa": "Europa", "Ganymede": "Ganimedas", "Callisto": "Kalista", "Saturn": "Saturnas", "Mimas": "Mimas", "Enceladus": "Enceladas", "Tethys": "Tetija", "Dione": "Dionė", "Rhea": "Rėja", "Titan": "Titanas", "Iapetus": "Iapetas", "Uranus": "Uranas", "Miranda": "Miranda", "Ariel": "Arielė", "Umbriel": "Umbrielis", "Titania": "Titanija", "Oberon": "Oberonas", "Neptune": "Neptūnas", "Triton": "Tritonas", "Nereid": "Nereidė" }, "pl": { "Sun": "Słońce", "Mercury": "Merkury", "Venus": "Wenus", "Earth": "Ziemia", "Moon": "Księżyc", "Mars": "Mars", "Phobos": "Fobos", "Deimos": "Deimos", "Jupiter": "Jowisz", "Io": "Io", "Europa": "Europa", "Ganymede": "Ganimedes", "Callisto": "Kallisto", "Saturn": "Saturn", "Mimas": "Mimas", "Enceladus": "Enceladus", "Tethys": "Tetyda", "Dione": "Dione", "Rhea": "Rea", "Titan": "Tytan", "Iapetus": "Japetus", "Uranus": "Uran", "Miranda": "Miranda", "Ariel": "Ariel", "Umbriel": "Umbriel", "Titania": "Tytania", "Oberon": "Oberon", "Neptune": "Neptun", "Triton": "Tryton", "Nereid": "Nereida" }, "de": { "Sun": "Sonne", "Mercury": "Merkur", "Venus": "Venus", "Earth": "Erde", "Moon": "Mond", "Mars": "Mars", "Phobos": "Phobos", "Deimos": "Deimos", "Jupiter": "Jupiter", "Io": "Io", "Europa": "Europa", "Ganymede": "Ganymed", "Callisto": "Kallisto", "Saturn": "Saturn", "Mimas": "Mimas", "Enceladus": "Enceladus", "Tethys": "Tethys", "Dione": "Dione", "Rhea": "Rhea", "Titan": "Titan", "Iapetus": "Iapetus", "Uranus": "Uranus", "Miranda": "Miranda", "Ariel": "Ariel", "Umbriel": "Umbriel", "Titania": "Titania", "Oberon": "Oberon", "Neptune": "Neptun", "Triton": "Triton", "Nereid": "Nereid" }, "es": { "Sun": "Sol", "Mercury": "Mercurio", "Venus": "Venus", "Earth": "Tierra", "Moon": "Luna", "Mars": "Marte", "Phobos": "Fobos", "Deimos": "Deimos", "Jupiter": "Júpiter", "Io": "Ío", "Europa": "Europa", "Ganymede": "Ganímedes", "Callisto": "Calisto", "Saturn": "Saturno", "Mimas": "Mimas", "Enceladus": "Encélado", "Tethys": "Tetis", "Dione": "Dione", "Rhea": "Rea", "Titan": "Titán", "Iapetus": "Jápeto", "Uranus": "Urano", "Miranda": "Miranda", "Ariel": "Ariel", "Umbriel": "Umbriel", "Titania": "Titania", "Oberon": "Oberón", "Neptune": "Neptuno", "Triton": "Tritón", "Nereid": "Nereida" }, "zh": { "Sun": "太阳", "Mercury": "水星", "Venus": "金星", "Earth": "地球", "Moon": "月球", "Mars": "火星", "Phobos": "火卫一", "Deimos": "火卫二", "Jupiter": "木星", "Io": "木卫一", "Europa": "木卫二", "Ganymede": "木卫三", "Callisto": "木卫四", "Saturn": "土星", "Mimas": "土卫一", "Enceladus": "土卫二", "Tethys": "土卫三", "Dione": "土卫四", "Rhea": "土卫五", "Titan": "土卫六", "Iapetus": "土卫八", "Uranus": "天王星", "Miranda": "天卫五", "Ariel": "天卫一", "Umbriel": "天卫二", "Titania": "天卫三", "Oberon": "天卫四", "Neptune": "海王星", "Triton": "海卫一", "Nereid": "海卫二" } }; // Sun Vertex Shader BABYLON.Effect.ShadersStore["sunVertexShader"] = ` precision highp float; attribute vec3 position; attribute vec3 normal; uniform mat4 world; uniform mat4 worldViewProjection; varying vec3 vPosition; varying vec3 vNormal; varying vec3 vWorldPosition; void main() { gl_Position = worldViewProjection * vec4(position, 1.0); vPosition = position; vWorldPosition = (world * vec4(position, 1.0)).xyz; vNormal = normalize((world * vec4(normal, 0.0)).xyz); } `; // Sun Fragment Shader BABYLON.Effect.ShadersStore["sunFragmentShader"] = ` precision highp float; varying vec3 vPosition; varying vec3 vNormal; varying vec3 vWorldPosition; uniform float time; uniform vec3 cameraPosition; float hash(vec3 p) { return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453); } float noise(vec3 p) { vec3 i = floor(p); vec3 f = fract(p); vec3 u = f * f * (3.0 - 2.0 * f); return mix(mix(mix(hash(i + vec3(0.0,0.0,0.0)), hash(i + vec3(1.0,0.0,0.0)), u.x), mix(hash(i + vec3(0.0,1.0,0.0)), hash(i + vec3(1.0,1.0,0.0)), u.x), u.y), mix(mix(hash(i + vec3(0.0,0.0,1.0)), hash(i + vec3(1.0,0.0,1.0)), u.x), mix(hash(i + vec3(0.0,1.0,1.0)), hash(i + vec3(1.0,1.0,1.0)), u.x), u.y), u.z); } float fbm(vec3 p) { float v = 0.0; float a = 0.5; vec3 shift = vec3(100.0); for (int i = 0; i < 4; ++i) { v += a * noise(p); p = p * 2.0 + shift; a *= 0.5; } return v; } void main() { vec3 pos = normalize(vPosition); vec2 sphericalUV = vec2(atan(pos.z, pos.x), asin(pos.y)); sphericalUV.x = sphericalUV.x * 0.159154943 + 0.5; sphericalUV.y = sphericalUV.y * 0.318309886 + 0.5; vec3 baseColor = mix(vec3(1.0, 0.9, 0.4), vec3(1.0, 0.5, 0.1), length(sphericalUV - 0.5)); float spots = fbm(pos * 8.0 + time * 0.1); spots = pow(spots, 3.0); vec3 spotColor = vec3(0.8, 0.4, 0.1) * spots; float detail = fbm(pos * 20.0 + time * 0.05); vec3 detailColor = vec3(0.2, 0.1, 0.0) * detail; vec3 viewDir = normalize(cameraPosition - vWorldPosition); float rim = 1.0 - max(dot(vNormal, viewDir), 0.0); vec3 finalColor = baseColor; finalColor = mix(finalColor, spotColor, spots * 0.8); finalColor += detailColor; finalColor += vec3(1.0, 0.8, 0.2) * pow(rim, 1.5) * 0.4; float pulse = sin(time * 1.5) * 0.03 + 0.97; finalColor *= pulse; gl_FragColor = vec4(finalColor, 1.0); } `; // Space Vertex Shader BABYLON.Effect.ShadersStore["spaceVertexShader"] = ` precision highp float; attribute vec3 position; attribute vec3 normal; uniform mat4 world; uniform mat4 view; uniform mat4 projection; varying vec3 vPosition; varying vec3 vNormal; void main() { vPosition = position; vNormal = normal; gl_Position = projection * view * world * vec4(position, 1.0); } `; // Space Fragment Shader BABYLON.Effect.ShadersStore["spaceFragmentShader"] = ` precision highp float; varying vec3 vPosition; uniform float time; float hash(vec3 p) { p = fract(p * 0.3183099 + 0.1); return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453); } float noise(vec3 x) { vec3 i = floor(x); vec3 f = fract(x); f = f * f * (3.0 - 2.0 * f); return mix(mix(mix(hash(i + vec3(0.0, 0.0, 0.0)), hash(i + vec3(1.0, 0.0, 0.0)), f.x), mix(hash(i + vec3(0.0, 1.0, 0.0)), hash(i + vec3(1.0, 1.0, 0.0)), f.x), f.y), mix(mix(hash(i + vec3(0.0, 0.0, 1.0)), hash(i + vec3(1.0, 0.0, 1.0)), f.x), mix(hash(i + vec3(0.0, 1.0, 1.0)), hash(i + vec3(1.0, 1.0, 1.0)), f.x), f.y), f.z); } float fbm(vec3 p) { float v = 0.0; float a = 0.5; vec3 shift = vec3(100.0); for (int i = 0; i < 2; ++i) { v += a * noise(p); p = p * 2.0 + shift; a *= 0.5; } return v; } void main() { vec3 pos = normalize(vPosition) * 10.0 + vec3(time * 0.01); float stars = noise(pos * 100.0); stars = pow(stars, 40.0); float nebula = fbm(pos * 0.5); vec3 nebulaColor = vec3(0.3, 0.2, 0.7) * nebula * 0.8; vec3 color = vec3(0.0); color += vec3(0.8, 0.8, 0.9) * stars; color += nebulaColor; color = mix(vec3(0.0, 0.0, 0.05), color, clamp(color.r + color.g + color.b, 0.0, 1.0)); gl_FragColor = vec4(color, 1.0); } `; // Space background const shaderMaterialSpace = new BABYLON.ShaderMaterial("spaceShader", scene, { vertex: "space", fragment: "space", }, { attributes: ["position", "normal"], uniforms: ["world", "view", "projection", "time"] }); const box = BABYLON.MeshBuilder.CreateBox("box", { size: 10000 }, scene); box.material = shaderMaterialSpace; box.flipFaces(); // Scaling factors const AU = 30; const planetScale = 1; const moonScale = 1; // Sun setup const sun = BABYLON.MeshBuilder.CreateSphere("sun", { diameter: 5 * planetScale, segments: 128 }, scene); const sunMaterial = new BABYLON.ShaderMaterial("sunShader", scene, { vertex: "sun", fragment: "sun", }, { attributes: ["position", "normal"], uniforms: ["world", "worldViewProjection", "time", "cameraPosition"] }); sunMaterial.setVector3("cameraPosition", scene.activeCamera.position); sun.material = sunMaterial; const sgs = scene.metadata.shadowGenerators; // sgs.forEach(shadowGenerator => { // shadowGenerator.addShadowCaster(sun); // }); // Celestial body definitions const celestialData = [ { name: "Mercury", diameter: 0.8, orbit: 0.4, speed: 2.0, color: [0.7, 0.7, 0.7], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.06, moons: [] }, { name: "Venus", diameter: 1.8, orbit: 0.7, speed: 0.8, color: [0.9, 0.6, 0.3], metallic: 0.05, roughness: 0.6, rotationSpeed: 0.04, moons: [] }, { name: "Earth", diameter: 1.8, orbit: 1, speed: 0.5, color: [0.0, 0.6, 0.8], metallic: 0.0, roughness: 0.5, rotationSpeed: 0.05, moons: [{ name: "Moon", diameter: 0.5, orbit: 2, speed: 4, color: [0.8, 0.8, 0.8], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.02 }] }, { name: "Mars", diameter: 1.5, orbit: 1.5, speed: 0.4, color: [0.8, 0.4, 0.2], metallic: 0.1, roughness: 0.7, rotationSpeed: 0.03, moons: [ { name: "Phobos", diameter: 0.3, orbit: 1, speed: 3, color: [0.6, 0.5, 0.5], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.04 }, { name: "Deimos", diameter: 0.2, orbit: 1.5, speed: 2.5, color: [0.7, 0.6, 0.6], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.03 } ] }, { name: "Jupiter", diameter: 4, orbit: 5, speed: 0.2, color: [0.9, 0.7, 0.5], metallic: 0.0, roughness: 0.4, rotationSpeed: 0.02, moons: [ { name: "Io", diameter: 0.7, orbit: 2, speed: 2.5, color: [1.0, 0.8, 0.3], metallic: 0.1, roughness: 0.7, rotationSpeed: 0.03 }, { name: "Europa", diameter: 0.6, orbit: 3, speed: 2, color: [0.9, 0.9, 0.9], metallic: 0.0, roughness: 0.3, rotationSpeed: 0.025 }, { name: "Ganymede", diameter: 1.0, orbit: 4, speed: 1.5, color: [0.7, 0.7, 0.7], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.02 }, { name: "Callisto", diameter: 0.9, orbit: 5, speed: 1, color: [0.6, 0.6, 0.6], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.015 } ] }, { name: "Saturn", diameter: 3.5, orbit: 9.5, speed: 0.15, color: [0.8, 0.7, 0.4], metallic: 0.0, roughness: 0.4, rotationSpeed: 0.015, rings: { radius: 5, color: [0.7, 0.6, 0.5], metallic: 0.0, roughness: 0.6 }, moons: [ { name: "Mimas", diameter: 0.3, orbit: 1, speed: 3, color: [0.8, 0.8, 0.8], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.04 }, { name: "Enceladus", diameter: 0.4, orbit: 1.5, speed: 2.5, color: [0.9, 0.9, 0.9], metallic: 0.0, roughness: 0.3, rotationSpeed: 0.035 }, { name: "Tethys", diameter: 0.5, orbit: 2, speed: 2, color: [0.8, 0.8, 0.8], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.03 }, { name: "Dione", diameter: 0.6, orbit: 2.5, speed: 1.8, color: [0.7, 0.7, 0.7], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.025 }, { name: "Rhea", diameter: 0.7, orbit: 3, speed: 1.5, color: [0.8, 0.8, 0.8], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.02 }, { name: "Titan", diameter: 1.0, orbit: 4, speed: 1, color: [0.9, 0.6, 0.3], metallic: 0.0, roughness: 0.5, rotationSpeed: 0.015 }, { name: "Iapetus", diameter: 0.8, orbit: 5, speed: 0.8, color: [0.5, 0.5, 0.5], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.01 } ] }, { name: "Uranus", diameter: 3, orbit: 19, speed: 0.1, color: [0.5, 0.8, 0.8], metallic: 0.0, roughness: 0.4, rotationSpeed: 0.012, moons: [ { name: "Miranda", diameter: 0.3, orbit: 1, speed: 3, color: [0.7, 0.7, 0.7], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.04 }, { name: "Ariel", diameter: 0.5, orbit: 1.5, speed: 2.5, color: [0.8, 0.8, 0.8], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.035 }, { name: "Umbriel", diameter: 0.6, orbit: 2, speed: 2, color: [0.6, 0.6, 0.6], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.03 }, { name: "Titania", diameter: 0.8, orbit: 3, speed: 1.5, color: [0.7, 0.7, 0.7], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.02 }, { name: "Oberon", diameter: 0.7, orbit: 4, speed: 1, color: [0.6, 0.6, 0.6], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.015 } ] }, { name: "Neptune", diameter: 3, orbit: 30, speed: 0.08, color: [0.2, 0.4, 0.8], metallic: 0.0, roughness: 0.4, rotationSpeed: 0.01, moons: [ { name: "Triton", diameter: 0.9, orbit: 3, speed: 1.5, color: [0.7, 0.7, 0.8], metallic: 0.1, roughness: 0.8, rotationSpeed: 0.02 }, { name: "Nereid", diameter: 0.3, orbit: 5, speed: 0.5, color: [0.6, 0.6, 0.7], metallic: 0.1, roughness: 0.9, rotationSpeed: 0.01 } ] } ]; // Utility functions const createOrbitPath = (radius, parent = null, segments = 128) => { const path = []; for (let i = 0; i <= segments; i++) { const angle = (i / segments) * Math.PI * 2; path.push(new BABYLON.Vector3(Math.cos(angle) * radius, 0, Math.sin(angle) * radius)); } const orbit = BABYLON.MeshBuilder.CreateLines(`orbit_${radius}`, { points: path }, scene); orbit.color = new BABYLON.Color3(0.5, 0.5, 0.5); orbit.alpha = 0.5; orbit.visibility = 0.1; if (parent) orbit.parent = parent; return orbit; }; const createBody = (name, diameter, color, metallic, roughness, isMoon = false) => { const mesh = BABYLON.MeshBuilder.CreateSphere(name, { diameter: (isMoon ? moonScale : planetScale) * diameter, segments: 32 }, scene); const mat = new BABYLON.PBRMetallicRoughnessMaterial(`${name}Mat`, scene); mat.baseColor = new BABYLON.Color3(...color); mat.metallic = metallic; mat.roughness = roughness; mat.backFaceCulling = false; mesh.material = mat; mesh.receiveShadows = true; // sgs.forEach(shadowGenerator => { // shadowGenerator.addShadowCaster(mesh); // }); return mesh; }; // Create celestial bodies const celestialBodies = [{ mesh: sun, name: "Sun" }]; const planets = celestialData.map(planet => { const mesh = createBody(planet.name, planet.diameter, planet.color, planet.metallic, planet.roughness); mesh.position.x = AU * planet.orbit; createOrbitPath(AU * planet.orbit); if (planet.rings) { const ringMat = new BABYLON.PBRMetallicRoughnessMaterial("ringMat", scene); ringMat.baseColor = new BABYLON.Color3(...planet.rings.color); ringMat.metallic = planet.rings.metallic; ringMat.roughness = planet.rings.roughness; ringMat.backFaceCulling = true; const ring = BABYLON.MeshBuilder.CreateDisc("ring", { radius: planet.rings.radius * planetScale, tessellation: 64 }, scene); ring.rotation.x = Math.PI / 2; ring.parent = mesh; ring.material = ringMat; ring.receiveShadows = true; } const moons = planet.moons.map(moon => { const moonMesh = createBody(moon.name, moon.diameter, moon.color, moon.metallic, moon.roughness, true); moonMesh.position.x = AU * planet.orbit + moon.orbit; createOrbitPath(moon.orbit, mesh); return { mesh: moonMesh, data: moon }; }); celestialBodies.push({ mesh, name: planet.name }); moons.forEach(moon => celestialBodies.push({ mesh: moon.mesh, name: moon.data.name })); return { mesh, data: planet, moons }; }); // Setup pointer events with language support const updateHoverText = (body, language) => { hoverText.text = translations[language][body.name] || body.name; }; // Setup pointer events celestialBodies.forEach(body => { body.mesh.actionManager = new BABYLON.ActionManager(scene); body.mesh.actionManager.registerAction( new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOverTrigger, () => { updateHoverText(body, currentLanguage); hoverText.isVisible = true; }) ); body.mesh.actionManager.registerAction( new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOutTrigger, () => { hoverText.isVisible = false; }) ); }); const canvas = engine.getRenderingCanvas(); const scalingFactor = 1 / engine.getHardwareScalingLevel(); scene.onPointerObservable.add((pointerInfo) => { if (hoverText.isVisible) { const rect = canvas.getBoundingClientRect(); const x = (pointerInfo.event.x - rect.width / 2) * scalingFactor; const y = (pointerInfo.event.y - rect.height / 2) * scalingFactor; hoverText.left = x + 60 + "px"; hoverText.top = y - 60 + "px"; } }, BABYLON.PointerEventTypes.POINTERMOVE); // Animation let time = 0; let twinkleTime = 0; bitbybit.time.registerRenderFunction(() => { const speedFactor = speedSlider.value; time += engine.getDeltaTime() * 0.001 * speedFactor; twinkleTime += 0.001; sunMaterial.setFloat("time", twinkleTime * 40); sunMaterial.setVector3("cameraPosition", scene.activeCamera.position); shaderMaterialSpace.setFloat("time", twinkleTime); sun.rotation.y += 0.01 * speedFactor; planets.forEach(planet => { const p = planet.data; planet.mesh.position.x = Math.cos(time * p.speed) * AU * p.orbit; planet.mesh.position.z = Math.sin(time * p.speed) * AU * p.orbit; planet.mesh.rotation.y += p.rotationSpeed * speedFactor; planet.moons.forEach(moon => { const m = moon.data; moon.mesh.position.x = planet.mesh.position.x + Math.cos(time * m.speed) * m.orbit; moon.mesh.position.z = planet.mesh.position.z + Math.sin(time * m.speed) * m.orbit; moon.mesh.rotation.y += m.rotationSpeed * speedFactor; }); }); }); // Add HDR Glow Effect const glowLayer = new BABYLON.GlowLayer("glow", scene, { // mainTextureFixedSize: 1024, mainTextureRatio: 1, // Adjust for performance vs quality blurKernelSize: 32, // Larger kernel for softer glow }); glowLayer.intensity = 0.22; glowLayer.addExcludedMesh(box); // Exclude the background box from glowing glowLayer.referenceMeshToUseItsOwnMaterial(sun); } function createLogo() { const gui = bitbybit.babylon.gui; const textOpt = new Bit.Inputs.BabylonGui.CreateFullScreenUIDto(); const fullScreenUI = gui.advancedDynamicTexture.createFullScreenUI(textOpt); const stackPanelOpt = new Bit.Inputs.BabylonGui.CreateStackPanelDto(); stackPanelOpt.background = "#00000000"; const stackPanel = gui.stackPanel.createStackPanel(stackPanelOpt); const stackPanelOpt2 = new Bit.Inputs.BabylonGui.CreateStackPanelDto(); stackPanelOpt2.background = "#00000000"; const stackPanel2 = gui.stackPanel.createStackPanel(stackPanelOpt2); stackPanel2.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_BOTTOM; fullScreenUI.addControl(stackPanel2); stackPanel.paddingTopInPixels = 10; stackPanel2.addControl(stackPanel); const imageOpt = new Bit.Inputs.BabylonGui.CreateImageDto(); imageOpt.url = "assets/logo-gold-small.png"; const image = gui.image.createImage(imageOpt); const padding = 30; image.paddingTopInPixels = padding; image.paddingBottomInPixels = padding; image.paddingLeftInPixels = padding; image.paddingRightInPixels = padding; image.onPointerClickObservable.add(() => { window.open("https://bitbybit.dev", '_blank').focus(); }); const txtBlockOptions = new Bit.Inputs.BabylonGui.CreateTextBlockDto(); txtBlockOptions.text = "BITBYBIT.DEV"; const txtBlock = gui.textBlock.createTextBlock(txtBlockOptions); txtBlock.height = "60px"; txtBlock.paddingBottomInPixels = 30; stackPanel2.addControl(image); stackPanel2.addControl(txtBlock); } start().catch(console.error);