You are browsing as a guest. Sign up (or log in) to start making projects!

orbital

  • 13 Devlogs
  • 56 Total hours

Orbit Lens is a real-time 3D satellite tracking website built using vanilla JavaScript and Three.js. It tracks over 16,000 live space objects around earth using real-time data from CelesTrak.

Ship #1 Pending review

This is Orbit Lens, a real-time 3D satellite tracking website built using vanilla JavaScript and Three.js. It tracks over 16,000 live space objects around earth using real-time data from CelesTrak.

It has many features including 3d and 2d orbit tracking, 3d models of select satellites (ISS, Terra, HST, and Aqua). It also includes a filtering feature where you can filter satellites based on specific categories

Before testing this project, it is important to know some stuff:

You will have the best experience if you access this through a laptop or desktop
Sometimes, the api maybe down or is not responding to requests so please keep in mind that if you see an alert saying API not responding, it is out of the website’s hands and it an error outside of my control.

That’s it. Thank you for testing this project and hope you like it :)

  • 13 devlogs
  • 56h
Try project → See source code →
Open comments for this post

35m 56s logged

OrbitLens Devlog #13: fixing deployment bugs 😭😭

Before i continue with this devlog, let me start by saying that
modern security rules are the worst. Like istg, why do they have to be
so strict? Anyway, you’ll see what i mean by that down below. THis
session was all about fixing the deployment bugs. I was almost done and
then these f bugs ruined it. This devlog has only abt 30 mins logged
because i had the help of ai to fix this because this was way way out of
my expertise. Here are the changes. I used ai for this devlog though
cus i didn’t understand what it did (but i only used it for htis
devlog):
Problem 1: The [UNSUPPORTED_FEATURE] Vite Crash

My very first Vercel build crashed immediately with a “Top-level
await is currently not supported with the ‘iife’ output format” error.
Apparently, the satellite.js library I use for SGP4 orbital propagation
runs heavy calculations using Web Workers and WebAssembly. By default,
Vite tries to bundle everything into an older iife format for maximum
browser compatibility, which completely choked on the newer await
feature inside the worker file.
I fixed this (with the help of ai) by explicitly telling Vite’s
internal bundler (Rolldown) to output modern ES modules for both the
main thread and the background workers. I created a vite.config.js file
and updated the configuration (see vite.config.js in the github repo)
Problem 2: 404 Missing 3D Models

After fixing the build, the site successfully deployed, but my 3D
models (like the ISS and Hubble) and Earth textures threw 404 Not Found
errors in the console. Because I was loading these assets while
the app was running in my Three.js code using string paths (e.g.,
‘/models/iss.glb’), Vite didn’t know they existed and simply excluded
them from the final production build.
I moved my models and textures folders into Vite’s public directory.
Anything placed in the public folder gets copied exactly as is to the
root of the final build.
This bug wasn’t too bad but the next one was absolute hell.
Problem 3: API, Cloudflare and CORS block

This was the hardest part. Orbit Lens fetches live Two-Line Element
(TLE) data for over 16,000 satellites directly from CelesTrak. It worked
perfectly when i hosted it locally, but on Vercel, the browser
instantly threw a 403 Forbidden error. CelesTrak uses Cloudflare to
prevent automated scraping. When Cloudflare saw an Origin header coming
from a deployed Vercel frontend instead of an normaly IP like my
computer’s, it blocked the connection.
Attempts to use public proxies (like allorigins) resulted in 408
Request Timeout errors because the multiple mb big satellite data took
too long to transfer.
To fix this, I used Vercel’s Native Rewrites (i have no idea how to
use this so i asked ai to do it for me). “I” ;) created a vercel.json
file in the root directory to act as a silent backend proxy.
By fetching from my own local route (/api/celestrak), the browser
doesn’t trigger CORS security. Vercel’s backend intercepts the request,
strips the frontend Origin header that was triggering the firewall, and
routes the raw data back to the application.
This worked! And the website is finally live and i am about to ship the project!

1
0
15
Open comments for this post

1h 33m 14s logged

OrbitLens Devlog #12: Added README.md and ARCHITECTURE.md

In this session, i added the README and ARCHITECTURE.md.
The README.md highlights the basic features of the website, the tech
stack used and how to run this project locally. The ARCHITECTURE.md goes
deeper into how the code itself works so anyone perusing it can get a
better idea on how i built this project.

