This program simulates the Earth and Moon orbiting the sun, and uses _MAPTRIANGLE(3D) to give a full 3D simulation. This is the last of my _MAPTRIANGLE - Conic Sections quartet of programs (Rotating Cylinders in 3D Space,3D Rolling Sphere,3D Rocket Launch to the Moon).
Unzip the folder into the QB64 directory.
3D-Sun-Earth-Moon.zip (Size: 5.52 MB / Downloads: 45)
The Earth orbits the sun by Newtonian gravitation (inverse square law). The mathematics is set to give a pronounced elliptical orbit (the ellipse completes the Conic Sections set) - in reality the Earth's orbit is nearly circular.
The Moon orbits the Earth in a set circular path (not set by gravitation).
The Earth spins on its axis and is tilted at 23.4° to the orbit, exactly as reality. The period for one revolution defines the day, and the Earth completes its orbit around the Sun in 365.25 days, exactly as reality.
The Moon spins on its axis and keeps the same face to the Earth, exactly as reality. The Moon takes 27 days to orbit the Earth, exactly as reality.
The Sun spins on its axis. Because it is a plasma-y object, its spins faster at its equator than at its poles and this is simulated in the program.
Compromises were required. Clearly the size of the objects bears no relation to the orbits in reality. A large window is required to show the motions, and even so the Earth and Moon disappear at the left- and right-hand sides. A video of the running program is attached if your screen is too small to view the whole window.
Because it takes 365.25 Earth days for a complete orbit, the program runs for about 4½ minutes to complete a revolution.
Further enhancements could have been coded (eg altering viewing angles by arrow keys) but the program as is demonstrates the principles.
Unzip the folder into the QB64 directory.
3D-Sun-Earth-Moon.zip (Size: 5.52 MB / Downloads: 45)
The Earth orbits the sun by Newtonian gravitation (inverse square law). The mathematics is set to give a pronounced elliptical orbit (the ellipse completes the Conic Sections set) - in reality the Earth's orbit is nearly circular.
The Moon orbits the Earth in a set circular path (not set by gravitation).
The Earth spins on its axis and is tilted at 23.4° to the orbit, exactly as reality. The period for one revolution defines the day, and the Earth completes its orbit around the Sun in 365.25 days, exactly as reality.
The Moon spins on its axis and keeps the same face to the Earth, exactly as reality. The Moon takes 27 days to orbit the Earth, exactly as reality.
The Sun spins on its axis. Because it is a plasma-y object, its spins faster at its equator than at its poles and this is simulated in the program.
Compromises were required. Clearly the size of the objects bears no relation to the orbits in reality. A large window is required to show the motions, and even so the Earth and Moon disappear at the left- and right-hand sides. A video of the running program is attached if your screen is too small to view the whole window.
Because it takes 365.25 Earth days for a complete orbit, the program runs for about 4½ minutes to complete a revolution.
Further enhancements could have been coded (eg altering viewing angles by arrow keys) but the program as is demonstrates the principles.
Code: (Select All)
'3D Sun-Earth-Moon Simulation [_MAPTRIANGLE(3D] by Magdha QB64 v2.0 12/11/25
'Parameter set to give correct orbit times for Earth around Sun and Moon around Earth
'The Earth is tilted correctly. The Moon Orbit has correct tilt, and Moon keeps constant face to Earth
'The Sun has more rapid spin at its equator cf its poles
CONST False = 0, True = NOT False
CONST NoPhis%% = 32, NoThetas%% = 4, NoImages%% = 16, Phi! = _PI / NoPhis%%, Theta! = 2 * _PI / (NoImages%% * NoThetas%%)
CONST ImageRad% = 250, SunRad% = 200, EarthRad% = 100, MoonRad% = 40, ZOffset% = 1800, EarthTilt! = 23.4 * _PI / 180
CONST MoonTilt! = 5.15 * _PI / 180, M1% = 10000, g! = 9.81, RMoon% = 200, MoonOmega! = 0.00533 * 2
CONST SunPoles! = 0.00411, SunEquator! = 0.00164, SunRot! = 0.144
DIM MapFromImage%(NoPhis%%, NoThetas%%, 1), MapToSphere!(2, NoPhis%%, NoImages%% * NoThetas%%, 2)
DIM SunSpot&(NoImages%%), Moony&(NoImages%%), Earthling&(NoImages%%), SunSpin!(NoPhis%%)
_TITLE "3d Sun-Earth-Moon Esc to Quit"
'Load Images and Map to 3D
FOR K%% = 1 TO NoImages%%
Filename$ = "HSun" + LTRIM$(STR$(K%%)) + ".jpg"
PRINT Filename$
TempImage& = _LOADIMAGE(Filename$, 32)
TempImage1& = _NEWIMAGE(251, 501, 32)
_DEST TempImage1&
_PUTIMAGE , TempImage&
SunSpot&(K%%) = HardwareImage&(TempImage1&, True)
_FREEIMAGE TempImage&
Filename$ = "HMoon" + LTRIM$(STR$(K%%)) + ".jpg"
PRINT Filename$
TempImage& = _LOADIMAGE(Filename$, 32)
TempImage1& = _NEWIMAGE(251, 501, 32)
_DEST TempImage1&
_PUTIMAGE , TempImage&
Moony&(K%%) = HardwareImage&(TempImage1&, True)
_FREEIMAGE TempImage&
Filename$ = "HEarth" + LTRIM$(STR$(K%%)) + ".jpg"
PRINT Filename$
TempImage& = _LOADIMAGE(Filename$, 32)
TempImage1& = _NEWIMAGE(251, 501, 32)
_DEST TempImage1&
_PUTIMAGE , TempImage&
Earthling&(K%%) = HardwareImage&(TempImage1&, True)
_FREEIMAGE TempImage&
FOR N%% = 0 TO NoPhis%%
FOR M%% = 0 TO NoThetas%%
'Sun Mapping not required as this is handles in running motion
'MapToSphere!(0, N%%, M%% + (K%% - 1) * NoThetas%%, 0) = SunRad% * SIN(N%% * Phi!) * SIN((M%% + (K%% - 1) * NoThetas%%) * Theta!) 'x Sphere
'MapToSphere!(0, N%%, M%% + (K%% - 1) * NoThetas%%, 1) = SunRad% * COS(N%% * Phi!) 'y Sphere
'MapToSphere!(0, N%%, M%% + (K%% - 1) * NoThetas%%, 2) = SunRad% * SIN(N%% * Phi!) * COS((M%% + (K%% - 1) * NoThetas%%) * Theta!) 'z Sphere
'Earth Mapping
MapToSphere!(1, N%%, M%% + (K%% - 1) * NoThetas%%, 0) = EarthRad% * SIN(N%% * Phi!) * SIN((M%% + (K%% - 1) * NoThetas%%) * Theta!) 'x Sphere
MapToSphere!(1, N%%, M%% + (K%% - 1) * NoThetas%%, 1) = EarthRad% * COS(N%% * Phi!) 'y Sphere
MapToSphere!(1, N%%, M%% + (K%% - 1) * NoThetas%%, 2) = EarthRad% * SIN(N%% * Phi!) * COS((M%% + (K%% - 1) * NoThetas%%) * Theta!) 'z Sphere
'Moon Mapping
MapToSphere!(2, N%%, M%% + (K%% - 1) * NoThetas%%, 0) = MoonRad% * SIN(N%% * Phi!) * SIN((M%% + (K%% - 1) * NoThetas%%) * Theta!) 'x Sphere
MapToSphere!(2, N%%, M%% + (K%% - 1) * NoThetas%%, 1) = MoonRad% * COS(N%% * Phi!) 'y Sphere
MapToSphere!(2, N%%, M%% + (K%% - 1) * NoThetas%%, 2) = MoonRad% * SIN(N%% * Phi!) * COS((M%% + (K%% - 1) * NoThetas%%) * Theta!) 'z Sphere
NEXT M%%
NEXT N%%
NEXT K%%
'Mapping from Input Images
FOR N%% = 0 TO NoPhis%%
FOR M%% = 0 TO NoThetas%%
MapFromImage%(N%%, M%%, 0) = CINT(1.4 * ImageRad% * SIN(N%% * Phi!) * SIN(M%% * Theta!)) 'x Image: 1.4 best compromise
MapFromImage%(N%%, M%%, 1) = CINT(ImageRad% - ImageRad% * COS(N%% * Phi!)) 'y Image
NEXT M%%
NEXT N%%
'Background Image
TempImage& = _NEWIMAGE(1900, 1000, 32)
_DEST TempImage&
COLOR _RGB32(200, 200, 200), _RGB32(0, 60, 0)
CLS
Background& = HardwareImage&(TempImage&, True)
'Screen
SCREEN _NEWIMAGE(1900, 1000, 32)
_SCREENMOVE 10, 0
_DEST 0
COLOR _RGB32(255, 255, 255)
CLS
_DISPLAYORDER _SOFTWARE , _HARDWARE 'Doesn't display software Days no matter what
K%% = 1
Count& = 0
XSun! = 400
YSun! = 0
ZSun! = 0
XEarth! = XSun! + DXEarth!
YEarth! = YSun! + DYEarth!
ZEarth! = ZSun! + DZEarth!
DXStart! = 700
DXEarth! = DXStart!
VzStart! = -SQR(g! * M1% / 500)
Vx! = 0
Vz! = VzStart!
deltaT! = 0.05
EarthThetaOld! = 0
DYEarth! = 0
DZEarth! = 0
MoonTheta! = 0
SolarSystem%% = True
WHILE SolarSystem%%
K1$ = INKEY$
IF K1$ <> "" THEN
IF ASC(K1$) = 27 THEN SolarSystem%% = False
END IF
K1$ = ""
_LIMIT 60
_PUTIMAGE , Background&
'LOCATE 1, 1 'Want to print days
'PRINT EarthDays%
Count& = Count& + 1
'Display Images
FOR K%% = 1 TO NoImages%%
FOR N%% = 1 TO NoPhis%%
FOR M%% = 1 TO NoThetas%%
'The Sun
'Sun spins on its axis, faster at the equator
SunSpin!(N%%) = SunSpin(N%%) + 0.03 * (SunPoles! + SIN(N%% * Phi!) * SunEquator!)
dx1! = SunRad% * SIN((N%% - 1) * Phi!) * SIN(SunSpin!(N%%) + (M%% - 1 + (K%% - 1) * NoThetas%%) * Theta!)
dy1! = SunRad% * COS((N%% - 1) * Phi!)
dz1! = SunRad% * SIN((N%% - 1) * Phi!) * COS(SunSpin!(N%%) + (M%% - 1 + (K%% - 1) * NoThetas%%) * Theta!)
dx2! = SunRad% * SIN((N%% - 1) * Phi!) * SIN(SunSpin!(N%%) + (M%% + (K%% - 1) * NoThetas%%) * Theta!)
dy2! = SunRad% * COS((N%% - 1) * Phi!)
dz2! = SunRad% * SIN((N%% - 1) * Phi!) * COS(SunSpin!(N%%) + (M%% + (K%% - 1) * NoThetas%%) * Theta!)
dx3! = SunRad% * SIN(N%% * Phi!) * SIN(SunSpin!(N%%) + (M%% + (K%% - 1) * NoThetas%%) * Theta!)
dy3! = SunRad% * COS(N%% * Phi!)
dz3! = SunRad% * SIN(N%% * Phi!) * COS(SunSpin!(N%%) + (M%% + (K%% - 1) * NoThetas%%) * Theta!)
dx4! = SunRad% * SIN(N%% * Phi!) * SIN(SunSpin!(N%%) + (M%% - 1 + (K%% - 1) * NoThetas%%) * Theta!)
dy4! = SunRad% * COS(N%% * Phi!)
dz4! = SunRad% * SIN(N%% * Phi!) * COS(SunSpin!(N%%) + (M%% - 1 + (K%% - 1) * NoThetas%%) * Theta!)
_MAPTRIANGLE (MapFromImage%(N%% - 1, M%% - 1, 0), MapFromImage%(N%% - 1, M%% - 1, 1))-(MapFromImage%(N%% - 1, M%%, 0), MapFromImage%(N%% - 1, M%%, 1))-(MapFromImage%(N%%, M%%, 0), MapFromImage%(N%%, M%%, 1)), SunSpot&(K%%) TO(dx1! + XSun!, dy1! + YSun!, dz1! + ZSun! - ZOffset%)-(dx2! + XSun!, dy2! + YSun!, dz2! + ZSun! - ZOffset%)-(dx3! + XSun!, dy3! + YSun!, dz3! + ZSun! - ZOffset%)
_MAPTRIANGLE (MapFromImage%(N%%, M%%, 0), MapFromImage%(N%%, M%%, 1))-(MapFromImage%(N%%, M%% - 1, 0), MapFromImage%(N%%, M%% - 1, 1))-(MapFromImage%(N%% - 1, M%% - 1, 0), MapFromImage%(N%% - 1, M%% - 1, 1)), SunSpot&(K%%) TO(dx3! + XSun!, dy3! + YSun!, dz3! + ZSun! - ZOffset%)-(dx4! + XSun!, dy4! + YSun!, dz4! + ZSun! - ZOffset%)-(dx1! + XSun!, dy1! + YSun!, dz1! + ZSun! - ZOffset%)
'The Earth
x1! = MapToSphere!(1, N%% - 1, M%% - 1 + (K%% - 1) * NoThetas%%, 0)
z1! = MapToSphere!(1, N%% - 1, M%% - 1 + (K%% - 1) * NoThetas%%, 2)
y1! = MapToSphere!(1, N%% - 1, M%% - 1 + (K%% - 1) * NoThetas%%, 1)
x2! = MapToSphere!(1, N%% - 1, M%% + (K%% - 1) * NoThetas%%, 0)
z2! = MapToSphere!(1, N%% - 1, M%% + (K%% - 1) * NoThetas%%, 2)
y2! = MapToSphere!(1, N%% - 1, M%% + (K%% - 1) * NoThetas%%, 1)
x3! = MapToSphere!(1, N%%, M%% + (K%% - 1) * NoThetas%%, 0)
z3! = MapToSphere!(1, N%%, M%% + (K%% - 1) * NoThetas%%, 2)
y3! = MapToSphere!(1, N%%, M%% + (K%% - 1) * NoThetas%%, 1)
x4! = MapToSphere!(1, N%%, M%% - 1 + (K%% - 1) * NoThetas%%, 0)
z4! = MapToSphere!(1, N%%, M%% - 1 + (K%% - 1) * NoThetas%%, 2)
y4! = MapToSphere!(1, N%%, M%% - 1 + (K%% - 1) * NoThetas%%, 1)
'Rotate Earth (y-axis)
x11! = x1! * COS(EarthOmega!) + z1! * SIN(EarthOmega!)
z11! = -x1! * SIN(EarthOmega!) + z1! * COS(EarthOmega!)
x21! = x2! * COS(EarthOmega!) + z2! * SIN(EarthOmega!)
z21! = -x2! * SIN(EarthOmega!) + z2! * COS(EarthOmega!)
x31! = x3! * COS(EarthOmega!) + z3! * SIN(EarthOmega!)
z31! = -x3! * SIN(EarthOmega!) + z3! * COS(EarthOmega!)
x41! = x4! * COS(EarthOmega!) + z4! * SIN(EarthOmega!)
z41! = -x4! * SIN(EarthOmega!) + z4! * COS(EarthOmega!)
y11! = y1!
y21! = y2!
y31! = y3!
y41! = y4!
'Tilt Earth (z-axis rotation)
dx1! = x11! * COS(EarthTilt!) + y11! * SIN(EarthTilt!)
dy1! = -x11! * SIN(EarthTilt!) + y11! * COS(EarthTilt!)
dx2! = x21! * COS(EarthTilt!) + y21! * SIN(EarthTilt!)
dy2! = -x21! * SIN(EarthTilt!) + y21! * COS(EarthTilt!)
dx3! = x31! * COS(EarthTilt!) + y31! * SIN(EarthTilt!)
dy3! = -x31! * SIN(EarthTilt!) + y31! * COS(EarthTilt!)
dx4! = x41! * COS(EarthTilt!) + y41! * SIN(EarthTilt!)
dy4! = -x41! * SIN(EarthTilt!) + y41! * COS(EarthTilt!)
dz1! = z11!
dz2! = z21!
dz3! = z31!
dz4! = z41!
_MAPTRIANGLE (MapFromImage%(N%% - 1, M%% - 1, 0), MapFromImage%(N%% - 1, M%% - 1, 1))-(MapFromImage%(N%% - 1, M%%, 0), MapFromImage%(N%% - 1, M%%, 1))-(MapFromImage%(N%%, M%%, 0), MapFromImage%(N%%, M%%, 1)), Earthling&(K%%) TO(dx1! + XEarth!, dy1! + YEarth!, dz1! + ZEarth! - ZOffset%)-(dx2! + XEarth!, dy2! + YEarth!, dz2! + ZEarth! - ZOffset%)-(dx3! + XEarth!, dy3! + YEarth!, dz3! + ZEarth! - ZOffset%)
_MAPTRIANGLE (MapFromImage%(N%%, M%%, 0), MapFromImage%(N%%, M%%, 1))-(MapFromImage%(N%%, M%% - 1, 0), MapFromImage%(N%%, M%% - 1, 1))-(MapFromImage%(N%% - 1, M%% - 1, 0), MapFromImage%(N%% - 1, M%% - 1, 1)), Earthling&(K%%) TO(dx3! + XEarth!, dy3! + YEarth!, dz3! + ZEarth! - ZOffset%)-(dx4! + XEarth!, dy4! + YEarth!, dz4! + ZEarth! - ZOffset%)-(dx1! + XEarth!, dy1! + YEarth!, dz1! + ZEarth! - ZOffset%)
'The Moon
XMoon! = XEarth! + RMoon% * COS(MoonTheta!) * COS(MoonTilt!)
ZMoon! = ZEarth! + RMoon% * SIN(MoonTheta!) * COS(MoonTilt!)
YMoon! = YEarth! + RMoon% * COS(MoonTheta!) * SIN(MoonTilt!)
x1! = MapToSphere!(2, N%% - 1, M%% - 1 + (K%% - 1) * NoThetas%%, 0)
z1! = MapToSphere!(2, N%% - 1, M%% - 1 + (K%% - 1) * NoThetas%%, 2)
y1! = MapToSphere!(2, N%% - 1, M%% - 1 + (K%% - 1) * NoThetas%%, 1)
x2! = MapToSphere!(2, N%% - 1, M%% + (K%% - 1) * NoThetas%%, 0)
z2! = MapToSphere!(2, N%% - 1, M%% + (K%% - 1) * NoThetas%%, 2)
y2! = MapToSphere!(2, N%% - 1, M%% + (K%% - 1) * NoThetas%%, 1)
x3! = MapToSphere!(2, N%%, M%% + (K%% - 1) * NoThetas%%, 0)
z3! = MapToSphere!(2, N%%, M%% + (K%% - 1) * NoThetas%%, 2)
y3! = MapToSphere!(2, N%%, M%% + (K%% - 1) * NoThetas%%, 1)
x4! = MapToSphere!(2, N%%, M%% - 1 + (K%% - 1) * NoThetas%%, 0)
z4! = MapToSphere!(2, N%%, M%% - 1 + (K%% - 1) * NoThetas%%, 2)
y4! = MapToSphere!(2, N%%, M%% - 1 + (K%% - 1) * NoThetas%%, 1)
'Rotate Moon (y-axis) in opposite direction to its orbit: it keeps the same face towards Earth
MoonAngle! = -MoonTheta!
dx1! = x1! * COS(MoonAngle!) + z1! * SIN(MoonAngle!)
dz1! = -x1! * SIN(MoonAngle!) + z1! * COS(MoonAngle!)
dx2! = x2! * COS(MoonAngle!) + z2! * SIN(MoonAngle!)
dz2! = -x2! * SIN(MoonAngle!) + z2! * COS(MoonAngle!)
dx3! = x3! * COS(MoonAngle!) + z3! * SIN(MoonAngle!)
dz3! = -x3! * SIN(MoonAngle!) + z3! * COS(MoonAngle!)
dx4! = x4! * COS(MoonAngle!) + z4! * SIN(MoonAngle!)
dz4! = -x4! * SIN(MoonAngle!) + z4! * COS(MoonAngle!)
dy1! = y1!
dy2! = y2!
dy3! = y3!
dy4! = y4!
_MAPTRIANGLE (MapFromImage%(N%% - 1, M%% - 1, 0), MapFromImage%(N%% - 1, M%% - 1, 1))-(MapFromImage%(N%% - 1, M%%, 0), MapFromImage%(N%% - 1, M%%, 1))-(MapFromImage%(N%%, M%%, 0), MapFromImage%(N%%, M%%, 1)), Moony&(K%%) TO(dx1! + XMoon!, dy1! + YMoon!, dz1! + ZMoon! - ZOffset%)-(dx2! + XMoon!, dy2! + YMoon!, dz2! + ZMoon! - ZOffset%)-(dx3! + XMoon!, dy3! + YMoon!, dz3! + ZMoon! - ZOffset%)
_MAPTRIANGLE (MapFromImage%(N%%, M%%, 0), MapFromImage%(N%%, M%%, 1))-(MapFromImage%(N%%, M%% - 1, 0), MapFromImage%(N%%, M%% - 1, 1))-(MapFromImage%(N%% - 1, M%% - 1, 0), MapFromImage%(N%% - 1, M%% - 1, 1)), Moony&(K%%) TO(dx3! + XMoon!, dy3! + YMoon!, dz3! + ZMoon! - ZOffset%)-(dx4! + XMoon!, dy4! + YMoon!, dz4! + ZMoon! - ZOffset%)-(dx1! + XMoon!, dy1! + YMoon!, dz1! + ZMoon! - ZOffset%)
NEXT M%%
NEXT N%%
NEXT K%%
_DISPLAY
'Motions and Rotations
'Earth Rotation (one complete revolution = 1 day)
EarthOmega! = EarthOmega! + SunRot!
IF EarthOmega! > _PI THEN
EarthOmega! = EarthOmega! - 2 * _PI
EarthDays% = EarthDays% + 1
END IF
'Move the Moon relative to Earth in a tilted circular orbit
MoonTheta! = MoonTheta! - MoonOmega! '* deltaT!
IF MoonTheta! < -_PI THEN
MoonTheta! = MoonTheta! + 2 * _PI
MoonDays% = MoonDays% + 1
END IF
EarthTheta! = _ATAN2(DZEarth!, DXEarth!)
IF EarthThetaOld! > 0 AND EarthTheta! <= 0 THEN
'Reset at complete orbital revoltion (slight error in ellipse calculations)
DXEarth! = DXStart!
DZEarth! = 0
Vx! = 0
Vz! = VzStart!
EarthTheta! = 0
EarthThetaOld! = 0
ELSE
'Gravitational calculations for Earth's orbit
R! = SQR(DXEarth! * DXEarth! + DZEarth! * DZEarth!)
A! = g! * M1% / (R! * R!)
Ax! = -A! * COS(EarthTheta!)
Az! = -A! * SIN(EarthTheta!)
deltaVx! = Ax! * deltaT!
deltaVz! = Az! * deltaT!
Vx! = Vx! + deltaVx!
Vz! = Vz! + deltaVz!
DXEarth! = DXEarth! + (Vx! + deltaVx! / 2) * deltaT!
DZEarth! = DZEarth! + (Vz! + deltaVz! / 2) * deltaT!
EarthThetaOld! = EarthTheta!
XEarth! = XSun! + DXEarth!
ZEarth! = ZSun! + DZEarth!
END IF
WEND
SYSTEM
FUNCTION HardwareImage& (ImageName&, Scrap%%)
HardwareImage& = _COPYIMAGE(ImageName&, 33)
IF Scrap%% THEN _FREEIMAGE ImageName&
END FUNCTION

