Journal

Interactive Solar System 3D Viewer in SwiftUI

Orbits are rotations, not trigonometry. Texture sells it, and nothing watchable is ever fully to scale.

Interactive Solar System 3D Viewer in SwiftUI: a phone toggle icon surrounded by location, calendar, settings, wallet and chart app icons on a coral gradient

TL;DR

An interactive solar system viewer in SwiftUI uses RealityView with RealityKit (the modern path; Model3D for a single USDZ, SceneKit only for legacy): a parent Sun entity, each planet a child whose orbit is the rotation of an invisible pivot rather than per-frame trigonometry, with moons nesting the same way. Texture is what separates it from colored marbles, NASA albedo maps, an emissive Sun, Saturn's rings as a textured alpha disc. No watchable model is fully to scale, so pick the scale cheat deliberately and label it. Tap-to-focus plus an info panel turns the screensaver into an app. A free VP0 design supplies the cards and controls to build the scene under.

What renders the planets, and what is the honest scope?

RealityKit on the modern path, SceneKit on the legacy one, and the scope question matters before either: a solar-system viewer is gorgeous and finite, so decide early whether it is an accurate model or a beautiful toy, because the two have different data and different physics. Both are legitimate; pretending a toy is accurate is the trap.

RealityKit is Apple’s current 3D framework and the right default for a new build: it renders physically-based materials, runs on iOS and visionOS, and drops into SwiftUI through RealityView. SceneKit still works and has more tutorials, but it is the aging path. For a quick single-model drop-in, SwiftUI’s Model3D loads a USDZ with almost no code; for an interactive system of orbiting bodies you want the full RealityView with entities you control.

How do you build the system itself?

As a parent-child entity hierarchy where orbits are rotations, not position math. The clean structure: an anchor holds the Sun, each planet is a child entity, and a planet’s orbit is the rotation of an invisible parent pivot around the Sun rather than per-frame trigonometry on x and y. Spin the pivot, the planet circles; rotate the planet entity itself, it spins on its axis. Two transforms, no orbital math, and moons nest the same way under their planet.

RealityView { content in
    let sun = ModelEntity(mesh: .generateSphere(radius: 0.3),
                          materials: [sunMaterial])
    for planet in planets {
        let pivot = Entity()                 // orbit center
        let body = ModelEntity(mesh: .generateSphere(radius: planet.radius),
                               materials: [planet.material])
        body.position = [planet.orbitRadius, 0, 0]
        pivot.addChild(body)
        sun.addChild(pivot)
        // animate pivot.orientation around Y for the orbit
    }
    content.add(sun)
}

Texture is what separates a credible viewer from colored marbles (and the size gap is real: Jupiter spans about 139,820 km against Earth’s 12,742 km): each planet gets an albedo map (NASA publishes usable surface imagery, and NASA’s solar-system resources are the canonical reference), the Sun gets an emissive material so it glows rather than reflects, and Saturn’s rings are a textured disc with alpha, not geometry. Keep sphere mesh detail moderate; a viewer rendering eight high-poly planets plus moons can stutter, and level-of-detail (simpler meshes when zoomed out) is the budget that keeps it smooth, the same render-only-what-you-must discipline as the flight radar live map.

Where does the “accurate vs. beautiful” fork actually bite?

In scale, and you cannot have both. Real relative sizes and distances make the planets invisible specks across an empty void (Jupiter is tiny next to the Sun; the gaps are enormous), so every watchable solar-system viewer cheats, and the honest move is choosing the cheat deliberately:

ModelSizesDistancesBest for
Visually balancedCompressed, all visibleCompressed, navigableThe toy that teaches shape and order
Size-accurateTrue relative radiiCompressedShowing how small Earth really is
Fully accurateTrueTrueA specks-in-void art piece, rarely usable

State the choice in the UI (“distances not to scale”) rather than implying a fidelity the model does not have, the same estimate-labeling honesty that governs every data visualization. Orbital speeds can follow the same logic: real relative periods (Mercury fast, Neptune glacial) are cheap to encode and add real teaching value even when sizes are stylized.

What makes it interactive instead of a screensaver?

Gestures and tappable bodies, wired to RealityKit’s input. Pinch zooms the camera, drag orbits the viewpoint around the system, and a tap on a planet does the thing that makes it an app: selects it, eases the camera toward it, and surfaces an info panel (diameter, day length, moons, the one weird fact). That tap-to-focus camera move is the payoff, and the SwiftUI overlay carrying the info panel is where the screen design lives, the 3D scene below, a clean data card above. The same canvas-gesture craft underlies the Apple Pencil drawing canvas, where direct manipulation has to feel physical.

Respect the platform: a play/pause for the orbital motion (constant animation is battery and a distraction when reading), Reduce Motion slowing or stopping the spin, and a reset-view button because users always tumble the camera into a confusing angle. A free VP0 design supplies the surrounding chrome, the info cards, the body selector, the controls, so an agent builds the RealityView scene under a UI that was actually designed.

Key takeaways: a solar system viewer in SwiftUI

  • RealityView with RealityKit is the modern path; Model3D for a single USDZ, SceneKit only for legacy.
  • Orbits are parent-pivot rotations, not per-frame trigonometry; moons nest under planets the same way.
  • Texture sells it: NASA albedo maps, an emissive Sun, Saturn’s rings as a textured alpha disc.
  • Pick the scale cheat deliberately and label it: nothing watchable is fully to scale.
  • Tap-to-focus plus an info panel is what turns a screensaver into an app; add play/pause and reset-view.