0
0
7
Open comments for this post

2h 11m 40s logged

OrbitLens Devlog #11: Semi-final changes

In this session, i focused on finding small aspects that need to be improved and improved them.
Change 1:

Firstly, i realised that the dropdown i had implemented was the
default dropdown and it didn’t rlly fare well when there were 16000
items to choose from. So i made a custom dropdown, which looks much
better than the default one, and made a funciton along with it that
shows like the first 200 items matching the search query or, if nothing
in being searched, the first 200 items in the list that the API gave.
This made the entire experiene so much better because the default
dropdown looked kinda ugly cus it took the whole length of the screen.
Normally, this wouldnt take too long but i accidentally deleted the
wrong eventListeners multiple times because satFilter and satSearch were
so similar. So i spent like a good amount of time trying ot find the
problem, and it turned out that i justmodified or deleted the wrong
thing.
Change 2:

I found a problem with the filtering system, more specifically in
filtering the space stations. Previously, i just had all the satellites
with ISS or CSS in their names classified as space station because there
are only two space statoins in space right now (ISS and Tiangong) so i
filtered any satellites with those two names. But i failed to take into
account that other satellites might also have ISS or CSS in their names
so instead of two satellites showin up, 16 satellites were avaialbe in
that filter. And these were not space stations but rather other
statellits which had like ISS or CSS in their names (e.g. Swisscube). So
i changed the filter to filter the space stations by their respective
NoradIDs, which worked.
Change 3:

This change wasnt too big; i modified the expanded map layout becaues
how it was before led to it having a lot of blank space and probalby
wouldnt have looked good in differnet devices.

0
0
9
Open comments for this post

4h 12m 8s logged

OrbitLens Devlog #10: mobile layout implementation + better loading screen

I am nearing the first ship of this project so this session were just about the final aspects that needed to be improved
Change 1:

I completely changed the loading screen. Firstly, it now displays the
loading percentage that accurately shows the real time progress.
Secondly, overall it just looks much better. Thirdly, i also implemented
an error notification in the main dashboard in case the API doesnt work
and so the website doesnt look like it’s broken
Change 2:

I added a mobile layout option. by that i mean that if the user is
accessing this website on a mobile, it won’t be completely botched
(hopefully)
p.s. i know this devlog isnt that detailed as my previous ones and
that’s because there isn’t much to talk about in this session cus the
main changes were in the styles.css (and i’m hella tired)

0
0
23
Open comments for this post

6h 30m 57s logged

OrbitLens Devlog #9: implemented satellite filtering + earth connecting line and complete UI overhaul

Now that the website has a proper engine and everything was working
well, i decided to add some more stuff. I had two goals for this
session. One was to add a satellite filtering option where the user can
filter categories of satellites. The other is to change the ui because
there were many imprefectoins. Here is a breakdown of what i changed and
the challenges i faced:
Change 1:

I added a global filtering system to fiter satellites by categories.
To do this i first built a string-matching engine directly into the TLE
parsing loop. As the engine downloads the TLE data from the API, it
scans the satellite names and tags them each with categories. I didn’t
really know what to categorise them so i thought of some categories and i
asked ai to think of some categories. These are the categories:
StarlinkOnewebCommsNavigationWeatherand Other/Miscallaneous (which i impemented later; read below)
I then wired the HTML dropdown directly into the WebGL gpu loop.
Instead of deleting unselected satellites (which would take up too much
gpu memory), the gpu simply multiplies their matrix scale to 0, 0, 0,
which would just hide them.
But there was a challenge that i faced, though it wasn’t a big one.
When i first implemented the filter, I noticed that the total satellite
count dropped to around 12,000. It turned out that all the satellites
that didnt fit into any cateogry were not shown at all so i expanded the
categories to include an OTHER category.
I also had to make some changes in the raycaster or the users would accidentally be clicking on the hidden satellites.
Change 2:

I also added a line connecting the selected satellite directly to its
exact spot on the Earth’s surface directly beneath it. I did this by
first pre-allocating a THREE.BufferGeometry with exactly two vertices.
Inside the animation loop, i then took the satellite’s live 3D
coordinates and use a .normalize() math function. Because the Earth has a
radius of exactly 1, normalizing the 3d coordinates perfectly attaches
the bottom of the line to the planet’s surface.
But, i ran into a bug where the line would randomly disappear
depending on the camera angle. After some research (ai) i found out that
this was caused by Three.js’s “Frustum Culling.” The code calculated
the line bounding box once when the websited started up and when the
camera moved away from that initial box, the gpu assumed the line was
out of sight and stopped rendering it to save memory. So i just added a
line of code (frustumCulled = false) that just overrode that.
Change 3:

Lastly, i essentially completely rewrote the styles.css to change how
the ui looked cus i didn’t relaly like how it looked before. So this
was the third change.

0
0
19
Open comments for this post

6h 31m 5s logged

OrbitLens Devlog #8: Scaling the 3d globe and some other stuff

In the last update, i finally implemented the 2d map so this time i
want to take this website a step further since the foundation is stable
enough. I decided to go from tracking 5 hardcoded satellites to over
16,000 space objects. Here is what i changed, how i changed it and the
challenges i faced:
Change 1:

Originally, i just added the starlink satellites to what i already
had which was my initial goal. but the thing was, i was requesting the
API for thousands of satellites, which did work once and all of them
were stored in localStorage but for ‘testing purposes’ (i was just
stupif), i cleared the localStorage and re-requested the TLE which it
then instantly rejected cus of its ‘anti-bot firewalls’ and i got ip
banned for like a couple of hours and it gave a 403 error aswell.
To fix this, i read some CelesTrak documentation and i realised that
there is a way to ismply request all the satellite (every satellite that
it had) data in one request. Apparently there was a special search
query (‘active’) that i could’ve used but instead i individually fetched
everything. So once i used that query, i got all of the satellitse (a
bit more than 16000) rendered on the earth but it was laggy, which leads
to my second change.
Change 2

To fix this massive lag caused by the 16000+ satellites, I completely
replaced the standard 3D mesh pipeline with THREE.InstancedMesh so that
instead of creating 16,000 individual sphere objects (which would like
instantly crashes the browser), i can feed the GPU a single geometry and
material, along with an array of 16,000 matrixes. That means now the
gpu like renders everything in one go.
But, I hit a massive 5-second freeze whenever a user clicked the ISS
(which makes sense cus this was a 4k extremely detailed 3d model). The
thing was, WebGL delays uploading heavy 3D textures to the GPU until an
object is actually rendered on screen. And because the ISS model was
hidden on startup, the compiler skipped it, so the website was stuck
trying to render it when i selected the ISS. I solved this by forcing
the renderer to draw one “dummy frame” with all models visible during
the loading screen, which, in a sense, ‘warmed up’ the GPU.
Change 3:

The lag was better but it was still there and i realised the problem
was that each of the dots representing a satellite were smoothly moving
in space. This smooth-moving physics applied to over 16000 dots was what
slowed down the website.
To fix this, I rewrote the loop that propogates the satellite dots so
physics calculations wouldn’t choke the main JavaScript thread. To do
this i built a system to process the satellites in batches of 4,000
satellites per frame instead of all 16,000. Second, i scrapped geodetic
trigonometry (latitude/longitude conversions; see one of the earlier
devlogs) and replaced it with direct Earth-Centered, Earth-Fixed (ECEF)
3D vector rotation.
Initially, our batches were too small, causing satellites to visually
‘teleport’ instead of smoothly gliding, which looked really glitchy.
But by upgrading to matrix rotation, i managed to get a huge increase in
speed. This allowed me to crank the batch size up and get that smooth
motion across the entire thing.
Change(s) 4:

There were still some small bugs in the visual aspects like the dots
disappearing or the transition jump (see previous devlog(s) to
understand) and stuff but i took care of them.

0
0
3
Open comments for this post

3h 53m 9s logged

OrbitLens Devlog #7: Implementing a 2D orbit map

To expand the functinality of the website, i wanted to add a 2D world
map that has the 3d orbit projected on to it. Here is a breakdown of
what i built, how i built it and the challenge i faced.
What I Built:

I made a 2D projection of the 3d globe using the HTML5 Canvas API that runs at the same time with the WebGL 3D engine.
The map automatically appears when a satellite is selected, and
fetches live telemetry to draw exactly one full orbital period (half
past, half future). The orbit line looks like how it does on the 3d
globe with a yellow line representing the past trail and a dotted blue
line representing the predicted future track. I also built an “EXPAND”
toggle that expands the map to fill most of the screen if the user wants
to take a close look.
Challenges:

