Scene Graph: A Mini Solar System

Scene Graph: A Mini Solar System

A mini solar system with orbiting planets

The scene graph is the hierarchy that holds every object in a Three.js scene. Objects can be children of other objects, and a child moves, rotates and scales with its parent. This is the key to building complex systems — here it powers a miniature solar system where planets orbit a glowing sun.

The Big Idea: Parenting

Put a planet inside an empty Group (the "orbit"). Rotate the group and the planet revolves around the group's centre — no complex path math needed. The planet effectively inherits the orbit's rotation while we only ever move the group.

Full Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Three.js – Mini Solar System</title>
  <style>body{margin:0;overflow:hidden;background:#05070d}</style>
</head>
<body>
  <script type="importmap">
    { "imports": {
        "three": "https://unpkg.com/three@0.160.0/build/three.module.js",
        "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
    } }
  </script>
  <script type="module">
    import * as THREE from 'three';

const scene = new THREE.Scene(); scene.background = new THREE.Color(0x05070d);

const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 1000); camera.position.set(0, 9, 14); camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(innerWidth, innerHeight); document.body.appendChild(renderer.domElement);

scene.add(new THREE.AmbientLight(0x404040)); const dir = new THREE.DirectionalLight(0xffffff, 1); dir.position.set(5, 8, 4); scene.add(dir);

const sunLight = new THREE.PointLight(0xffe6b3, 2, 40); scene.add(sunLight); const sun = new THREE.Mesh( new THREE.SphereGeometry(1.4, 32, 16), new THREE.MeshBasicMaterial({ color: 0xffcf5e }) ); scene.add(sun);

function makeOrbit(radius, size, color, speed) { const orbit = new THREE.Group(); const planet = new THREE.Mesh( new THREE.SphereGeometry(size, 24, 12), new THREE.MeshStandardMaterial({ color }) ); planet.position.x = radius; orbit.add(planet); scene.add(orbit); const ring = new THREE.Mesh( new THREE.RingGeometry(radius - 0.05, radius + 0.05, 64).rotateX(-Math.PI / 2), new THREE.MeshBasicMaterial({ color: 0x232c40, transparent: true, opacity: 0.4 }) ); scene.add(ring); return { group: orbit, speed }; }

const mercury = makeOrbit(2.6, 0.25, 0x9b9b9b, 0.9); const venus = makeOrbit(3.8, 0.4, 0xf2c94c, 0.7); const earth = makeOrbit(5.0, 0.45, 0x2f80ed, 0.5);

const clock = new THREE.Clock(); function animate() { requestAnimationFrame(animate); const t = clock.getElapsedTime(); mercury.group.rotation.z = t * mercury.speed; venus.group.rotation.z = t * venus.speed; earth.group.rotation.z = t * earth.speed; sun.rotation.y = t * 0.2; renderer.render(scene, camera); } animate(); </script> </body> </html>

Building One Orbit

The reusable makeOrbit(radius, size, color, speed) function builds one planet system:

1. Create an empty Group — this is the invisible "orbit". 2. Create the planet mesh and set planet.position.x = radius — parked at the correct distance on the X axis. 3. orbit.add(planet) makes the planet a child of the orbit. 4. scene.add(orbit) adds the whole system to the scene. 5. Draw a semi-transparent ring (RingGeometry) on the ground to show the orbital path.

Because the planet is a child of the orbit, when we later write orbit.rotation.z = ..., the planet circles the sun. Its own position never changes — it just inherits the orbit's motion. That is the essence of parenting.

Orbiting in the Loop

Each frame we rotate each orbit around Z (t * speed), so every planet revolves at its own speed (Mercury fastest, Earth slowest — matching reality). The sun independently spins slowly, and a PointLight at the centre casts warm light onto the planets.

Try It Yourself

  • Add Mars: makeOrbit(6.2, 0.38, 0xeb5757, 0.4).
  • Make Earth orbit the other way: mercury.group.rotation.z = -t * mercury.speed.
  • Give a planet a moon: inside makeOrbit, add a tiny sphere positioned on X and rotate a second group.
  • Change orbital radii and watch planets cross in and out of view.

Summary

The scene graph lets objects inherit their parent's transforms. By nesting a planet inside a rotating Group, you get realistic orbital motion with almost no math. Groups + time-based rotation is a pattern you will reuse in the final capstone project.

Next Lesson

Your scenes are now moving and arranged. The next chapter brings interaction: the Raycaster lets you click exactly which object in the scene you want to pick up and highlight.

Quiz - Quiz - Scene Graph

1. To make a planet orbit a sun, the cleanest approach is to

2. In a scene graph, a child object

3. The material that emits its own light without needing a light source is

The Animation Loop and Clock