Frequently asked questions

How do I build an interactive 3D solar system viewer in SwiftUI? Use RealityView with RealityKit: a parent Sun entity, each planet a child whose orbit is the rotation of an invisible pivot, textured with NASA albedo maps and an emissive Sun. Add pinch-zoom, drag-to-orbit, and tap-to-focus gestures with an info panel overlay. A free VP0 design supplies the surrounding cards and controls to build the scene under.

Should I use RealityKit or SceneKit for a 3D solar system? RealityKit via RealityView for new builds: it is Apple’s current framework, renders physically-based materials, and works on iOS and visionOS. SceneKit still functions and has more legacy tutorials but is the aging path; reserve it for maintaining existing SceneKit code.

How do I animate planet orbits without complex math? Make each orbit the rotation of an invisible pivot entity centered on the Sun, with the planet positioned at its orbit radius as a child. Rotating the pivot circles the planet; rotating the planet entity spins it on its axis. No per-frame trigonometry, and moons nest under planets identically.

Can a solar system app show real scale? Not watchably: true relative sizes and distances make planets invisible specks in an empty void. Every usable viewer compresses scale, so choose the cheat (visually balanced, size-accurate, or fully accurate) deliberately and label it in the UI rather than implying false fidelity.

How do I make the 3D scene interactive? Wire RealityKit gestures: pinch to zoom the camera, drag to orbit the viewpoint, and tap a planet to select it, ease the camera toward it, and show an info panel. Add a SwiftUI overlay for the data cards and controls, plus play/pause and reset-view for usability.

Questions from the community

How do I build an interactive 3D solar system viewer in SwiftUI?

Use RealityView with RealityKit: a parent Sun entity, each planet a child whose orbit is an invisible pivot's rotation, textured with NASA albedo maps and an emissive Sun. Add pinch-zoom, drag-to-orbit, and tap-to-focus gestures with an info-panel overlay. A free VP0 design supplies the surrounding cards and controls.

Should I use RealityKit or SceneKit for a 3D solar system?

RealityKit via RealityView for new builds: it is Apple's current framework, renders physically-based materials, and works on iOS and visionOS. SceneKit still functions with more legacy tutorials but is the aging path, best reserved for maintaining existing SceneKit code.

How do I animate planet orbits without complex math?

Make each orbit the rotation of an invisible pivot entity centered on the Sun, with the planet positioned at its orbit radius as a child. Rotating the pivot circles the planet and rotating the planet entity spins it on its axis, with no per-frame trigonometry; moons nest under planets identically.

Can a solar system app show the real scale?

Not watchably: true relative sizes and distances render planets as invisible specks in an empty void. Every usable viewer compresses scale, so choose the cheat (visually balanced, size-accurate, or fully accurate) deliberately and label it in the UI instead of implying false fidelity.

How do I make the 3D solar system interactive?

Wire RealityKit gestures: pinch to zoom the camera, drag to orbit the viewpoint, and tap a planet to select it, ease the camera toward it, and show an info panel. Add a SwiftUI overlay for data cards and controls plus play/pause and reset-view for usability.

Part of the Native Apple & SwiftUI: The iOS Ecosystem hub. Browse all VP0 topics →

Keep reading

iMessage Reply Bubble Physics in SwiftUI: The Real Spring: a glass iPhone app-grid icon on a mint and teal gradient
Guides 5 min read

iMessage Reply Bubble Physics in SwiftUI: The Real Spring

Animate scale and offset not the frame, one restrained spring with sent springier than received, and a tail only on the last bubble of a run.

Lawrence Arya · June 7, 2026
iOS Context Menu Long-Press Blur in SwiftUI: a glass iPhone app-grid icon on a mint and teal gradient
Guides 6 min read

iOS Context Menu Long-Press Blur in SwiftUI

The native .contextMenu gives the lift, blur, and haptic for free. Build custom only when it is not a menu, and drive all three layers from one spring.

Lawrence Arya · June 7, 2026
Loyalty Punch-Card Stamp Animation in SwiftUI: the App Store logo as a glossy glass icon on a purple and blue gradient with floating bubbles
Guides 6 min read

Loyalty Punch-Card Stamp Animation in SwiftUI

The stamp is the product: a spring with overshoot, a resting tilt, and a haptic thunk, on a count the server owns and the merchant grants.

Lawrence Arya · June 7, 2026
AI Essay Grader Feedback Highlight UI: Teacher in the Loop: a glass app tile showing the VP0 logo on a pink and blue gradient
Guides 5 min read

AI Essay Grader Feedback Highlight UI: Teacher in the Loop

Design an AI essay grading UI: span-anchored highlights, rubric-mapped feedback categories, the teacher approval pass, and student views built for revision.

Lawrence Arya · June 5, 2026
AR Object Placement Target UI in SwiftUI: The Reticle: a reflective 3D App Store icon on a blue and purple gradient
Guides 4 min read

AR Object Placement Target UI in SwiftUI: The Reticle

Design AR placement UX in SwiftUI: the coaching phase, a state-honest reticle that snaps to surfaces, place-then-adjust gestures, and tracking truthfulness.

Lawrence Arya · June 5, 2026
School Parent Portal App in SwiftUI: A Design Guide: a glass iPhone app-grid icon on a mint and teal gradient
Guides 5 min read

School Parent Portal App in SwiftUI: A Design Guide

How to build a school parent portal in SwiftUI: the child switcher, a today-first home, absence reporting, actionable notifications, and student privacy.

Lawrence Arya · June 5, 2026