If a satellite flies east across the Pacific Ocean (where the
International Date Line is), its longitude coordinates suddenly jump
from +179deg to -179deg. I originally didnt take this into account and
it had like this massive, horizontal glitch streak entirely across the
screen cus of the sudden coordinate shift.
To fix this, I programmed a strict mathematical distance gate into
the drawing loop. If the engine detects that the X-coordinate has jumped
by more than half the width of the canvas, it forces the renderer to
break the current stroke (mapCtx.stroke()), lift the ‘pen’, and begin a
completely new path on the opposite edge of the map
(mapCtx.beginPath()).

When plotting a full 90-minute orbit, the beginning of the yellow
line and the end of the cyan line do not connect perfectly, leaving a
massive gap. I originally thought this was a problem and tried for quite
a while to fix this and i double checked the math formulas again and
again. But i realised this isnt a math error, it’s just physics. While
the satellite flies in a continuous circle, the Earth is physically
rotating underneath it. By the time the satellite completes one lap, the
ground has shifted roughly 22.5 degrees to the east, pushing the
satellite’s relative ground track to the west. So i just left it like
that to accurately represent the Earth’s rotation.

This was the biggest problem and took the most time to fix. Three.js
orbital camera controls are incredibly aggressive about capturing mouse
events. The 3D engine was always suppressing the HTML ‘click’ events,
making the “EXPAND” button not work. Not only that, the standard inline
CSS was pushing the 3D canvas down the page, which misaligned everything
and didnt allow me to select the satellites at all.

To fix this, fisrt, i locked the 3D canvas to a fixed background
layer (z-index: -1) to completely isolate it from the UI layout. Second,
i bypassed the WebGL event interceptors entirely and connected the code
that handles the expansion directly to a global window function
(window.toggleMap) and just injected the button with the HTML onclick
attribute. This fixed everything and now it works really great.

0
0
12
Open comments for this post

6h 12m 10s logged

OrbitLens Devlog #6: Implemented Sun and the day night cycles + camera panning improvements

The core engine was working smoothly, so this session was focused on
the ui and aesthetics and realism. Here are the changes i made, how i
made them, and the challenges i faced:
Change 1: Implemented the Sun

The first major goal was replacing the static and boring lighting the 3D earth originally had with a Sun.
To do this, I wrote a custom Solar Ephemeris algorithm. Using the
current Julian date, it calculates the sun’s exact Right Ascension,
Declination, and Earth’s Greenwich Mean Sidereal Time (GMST) to pinpoint
the real-time subsolar vector. Since this was some complicated math, i
had to use some ai for this.
But in a WebGL engine, lights are purely mathematical vectors and
there is no physical object in the sky. So when i first added a solid
white sphere, it literally looked like a flat plastic toy and looked
really ugly. To fix this, I abandoned the 3D ball and built a 2D Sprite
using the HTML5 Canvas API to generate a radial gradient. By using
Additive Blending to the material, I forced it to mathematically layer
the light over the space, which created like this blinding, light that
looked like the sun, which was good.
Change 2: The Day/Night City lights cycle:

To make the globe even more realistic, I wanted the night side of the
Earth to have like the night time city lights rather than just a dark
shadow.
To build this, I added an 8k night-map texture (from Solar System
Scope) and implemented a WebGL fragment shader into the Three.js’s
native MeshPhongMaterial using a compiler hook. But there was a problem,
the free night map that i implemented had this blue tint to it, and
when i tried to correct it, it literally turned to this muddy, polluted
yellow.
To fix this, I programmed the shader to intercept the texture data,
remove the color tint by calculating luminance, and pass it through a
smoothstep noise gate. Anything below a 10% threshold was forced to
pitch black, while populated areas were recolored with a warm golden
orange hue. And it worked great!
Change 3: More camera improvements

Despite the previous session having to do with correcting the camera
engine, there were still some stuff that i fixed here. The problem was
since i removed OrbitControls in the last session (read
previous devlog), once i had like hte earth upside, it was very hard to
make it upright again. like at one point, i had the entire europe upside
down and Africa was at the top of the globe but i couldnt get it back
to normal.
To fix this I changed the code so that the panning controls thing swaps between OrbitControls (for the 3D globe) and TrackballControls (for the satellites/spacecrafts). But there were some more challenges:

