ONLINE --:--:--
2026-07-06 ★ FEATURED [PUBLISHED]

EXOPLANET-INTERACTIVE

culmination of my exoplanet starmap project

ASTRONOMYEXOPLANET3Dinteractive
────────────────────────────────────────────────────────────

THE STORY UP UNTIL THE CURRENT MOMENT

In my mind I held this image of points of light hanging in a deep dark background, each one representing a tiny island where other worlds are confirmed to exist. I knew I had access to the public NASA data and the creative and technical mindset where I could just build something on my own. So I started to experiment with ideas and techniques. I downloaded the data manually as a csv at first, exploring plots with matplotlib, comparing stellar radius with planet radius. Do larger stars have more planets? I had some fun with that kind of idea for a bit. But I knew I still wanted that 3d map.

The Processing language seemed promising however it struggled to render the thousands of star systems on each frame. Its animations follow the pattern of drawing each frame then clearing it and drawing the next. I knew I needed to create a proper 3d model, and what better excuse exists to learn Blender than a real world use case. So that is what I did, I learned the basics of blender modeling, meshes, materials, camera animations, and its built in python scripting. I wrote a script that took a csv input and then plotted an iso sphere at each point in space, and the map was starting to come together brilliantly.

Or so I thought. I had missed something critical. In my data pipeline I was converting from right ascension, declination, and distance into x, y, z coordinates. But in the conversion in my code I had swapped sin and cos of the declination angles, incorrectly picturing declination as polar coordinates when really declination is measured from the equatorial plane while the polar zenith is measured from the pole. The result was a nice looking point cloud that was meaningless. I caught my error because I knew that there should be a cone of dense exoplanets from the Kepler mission, but this formation was not present in my map. After digging back through the data transformation functions and a trivial sin/cos swap, the correct map jumped out gloriously in my Blender viewport.

Then to automate the data collection aspect I built a small data pipeline that pulls from NASA’s exoplanet archive API, runs the transformation scripts, and then saves the transformed dataset in a form compatible with Blender. This pipeline is really just a collection of simple Python scripts, but it is reliable and does exactly what I need with minimal overhead.

So now I have the scene plotted in Blender, it looks good in the viewport, but how do I share it with others? My first thought was to create animations. Fly the camera around to explore the model and render out 1 or 2 minutes of video. This worked quite well after I solved some interesting problems. First, stars are really far apart. Plotting them at real scale just breaks blender and I knew this going in the data pipeline I scaled the distances to manageable sizes while keeping the relative spacing accurate. Still, in the render the far away stars bounce between 0 and 1 pixel creating a flickering effect that you can see in the final output. I solved this later in the interactive model by dynamically scaling the far away stars to always be at least one pixel in size and therefore always appear in the render. This is a good segue into the next iteration of this project, the interactive model.

CREATING THE INTERACTIVE MAP

Three.js is a Javascript library that wraps WebGL and allows you to create 3d graphics in a web browser. I actually first heard about it from a Blender tutorial on youtube. I was left thinking, why wait hours on Blender rendering for a fixed 2 minute animation when I could upload the same model and let people explore it themselves? The answer is, write that Three.js app.

The approach is simple, export the model as a .glb file, upload to my website, and render with a script in Three.js. GLB format stores a lot of the information from the model including meshes and materials in a neat compact binary. With just the file and a short script, the exoplanet map is live and interactive now in the lab section of my site.

Two aspects that were greatly improved in the interactive display of the model are as follows: ditching emissive material lighting, and dynamically sizing distant stars to always be rendered no matter how far from the camera they may be. In the first case, no matter how high I cranked the emission strength everything was still too dark. So instead I used an approach where during rendering a ray is cast from the POV of the camera, and if it intersects with any meshes, that point is stored as a hit. Then each hit is projected on the screen, the result is a binary either full brightness object pixel or black space background. In the second case I do some calculations before rendering each frame and if the expected size of a mesh based on its distance to the camera is less than a specified constant pixel value, the mesh is scaled up for that frame. The result is that there are no more flickering stars in the background, and instead every star is always visible in the map.

I have learned a lot during this project, from Three.js and agentic coding, to video editing and Blender animation, to astronomical measurements and data manipulation. I’m glad it’s finally coming together in a state that I am happy to share. Check it out in the lab section!