mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Added proper orbit calculations, and limited orbital plane calculations (only inclination is used).
This commit is contained in:
parent
f87524916e
commit
412387cc71
|
@ -1,5 +1,7 @@
|
||||||
from punyverse import framedata
|
from punyverse import framedata
|
||||||
from math import radians, sin, cos
|
from math import radians, sin, cos
|
||||||
|
from punyverse.orbit import KeplerOrbit
|
||||||
|
|
||||||
|
|
||||||
class Entity(object):
|
class Entity(object):
|
||||||
def __init__(self, id, location, rotation=(0, 0, 0), direction=(0, 0, 0), background=False):
|
def __init__(self, id, location, rotation=(0, 0, 0), direction=(0, 0, 0), background=False):
|
||||||
|
@ -48,9 +50,17 @@ class Satellite(Planet):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.parent = kwargs.pop('parent')
|
self.parent = kwargs.pop('parent')
|
||||||
self.orbit_speed = kwargs.pop('orbit_speed', 1)
|
self.orbit_speed = kwargs.pop('orbit_speed', 1)
|
||||||
self.inclination = kwargs.pop('inclination', 0)
|
|
||||||
|
# Semi-major axis and eccentricity defines orbit
|
||||||
self.distance = kwargs.pop('distance', 100)
|
self.distance = kwargs.pop('distance', 100)
|
||||||
|
self.eccentricity = kwargs.pop('eccentricity', 0)
|
||||||
|
|
||||||
|
# Inclination and longitude of ascending node defines orbital plane
|
||||||
|
self.inclination = kwargs.pop('inclination', 0)
|
||||||
|
|
||||||
self.theta = 0
|
self.theta = 0
|
||||||
|
# OpenGL's z-axis is reversed
|
||||||
|
self.orbit = KeplerOrbit(self.distance, self.eccentricity, -self.inclination)
|
||||||
super(Satellite, self).__init__(*args, **kwargs)
|
super(Satellite, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
@ -63,10 +73,8 @@ class Satellite(Planet):
|
||||||
self.rotation = pitch, yaw, roll
|
self.rotation = pitch, yaw, roll
|
||||||
|
|
||||||
self.parent.update()
|
self.parent.update()
|
||||||
x, y, z = self.location
|
|
||||||
px, py, pz = self.parent.location
|
px, py, pz = self.parent.location
|
||||||
self.theta += self.orbit_speed
|
self.theta += self.orbit_speed
|
||||||
x = cos(radians(self.theta)) * self.distance + px
|
x, z, y = self.orbit.orbit(self.theta)
|
||||||
z = sin(radians(self.theta)) * self.distance + pz
|
self.location = (x + px, y + py, z + pz)
|
||||||
self.location = (x, y, z)
|
|
||||||
|
|
||||||
|
|
36
punyverse/orbit.py
Normal file
36
punyverse/orbit.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from math import sin, cos, tan, atan, sqrt, radians
|
||||||
|
|
||||||
|
|
||||||
|
class KeplerOrbit(object):
|
||||||
|
def __init__(self, sma, eccentricity, inclination=0):
|
||||||
|
self.sma = sma
|
||||||
|
self.eccentricity = eccentricity
|
||||||
|
self.inclination = radians(inclination)
|
||||||
|
self.__true_anomaly_factor = sqrt((1 + eccentricity)/(1 - eccentricity))
|
||||||
|
self.__distance_factor = sma * (1 - eccentricity ** 2)
|
||||||
|
self.__sin_inclination = sin(self.inclination)
|
||||||
|
self.__cos_inclination = cos(self.inclination)
|
||||||
|
|
||||||
|
def eccentric_anomaly(self, mean_anomaly):
|
||||||
|
e1 = mean_anomaly
|
||||||
|
e2 = mean_anomaly + self.eccentricity * sin(e1)
|
||||||
|
while abs(e1 - e2) > 0.000001:
|
||||||
|
e1, e2 = e2, mean_anomaly + self.eccentricity * sin(e2)
|
||||||
|
return e2
|
||||||
|
|
||||||
|
def true_anomaly(self, mean_anomaly):
|
||||||
|
eccentric_anomaly = self.eccentric_anomaly(mean_anomaly)
|
||||||
|
return 2 * atan(self.__true_anomaly_factor * tan(eccentric_anomaly / 2))
|
||||||
|
|
||||||
|
def orbit(self, mean_anomaly):
|
||||||
|
mean_anomaly = radians(mean_anomaly)
|
||||||
|
phi = self.true_anomaly(mean_anomaly)
|
||||||
|
r = self.__distance_factor / (1 + self.eccentricity * cos(phi))
|
||||||
|
x = r * cos(phi)
|
||||||
|
y = r * sin(phi)
|
||||||
|
z = 0
|
||||||
|
|
||||||
|
x, z = (x * self.__cos_inclination - z * self.__sin_inclination,
|
||||||
|
x * self.__sin_inclination + z * self.__cos_inclination)
|
||||||
|
|
||||||
|
return x, y, z
|
|
@ -17,6 +17,9 @@
|
||||||
"texture": ["moon.jpg", "moon_medium.jpg", "moon_small.jpg", [0.53, 0.53, 0.53, 1]],
|
"texture": ["moon.jpg", "moon_medium.jpg", "moon_small.jpg", [0.53, 0.53, 0.53, 1]],
|
||||||
"radius": 25,
|
"radius": 25,
|
||||||
"distance": 200,
|
"distance": 200,
|
||||||
|
"orbit_speed": 1,
|
||||||
|
"eccentricity": 0.0549,
|
||||||
|
"inclination": 5.145,
|
||||||
"pitch": -90,
|
"pitch": -90,
|
||||||
"yaw": 6.68
|
"yaw": 6.68
|
||||||
},
|
},
|
||||||
|
|
|
@ -107,8 +107,9 @@ def load_world(file):
|
||||||
x, y, z = parent.location
|
x, y, z = parent.location
|
||||||
distance = e(info.get('distance', 100))
|
distance = e(info.get('distance', 100))
|
||||||
x -= distance
|
x -= distance
|
||||||
type = partial(Satellite, parent=parent, distance=distance, inclination=e(info.get('inclination', 0)),
|
type = partial(Satellite, parent=parent, orbit_speed=info.get('orbit_speed', 1),
|
||||||
orbit_speed=e(info.get('orbit_speed', 1)))
|
distance=distance, eccentricity=info.get('eccentricity', 0),
|
||||||
|
inclination=info.get('inclination', 0))
|
||||||
|
|
||||||
atmosphere_id = 0
|
atmosphere_id = 0
|
||||||
cloudmap_id = 0
|
cloudmap_id = 0
|
||||||
|
|
Loading…
Reference in a new issue