When a zoom-in animation (read previous devlogs) finished (after
selecting e.g. a satellite), the camera would like glitch backward into a
less zoomed in position which was kinds uncomfortable to look at.

Because the satellites were moving a static transition speed couldn’t
catch them before the animation finished, so the final frame was a bit
glitchy and the screen like jumped a bit.

To fix all of these problems, I first made sure that disabled camera
controls are completely turned off so they can’t fight the active zoom
animations. I also made it that instead of moving at a steady speed, I
added a speed-up effect as the camera gets closer to the target. This
ensures that the camera glides smoothly into place right on time without
any jerky jumps.

0
0
16
Open comments for this post

7h 19m 44s logged

OrbitLens Devlog #5: Camera panning improvements and performance updates

After the changes from Devlog #4, all the math and the 3d models were
all working but i faced some problems in other aspects of the website.
Here are soe of the changes i made:
Change 1: Correct orientation

This was a small change, but i noticed that some satellites were a
bit too big (like Aqua) and were positioned wrongly, so i just chaged
teh scale and the rotation to make it a bit more realistic
Changes 2, 3, and 4: The camera improvements

I faced a lots of problems with the camera and how it worked. Before,
i couldn’t rotated in all directions around the earth or the satellites
because they were using OrbitControls so i swapped that out with TrackballControls, which allows for 360deg panninh
There was also like a rubber band effect where the camera, when the
camera lock was selected as satellite, zoomed in towards a satellite, i
couldn’t interact with the satellite at all. THis was because as the
satellite’s moving, the camera is also actuvely trying to catch up so it
never actually ‘ended’ its animation so i was blocked from interacting
with the satellite. To fix this i implemented delta tracking. The engine
now calculates the exact mathematical vector the satellite moves every
frame and shifts the camera’s physical position by that exact same
amount, which worked.
Previously, switching targets caused the camera to travel in a
straight line, clipping through the Earth, which looked kinda
unprofessional so I engineered a custom transition that separates the
camera’s direction from its altitude. Now, when you select a new
satellite, the camera zooms out, tracels in a an arc over the globe, and
zooms in to the destination satellite.
The animation still needs a lot of improvement cus some parts are still a bit glitchy, but i’m happy for now.
Change 5:

I implemented it that the TLEs are now stored in the actual
localStorage for like 6 hours and then fetch new TLEs. So the user will
always have the latest TLEs cus they update evey 12hrs.

0
0
44
Open comments for this post

5h 49m 31s logged

OrbitLens Devlog #4: Adding multiple satellites

In my last update, I finally got a 3D model of the ISS rendering on
the globe with a basic UI dashboard. It looked cool, but I wanted to
scale it up. I wanted to add multiple famous satellites on top of the
ISS:
The Hubble Space Telescope (HST)NASA’s AquaNASA’s TerraTiangongISS (which already exists)
At least for now. Maybe in later stages, I can add Starlink satellites
or sth. Here is waht I built, how I built it, and the challenges I
faced.
Change/Challenge 1: the orbit that looked like a slinky

I hardcoded a 90-minute orbit line (the ISS orbit time). But other
satellites have different orbital periods, so 90 mins fell short.
Increasing it to a 12-hour calculation made the ISS orbit look like a
massive slinky wrapping around the Earth cus its orbit is only 90mins. I
fixed this by dynamically calculating the exact total orbit time using
the satellite’s math:
const periodMinutes = Math.ceil((2 * Math.PI) / satrec.no);
const halfPeriod = Math.floor(periodMinutes / 2);
Change/Challenge 2: IP ban (again)

The JS fetch() doesn’t consider a ‘429 too many requests’ (i got this
cus vite reloaded the page every time i saved something) response as a
network error, so it tried calculating the HTML error page as orbital
math and crashed. I fixed this by manually checking the response.ok HTTP
status. If the API blocks me, the code redirects to an “Offline
Fallback Mode”—loading a hardcoded string of ISS TLE math so the app
survives.
Change/Challenge 3: improper API request

After like 4 hours, I realized I still wasn’t getting a proper API
response even though the IP ban would have worn off. I looked at the
code and realized I was pulling data for all five satellites in one go
by just comma-separating the values in the URL like this:
…/gp.php?CATNR=25544,20580,48274&FORMAT=tle
(each number references to a satellite)
But after CelesTrak’s documentation, it strictly dictated that the
CATNR parameter only accepts a single catalog number. The server
rejected the request, my code assumed 0 satellites, and the engine
crashed.
The fix:

Writing five separate fetch() blocks is messy, and implementing an
await fetch() in a for-loop creates a slow “waterfall” effect (waiting
for one to finish before starting the next).
I fixed this with JavaScript’s Promise.all. I created an array of the
exact NORAD IDs, mapped over it to generate separate, perfectly
formatted fetch requests, and Promise.all fires them all at the exact
same time.
Change/Challenge 4:

I wanted 3D models for all of these. I found Aqua and HST easily from
NASA. I found Terra, but it was fetching some other incompatible file I
didn’t have, so I just scratched the Terra model. Tiangong was the
biggest pain—everywhere I looked was either paid or on Sketchfab, and I
cant create a Sketchfab account cus of some stupid Epic Games
restriction.
Implementing the files I did have was the next issue. Hardcoding
multiple GLTFLoader blocks would turn the code into spaghetti. Plus, 3D
models from the internet aren’t scaled equally—my Hubble was massive,
and my Aqua model was tiny.
The fix:

I built a central Model Registry object. It maps a satellite’s NORAD
ID to its file path and a specific scale multiplier. Even better, I
implemented a fallback for satellites I done have a model for. If I
track a satellite (like Tiangong) but leave the file path as null, the
code detects this and dynamically generates a glowing cyan sphere using
Three.js math to take its place.
Changes 5 and 6:

I updated the dashboard to include a dropdown to select the satellite
and the telemetry updates accordingly. I also added a camera toggle
feature where the user can lock the camera to follow the satellite or
stay locked on the Earth. Lastly, I implemented a custom loading screen
while the models load.
P.S.Lots of info is compressed cus i crossed the 4000 char limit.

0
0
20
Open comments for this post

5h 28m 55s logged

OrbitLens Devlog #3: Adding a dashboard + ISS 3d model implementation

I had two goals in my mind in this session. One was to add a
dashboard which displays some stats of the ISS and the other is to
replace the red dot with a 3d model of the ISS. Here is what and how I
implemented these stuff and the challenges i faced:
Change/Problem 1:

Before I even got started on the new stuff i wanted to add, i faced a
big problem. While testing the physics code and other stuff, my build
tool (Vite) was auto-refreshing the browser every time I hit save. This I
spammed CelesTrak’s public API with dozens of requests per minute. This
lead to me kinda getting IP blocked temporarily, at least that’s what i
think happend because it always returned an HTML error page instead of a
TLE string. My engine tried to calculate stuff with that empty TLE and
just crashed the engine
The fix:

It is important to know that a TLE is not like a live GPS broadcast
that gets transmitted every second. It’s literally like a mathematical
snapshot of a ton of stuff of the ISS like its position and its orbit
and NORAD only updates these TLEs like twice a day or sth. So I fixed
this api problem by making it such that the localStorage caches the TLE
once and uses it for the calculation for the next 12 hours and then
updates the TLE after that.
Change 2: Dashboard implementation

I implemented a dashboard that shows up on the top left of the screen and shows the following stuff abotu the ISS:
Longitude: the method i used to calculate this is in one of my
previous devlogs (i think my last one). But here is a quick summary:
To find coordinates I first calculated the Greenwich Mean Sidereal
Time (gmst), which gives me the exact rotational angle of the Earth at
that specific millisecond. I passed the ECI position (one of the
previosu devlogs) and gmst into satellite.eciToGeodetic(), which
projects the point onto the spinning globe in radians. I then multiplied
those values by 180/pi to convert the radians into standard degrees
latitude: same as longitude
-altitude: The eciToGeodetic() function also calculates the distance
from the satellite’s coordinates down to the mathematical surface of the
Earth (the WGS84 or the ‘World Geodetic System 1984’ ellipsoid which is
like a mathematical reference representation of the earth that is used
in calculatoin and stuff). It outputs this directly as height in
kilometers, which I then simply rounded to two dp.
-velocity: The propagate() function outputs the satellite’s speed
broken into X, Y, and Z axes (measured in km/s). To get a single speed, I
calculated the magnitude of that 3D vector using the 3D Pythagorean
theorem:
v = squareroot(x^2 + y^2 + z^2)
Change 3:

To implement a 3d model, i first needed that 3d image. I wanted the
highest quality NASA model available (Model D - IGOAL). I downloaded the
official .fbx, converted it to a .glb, and ended up with a 255mb file.
Which is really bad because shoving a 255mb file into a web browser
would just crash the entire thing. So i just ran that through a draco
compression and a texture compression (WebP 1024x1024) which brought the
size to about 18mb which was much better.
To render this, I used Three.js’s GLTFLoader with a dedicated Google WebAssembly DRACOLoader to decode the compressed math.
The next couple of changes were just to make it more realistic:

i changed the scale from 0.02 (where it was the size of a continent) to 0.001 (which made it a good size)

the direction the ISS faced was not accurate at all so I wanted to
rotate until its in the correct position. But because the animate() loop
was actively using math to point the model forward 60 times a second,
it kept overriding my manual rotation. So I wrapped the ISS in a
THREE.Group, rotated the mesh 90 degrees inside that container, and then
applied the math.

0
0
5
Open comments for this post

3h 54m 27s logged

OrbitLens Devlog #2: Adding ISS + Orbit

This session was mainly focused on implementing the ISS first to the satellite tracker. Here are the changes I made:
Satellite Data Extraction and ISS Positioning

To understand what I did in this session, it is important to know how I can get the ‘live’ location of the ISS works:

firstly, satellites don’t broadcast live GPS coordinates to the
internet. Instead, radars track them and publish Two-Line Element (TLE)
sets. A TLE is like a raw string that “acts as a mathematical variable
of an orbit’s shape at a specific moment.” I got these TLE from a
non-profit API called CelesTrak.

these TLEs are kinda useless so I used the satellite.js library to
parse te TLEs. This js engine also allows you to run what is known as
SGP4 models (Simplified General Perturbations 4) which is a mathematical
model used to predict an orbit. Using this, TLEs are then converted to
what’s known as Earth-Centered Inertial (ECI) vectors which is a

“non-rotating 3D coordinate system anchored to the center of the
Earth with its axes fixed relative to the stars, allowing you to
calculate a satellite’s absolute mathematical position in space
independent of the Earth spinning beneath it.”
The ECI is still not useful so I passed it through
satellite.eciToGeodetic which converted the eci to geodetic coordinates
(longitude, latitude and altitude)
But there’s one more step before the data is useful. The thing is
Three.js only understands Cartesian coordinates (x, y, z) so the
geodetic coordinates need to be converted to catesian. I did that using
these mathematical formulas:

x = r * cos(lat) * cos(lon)
y = r * sin(lat)
z = -r * cos(lat) * sin(lon)

Orbit Implementation

Satellites do not orbit in perfect circles; they follow complex
trajectories that shift as the Earth rotates underneath them. The ISS
takes roughly 92 minutes to complete one full orbit around the Earth. I
captured this entire window by running two separate for loops. For these
loops, i created 92 differed Date objects spaced exactly 1 second
apart. here are the loops and how they work in a small nutshell:

The Past: I looped backward from -46 minutes up to 0 (the current
moment) and inputted the X, Y, and Z coordinates in each loop into
THREE.BufferGeometry to draw a solid yellow LineBasicMaterial.

The Future: I looped forward from 0 to +46 minutes. In every single iteration of those loops, and did the same thing.

Challenges:

the hemisphere and orbit were originally flipped or were completely
false so i had to wrack my brain and dind the cause. I spent more than
an hour debugging this. Turns out the formula was wrong and i used sin
instaed of cos.
In te end, I also double checked my orbit and position with official ISS trackers, and they matched!

0
0
2
Open comments for this post

2h 12m 31s logged

OrbitLens Devlog #1: Rendering the Earth 3D

I just kick started this project, Orbit Lens, and my aim is to build a
fully free, real-time 3D satellite tracker from scratch using Three.js
and maybe some other libraries. Today was all about creating the core 3D
arch. You can’t track a satellite without a planet to orbit, so Phase 1
was focused on rendering the Earth and setting up the Three.js
environment.
What I accomplished in Phase 1:

Set up my environment with ViteBuilt the Three.js scene, camera, and render loop.Rendered a 3D Earth utilizing maps from solar system scope.Enabled OrbitControls to enable camera panning
This is just the basic foundations of the project so there’ll be much more development in the future.

0
0
15

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…