mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Moved drawing logic to the entities themselves.
This commit is contained in:
parent
1b973b0082
commit
63d42bca55
|
@ -1,4 +1,4 @@
|
||||||
from math import sin, cos, radians
|
from math import sin, cos, radians, hypot
|
||||||
|
|
||||||
|
|
||||||
class Camera(object):
|
class Camera(object):
|
||||||
|
@ -39,3 +39,6 @@ class Camera(object):
|
||||||
dx = cos(radians(self.yaw - 90)) * m
|
dx = cos(radians(self.yaw - 90)) * m
|
||||||
dz = sin(radians(self.yaw - 90)) * m
|
dz = sin(radians(self.yaw - 90)) * m
|
||||||
return dx, dy, dz
|
return dx, dy, dz
|
||||||
|
|
||||||
|
def distance(self, x, y, z):
|
||||||
|
return hypot(hypot(x - self.x, y - self.y), z - self.z)
|
||||||
|
|
|
@ -1,113 +1,189 @@
|
||||||
from math import sqrt
|
import random
|
||||||
|
from math import sqrt, pi
|
||||||
|
|
||||||
from pyglet.gl import *
|
from pyglet.gl import *
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
from six.moves import range
|
||||||
|
|
||||||
|
from punyverse.glgeom import compile, sphere, flare, disk, glMatrix, glRestore, belt
|
||||||
from punyverse.orbit import KeplerOrbit
|
from punyverse.orbit import KeplerOrbit
|
||||||
|
from punyverse.texture import get_best_texture, load_clouds
|
||||||
|
|
||||||
|
try:
|
||||||
|
from punyverse._model import model_list, load_model
|
||||||
|
except ImportError:
|
||||||
|
from punyverse.model import model_list, load_model
|
||||||
|
|
||||||
|
G = 6.67384e-11 # Gravitation Constant
|
||||||
|
|
||||||
|
|
||||||
class Entity(object):
|
class Entity(object):
|
||||||
def __init__(self, id, location, rotation=(0, 0, 0), direction=(0, 0, 0), background=False):
|
def __init__(self, name, location, rotation=(0, 0, 0), direction=(0, 0, 0)):
|
||||||
self.id = id
|
self.name = name
|
||||||
self.location = location
|
self.location = location
|
||||||
self.rotation = rotation
|
self.rotation = rotation
|
||||||
self.direction = direction
|
self.direction = direction
|
||||||
self.background = background
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
x, y, z = self.location
|
x, y, z = self.location
|
||||||
dx, dy, dz = self.direction
|
dx, dy, dz = self.direction
|
||||||
self.location = x + dx, y + dy, z + dz
|
self.location = x + dx, y + dy, z + dz
|
||||||
|
|
||||||
def collides(self, x, y, z):
|
def collides(self, x, y, z):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def draw(self, cam, options):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class Asteroid(Entity):
|
class Asteroid(Entity):
|
||||||
def __init__(self, *args, **kwargs):
|
asteroid_ids = []
|
||||||
super(Asteroid, self).__init__(*args, **kwargs)
|
|
||||||
|
@classmethod
|
||||||
|
def load_asteroid(cls, file):
|
||||||
|
cls.asteroid_ids.append(model_list(load_model(file), 5, 5, 5, (0, 0, 0)))
|
||||||
|
|
||||||
|
def __init__(self, location, direction):
|
||||||
|
super(Asteroid, self).__init__('Asteroid', location, direction=direction)
|
||||||
|
self.asteroid_id = random.choice(self.asteroid_ids)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
super(Asteroid, self).update()
|
super(Asteroid, self).update()
|
||||||
|
|
||||||
rx, ry, rz = self.rotation
|
rx, ry, rz = self.rotation
|
||||||
# Increment all axis to 'spin'
|
# Increment all axis to 'spin'
|
||||||
self.rotation = rx + 1, ry + 1, rz + 1
|
self.rotation = rx + 1, ry + 1, rz + 1
|
||||||
|
|
||||||
|
def draw(self, cam, options):
|
||||||
|
with glMatrix(self.location, self.rotation), glRestore(GL_CURRENT_BIT):
|
||||||
|
glCallList(self.asteroid_id)
|
||||||
|
|
||||||
|
|
||||||
class Belt(Entity):
|
class Belt(Entity):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, name, world, info):
|
||||||
self.rotation_angle = kwargs.pop('rotation_angle', 5)
|
self.world = world
|
||||||
self.world = kwargs.pop('world')
|
|
||||||
super(Belt, self).__init__(*args, **kwargs)
|
x = world.evaluate(info.get('x', 0))
|
||||||
|
y = world.evaluate(info.get('y', 0))
|
||||||
|
z = world.evaluate(info.get('z', 0))
|
||||||
|
radius = world.evaluate(info.get('radius', 0))
|
||||||
|
cross = world.evaluate(info.get('cross', 0))
|
||||||
|
count = int(world.evaluate(info.get('count', 0)))
|
||||||
|
scale = info.get('scale', 1)
|
||||||
|
longitude = info.get('longitude', 0)
|
||||||
|
inclination = info.get('inclination', 0)
|
||||||
|
argument = info.get('argument', 0)
|
||||||
|
rotation = info.get('period', 31536000)
|
||||||
|
models = info['model']
|
||||||
|
if not isinstance(models, list):
|
||||||
|
models = [models]
|
||||||
|
|
||||||
|
objects = [model_list(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
||||||
|
info.get('sz', scale), (0, 0, 0)) for model in models]
|
||||||
|
|
||||||
|
self.belt_id = compile(belt, radius, cross, objects, count)
|
||||||
|
self.rotation_angle = 360.0 / rotation if rotation else 0
|
||||||
|
|
||||||
|
super(Belt, self).__init__(name, (x, y, z), (inclination, longitude, argument))
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
super(Belt, self).update()
|
super(Belt, self).update()
|
||||||
pitch, yaw, roll = self.rotation
|
pitch, yaw, roll = self.rotation
|
||||||
self.rotation = pitch, self.world.tick * self.rotation_angle % 360, roll
|
self.rotation = pitch, self.world.tick * self.rotation_angle % 360, roll
|
||||||
|
|
||||||
|
def draw(self, cam, options):
|
||||||
|
with glMatrix(self.location, self.rotation), glRestore(GL_CURRENT_BIT):
|
||||||
|
glCallList(self.belt_id)
|
||||||
|
|
||||||
|
|
||||||
|
class Sky(Entity):
|
||||||
|
def __init__(self, world, info):
|
||||||
|
pitch = world.evaluate(info.get('pitch', 0))
|
||||||
|
yaw = world.evaluate(info.get('yaw', 0))
|
||||||
|
roll = world.evaluate(info.get('roll', 0))
|
||||||
|
|
||||||
|
super(Sky, self).__init__('Sky', (0, 0, 0), (pitch, yaw, roll))
|
||||||
|
self.world = world
|
||||||
|
|
||||||
|
texture = get_best_texture(info['texture'])
|
||||||
|
division = info.get('division', 30)
|
||||||
|
self.sky_id = compile(sphere, info.get('radius', 1000000), division, division, texture,
|
||||||
|
inside=True, lighting=False)
|
||||||
|
|
||||||
|
def draw(self, cam, options):
|
||||||
|
with glMatrix((-cam.x, -cam.y, -cam.z), self.rotation), glRestore(GL_CURRENT_BIT):
|
||||||
|
glCallList(self.sky_id)
|
||||||
|
|
||||||
|
|
||||||
class Body(Entity):
|
class Body(Entity):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, name, world, info, parent=None):
|
||||||
self.rotation_angle = kwargs.pop('rotation_angle', 5)
|
self.world = world
|
||||||
self.atmosphere = kwargs.pop('atmosphere', 0)
|
self.parent = parent
|
||||||
self.cloudmap = kwargs.pop('cloudmap', 0)
|
self.satellites = []
|
||||||
self.corona = kwargs.pop('corona', 0)
|
|
||||||
self.last_tick = 0
|
x = world.evaluate(info.get('x', 0))
|
||||||
self.mass = kwargs.pop('mass', None)
|
y = world.evaluate(info.get('y', 0))
|
||||||
self.radius = kwargs.pop('radius', None)
|
z = world.evaluate(info.get('z', 0))
|
||||||
self.world = kwargs.pop('world')
|
pitch = world.evaluate(info.get('pitch', 0))
|
||||||
orbit_distance = kwargs.pop('orbit_distance', 40000) + .0
|
yaw = world.evaluate(info.get('yaw', 0))
|
||||||
|
roll = world.evaluate(info.get('roll', 0))
|
||||||
|
rotation = world.evaluate(info.get('rotation', 86400))
|
||||||
|
|
||||||
|
self.mass = info.get('mass')
|
||||||
|
|
||||||
|
orbit_distance = float(world.evaluate(info.get('orbit_distance', world.au)))
|
||||||
self.orbit_show = orbit_distance * 1.25
|
self.orbit_show = orbit_distance * 1.25
|
||||||
self.orbit_blend = orbit_distance / 4
|
self.orbit_blend = orbit_distance / 4
|
||||||
self.orbit_opaque = orbit_distance
|
self.orbit_opaque = orbit_distance
|
||||||
super(Body, self).__init__(*args, **kwargs)
|
|
||||||
self.initial_roll = self.rotation[2]
|
|
||||||
|
|
||||||
def update(self):
|
super(Body, self).__init__(name, (x, y, z), (pitch, yaw, roll))
|
||||||
super(Body, self).update()
|
self.initial_roll = roll
|
||||||
|
|
||||||
if self.last_tick != self.world.tick:
|
self.orbit = None
|
||||||
self.last_tick = self.world.tick
|
self.orbit_speed = None
|
||||||
pitch, yaw, roll = self.rotation
|
|
||||||
roll = (self.initial_roll + self.world.tick * self.rotation_angle) % 360
|
|
||||||
self.rotation = pitch, yaw, roll
|
|
||||||
|
|
||||||
def collides(self, x, y, z):
|
|
||||||
if self.radius is None:
|
|
||||||
return False
|
|
||||||
ox, oy, oz = self.location
|
|
||||||
dx, dy, dz = x - ox, y - oy, z - oz
|
|
||||||
distance = sqrt(dx*dx + dy*dy + dz*dz)
|
|
||||||
if distance > self.radius:
|
|
||||||
return False
|
|
||||||
return (ox + dx * self.radius / distance,
|
|
||||||
oy + dy * self.radius / distance,
|
|
||||||
oz + dz * self.radius / distance)
|
|
||||||
|
|
||||||
|
if parent:
|
||||||
|
# Semi-major axis when actually displayed in virtual space
|
||||||
|
distance = world.evaluate(info.get('distance', 100))
|
||||||
|
# Semi-major axis used to calculate orbital speed
|
||||||
|
sma = world.evaluate(info.get('sma', distance))
|
||||||
|
|
||||||
class Satellite(Body):
|
if hasattr(parent, 'mass') and parent.mass is not None:
|
||||||
def __init__(self, *args, **kwargs):
|
period = 2 * pi * sqrt((sma * 1000) ** 3 / (G * parent.mass))
|
||||||
self.parent = kwargs.pop('parent')
|
self.orbit_speed = 360.0 / period
|
||||||
self.orbit_speed = kwargs.pop('orbit_speed', 1)
|
if not rotation: # Rotation = 0 assumes tidal lock
|
||||||
|
rotation = period
|
||||||
|
else:
|
||||||
|
self.orbit_speed = info.get('orbit_speed', 1)
|
||||||
|
|
||||||
# Semi-major axis and eccentricity defines orbit
|
self.orbit = KeplerOrbit(distance / world.length, info.get('eccentricity', 0), info.get('inclination', 0),
|
||||||
distance = kwargs.pop('distance', 100)
|
info.get('longitude', 0), info.get('argument', 0))
|
||||||
eccentricity = kwargs.pop('eccentricity', 0)
|
|
||||||
|
|
||||||
# Inclination, longitude of ascending node, and argument of periapsis defines orbital plane
|
self.rotation_angle = 360.0 / rotation if rotation else 0
|
||||||
inclination = kwargs.pop('inclination', 0)
|
|
||||||
longitude = kwargs.pop('longitude', 0)
|
|
||||||
argument = kwargs.pop('argument', 0)
|
|
||||||
|
|
||||||
# Orbit calculation
|
# Orbit calculation
|
||||||
self.orbit_id = None
|
self.orbit_id = None
|
||||||
self.orbit_cache = None
|
self.orbit_cache = None
|
||||||
|
|
||||||
self.theta = 0
|
def update(self):
|
||||||
# OpenGL's z-axis is reversed
|
super(Body, self).update()
|
||||||
self.orbit = KeplerOrbit(distance, eccentricity, inclination, longitude, argument)
|
|
||||||
super(Satellite, self).__init__(*args, **kwargs)
|
pitch, yaw, roll = self.rotation
|
||||||
|
roll = (self.initial_roll + self.world.tick * self.rotation_angle) % 360
|
||||||
|
self.rotation = pitch, yaw, roll
|
||||||
|
|
||||||
|
if self.orbit:
|
||||||
|
px, py, pz = self.parent.location
|
||||||
|
x, z, y = self.orbit.orbit(self.world.tick * self.orbit_speed % 360)
|
||||||
|
self.location = (x + px, y + py, z + pz)
|
||||||
|
|
||||||
|
for satellite in self.satellites:
|
||||||
|
satellite.update()
|
||||||
|
|
||||||
def get_orbit(self):
|
def get_orbit(self):
|
||||||
|
if not self.orbit:
|
||||||
|
return
|
||||||
|
|
||||||
# Cache key is the three orbital plane parameters and eccentricity
|
# Cache key is the three orbital plane parameters and eccentricity
|
||||||
cache = (self.orbit.eccentricity, self.orbit.longitude, self.orbit.inclination, self.orbit.argument)
|
cache = (self.orbit.eccentricity, self.orbit.longitude, self.orbit.inclination, self.orbit.argument)
|
||||||
if self.orbit_cache == cache:
|
if self.orbit_cache == cache:
|
||||||
|
@ -129,18 +205,146 @@ class Satellite(Body):
|
||||||
self.orbit_cache = cache
|
self.orbit_cache = cache
|
||||||
return id
|
return id
|
||||||
|
|
||||||
def update(self):
|
def _draw_orbits(self, distance):
|
||||||
super(Body, self).update() # Notice how the parent class is skipped
|
with glMatrix(self.parent.location), glRestore(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT):
|
||||||
|
glDisable(GL_LIGHTING)
|
||||||
|
solid = distance < self.parent.orbit_opaque
|
||||||
|
glColor4f(1, 1, 1, 1 if solid else (1 - (distance - self.parent.orbit_opaque) / self.parent.orbit_blend))
|
||||||
|
if not solid:
|
||||||
|
glEnable(GL_BLEND)
|
||||||
|
glLineWidth(1)
|
||||||
|
glCallList(self.get_orbit())
|
||||||
|
|
||||||
|
def draw(self, cam, options):
|
||||||
|
self._draw(cam, options)
|
||||||
|
|
||||||
|
if options.orbit and self.orbit:
|
||||||
|
dist = cam.distance(*self.parent.location)
|
||||||
|
if dist < self.parent.orbit_show:
|
||||||
|
self._draw_orbits(dist)
|
||||||
|
|
||||||
|
for satellite in self.satellites:
|
||||||
|
satellite.draw(cam, options)
|
||||||
|
|
||||||
|
def _draw(self, cam, options):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def collides(self, x, y, z):
|
||||||
|
return self._collides(x, y, z) or any(satellite.collides(x, y, z) for satellite in self.satellites)
|
||||||
|
|
||||||
|
def _collides(self, x, y, z):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class SphericalBody(Body):
|
||||||
|
def __init__(self, name, world, info, parent=None):
|
||||||
|
super(SphericalBody, self).__init__(name, world, info, parent)
|
||||||
|
|
||||||
|
self.radius = world.evaluate(info.get('radius', world.length)) / world.length
|
||||||
|
division = info.get('division', max(min(int(self.radius / 8), 60), 10))
|
||||||
|
|
||||||
|
texture = get_best_texture(info['texture'])
|
||||||
|
self.sphere_id = compile(sphere, self.radius, division, division, texture)
|
||||||
|
|
||||||
|
self.atmosphere_id = 0
|
||||||
|
self.cloudmap_id = 0
|
||||||
|
self.corona_id = 0
|
||||||
|
self.ring_id = 0
|
||||||
|
|
||||||
|
if 'atmosphere' in info:
|
||||||
|
atmosphere_data = info['atmosphere']
|
||||||
|
atm_size = world.evaluate(atmosphere_data.get('diffuse_size', None))
|
||||||
|
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
||||||
|
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
||||||
|
corona_texture = atmosphere_data.get('corona_texture', None)
|
||||||
|
if cloud_texture is not None:
|
||||||
|
cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
||||||
|
self.cloudmap_id = compile(sphere, self.radius + 2, division, division, cloud_texture, lighting=False)
|
||||||
|
|
||||||
|
if corona_texture is not None:
|
||||||
|
corona = get_best_texture(corona_texture)
|
||||||
|
corona_size = atmosphere_data.get('corona_size', self.radius / 2)
|
||||||
|
corona_division = atmosphere_data.get('corona_division', 100)
|
||||||
|
corona_ratio = atmosphere_data.get('corona_ratio', 0.5)
|
||||||
|
self.corona_id = compile(flare, self.radius, self.radius + corona_size, corona_division,
|
||||||
|
corona_ratio, corona)
|
||||||
|
|
||||||
|
if atm_texture is not None:
|
||||||
|
atm_texture = get_best_texture(atm_texture)
|
||||||
|
self.atmosphere_id = compile(disk, self.radius, self.radius + atm_size, 30, atm_texture)
|
||||||
|
|
||||||
|
if 'ring' in info:
|
||||||
|
distance = world.evaluate(info['ring'].get('distance', self.radius * 1.2))
|
||||||
|
size = world.evaluate(info['ring'].get('size', self.radius / 2))
|
||||||
|
|
||||||
if self.last_tick != self.world.tick:
|
|
||||||
self.last_tick = self.world.tick
|
|
||||||
pitch, yaw, roll = self.rotation
|
pitch, yaw, roll = self.rotation
|
||||||
roll = (self.initial_roll + self.world.tick * self.rotation_angle) % 360
|
pitch = world.evaluate(info['ring'].get('pitch', pitch))
|
||||||
self.rotation = pitch, yaw, roll
|
yaw = world.evaluate(info['ring'].get('yaw', yaw))
|
||||||
|
roll = world.evaluate(info['ring'].get('roll', roll))
|
||||||
|
self.ring_rotation = pitch, yaw, roll
|
||||||
|
|
||||||
self.parent.update()
|
self.ring_id = compile(disk, distance, distance + size, 30,
|
||||||
px, py, pz = self.parent.location
|
get_best_texture(info['ring'].get('texture', None)))
|
||||||
self.theta = self.world.tick * self.orbit_speed % 360
|
|
||||||
x, z, y = self.orbit.orbit(self.theta)
|
|
||||||
self.location = (x + px, y + py, z + pz)
|
|
||||||
|
|
||||||
|
def _draw_sphere(self):
|
||||||
|
with glMatrix(self.location, self.rotation), glRestore(GL_CURRENT_BIT):
|
||||||
|
glCallList(self.sphere_id)
|
||||||
|
|
||||||
|
def _draw_atmosphere(self, cam, glMatrixBuffer=GLfloat * 16):
|
||||||
|
with glMatrix(self.location), glRestore(GL_ENABLE_BIT):
|
||||||
|
matrix = glMatrixBuffer()
|
||||||
|
glGetFloatv(GL_MODELVIEW_MATRIX, matrix)
|
||||||
|
matrix[0: 3] = [1, 0, 0]
|
||||||
|
matrix[4: 7] = [0, 1, 0]
|
||||||
|
matrix[8:11] = [0, 0, 1]
|
||||||
|
glLoadMatrixf(matrix)
|
||||||
|
|
||||||
|
glEnable(GL_BLEND)
|
||||||
|
if self.atmosphere_id:
|
||||||
|
glCallList(self.atmosphere_id)
|
||||||
|
|
||||||
|
if self.corona_id:
|
||||||
|
x, y, z = cam.direction()
|
||||||
|
glTranslatef(-x, -y, -z)
|
||||||
|
glCallList(self.corona_id)
|
||||||
|
|
||||||
|
def _draw_clouds(self):
|
||||||
|
with glMatrix(self.location, self.rotation), glRestore(GL_ENABLE_BIT):
|
||||||
|
glEnable(GL_BLEND)
|
||||||
|
glEnable(GL_ALPHA_TEST)
|
||||||
|
glCallList(self.cloudmap_id)
|
||||||
|
|
||||||
|
def _draw_rings(self):
|
||||||
|
with glMatrix(self.location, self.ring_rotation), glRestore(GL_CURRENT_BIT):
|
||||||
|
glCallList(self.ring_id)
|
||||||
|
|
||||||
|
def _draw(self, cam, options):
|
||||||
|
self._draw_sphere()
|
||||||
|
|
||||||
|
if options.atmosphere and (self.atmosphere_id or self.corona_id):
|
||||||
|
self._draw_atmosphere(cam)
|
||||||
|
|
||||||
|
if options.cloud and self.cloudmap_id:
|
||||||
|
self._draw_clouds()
|
||||||
|
|
||||||
|
if self.ring_id:
|
||||||
|
self._draw_rings()
|
||||||
|
|
||||||
|
def _collides(self, x, y, z):
|
||||||
|
ox, oy, oz = self.location
|
||||||
|
dx, dy, dz = x - ox, y - oy, z - oz
|
||||||
|
distance = sqrt(dx * dx + dy * dy + dz * dz)
|
||||||
|
return distance <= self.radius
|
||||||
|
|
||||||
|
|
||||||
|
class ModelBody(Body):
|
||||||
|
def __init__(self, name, world, info, parent=None):
|
||||||
|
super(ModelBody, self).__init__(name, world, info, parent)
|
||||||
|
|
||||||
|
scale = info.get('scale', 1)
|
||||||
|
self.object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
|
||||||
|
info.get('sz', scale), (0, 0, 0))
|
||||||
|
|
||||||
|
def _draw(self, cam, options):
|
||||||
|
with glMatrix(self.location, self.rotation), glRestore(GL_CURRENT_BIT):
|
||||||
|
glCallList(self.object_id)
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from math import hypot, sqrt, atan2, degrees
|
from math import hypot
|
||||||
from time import clock
|
from time import clock
|
||||||
import time
|
import time
|
||||||
import random
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
@ -29,8 +28,7 @@ from pyglet.window import key, mouse
|
||||||
|
|
||||||
import pyglet
|
import pyglet
|
||||||
|
|
||||||
|
INITIAL_SPEED = 0 # The initial speed of the player
|
||||||
INITIAL_SPEED = 0 # The initial speed of the player
|
|
||||||
MOUSE_SENSITIVITY = 0.3 # Mouse sensitivity, 0..1, none...hyperspeed
|
MOUSE_SENSITIVITY = 0.3 # Mouse sensitivity, 0..1, none...hyperspeed
|
||||||
|
|
||||||
MAX_DELTA = 5
|
MAX_DELTA = 5
|
||||||
|
@ -109,15 +107,15 @@ class Applet(pyglet.window.Window):
|
||||||
self.cloud = not texture.badcard
|
self.cloud = not texture.badcard
|
||||||
|
|
||||||
self.tick = self.world.tick_length
|
self.tick = self.world.tick_length
|
||||||
self.ticks = [1, 2, 5, 10, 20, 40, 60, # Second range
|
self.ticks = [1, 2, 5, 10, 20, 40, 60, # Second range
|
||||||
120, 300, 600, 1200, 1800, 2700, 3600, # Minute range
|
120, 300, 600, 1200, 1800, 2700, 3600, # Minute range
|
||||||
7200, 14400, 21600, 43200, 86400, # Hour range
|
7200, 14400, 21600, 43200, 86400, # Hour range
|
||||||
172800, 432000, 604800, # 2, 5, 7 days
|
172800, 432000, 604800, # 2, 5, 7 days
|
||||||
1209600, 2592000, # 2 week, 1 month
|
1209600, 2592000, # 2 week, 1 month
|
||||||
5270400, 7884000, 15768000, 31536000, # 2, 3, 6, 12 months
|
5270400, 7884000, 15768000, 31536000, # 2, 3, 6, 12 months
|
||||||
63072000, 157680000, 315360000, # 2, 5, 10 years
|
63072000, 157680000, 315360000, # 2, 5, 10 years
|
||||||
630720000, 1576800000, 3153600000, # 20, 50, 100 years
|
630720000, 1576800000, 3153600000, # 20, 50, 100 years
|
||||||
]
|
]
|
||||||
self.__time_per_second_cache = None
|
self.__time_per_second_cache = None
|
||||||
self.__time_per_second_value = None
|
self.__time_per_second_value = None
|
||||||
self.__time_accumulate = 0
|
self.__time_accumulate = 0
|
||||||
|
@ -202,9 +200,9 @@ class Applet(pyglet.window.Window):
|
||||||
|
|
||||||
glLightfv(GL_LIGHT0, GL_POSITION, fv4(.5, .5, 1, 0))
|
glLightfv(GL_LIGHT0, GL_POSITION, fv4(.5, .5, 1, 0))
|
||||||
glLightfv(GL_LIGHT0, GL_SPECULAR, fv4(.5, .5, 1, 1))
|
glLightfv(GL_LIGHT0, GL_SPECULAR, fv4(.5, .5, 1, 1))
|
||||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4(1, 1, 1, 1))
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4(1, 1, 1, 1))
|
||||||
glLightfv(GL_LIGHT1, GL_POSITION, fv4(1, 0, .5, 0))
|
glLightfv(GL_LIGHT1, GL_POSITION, fv4(1, 0, .5, 0))
|
||||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
|
glLightfv(GL_LIGHT1, GL_DIFFUSE, fv4(.5, .5, .5, 1))
|
||||||
glLightfv(GL_LIGHT1, GL_SPECULAR, fv4(1, 1, 1, 1))
|
glLightfv(GL_LIGHT1, GL_SPECULAR, fv4(1, 1, 1, 1))
|
||||||
|
|
||||||
phase = 'Loading asteroids...'
|
phase = 'Loading asteroids...'
|
||||||
|
@ -213,9 +211,9 @@ class Applet(pyglet.window.Window):
|
||||||
def load_asteroids(files):
|
def load_asteroids(files):
|
||||||
for id, file in enumerate(files):
|
for id, file in enumerate(files):
|
||||||
callback(phase, 'Loading %s...' % file, float(id) / len(files))
|
callback(phase, 'Loading %s...' % file, float(id) / len(files))
|
||||||
yield model_list(load_model(file), 5, 5, 5, (0, 0, 0))
|
Asteroid.load_asteroid(file)
|
||||||
|
|
||||||
self.asteroid_ids = list(load_asteroids([r'asteroids/01.obj', r'asteroids/02.obj', r'asteroids/03.obj']))
|
load_asteroids(['asteroids/01.obj', 'asteroids/02.obj', 'asteroids/03.obj'])
|
||||||
|
|
||||||
c = self.cam
|
c = self.cam
|
||||||
c.x, c.y, c.z = self.world.start
|
c.x, c.y, c.z = self.world.start
|
||||||
|
@ -269,8 +267,7 @@ class Applet(pyglet.window.Window):
|
||||||
dx *= speed
|
dx *= speed
|
||||||
dy *= speed
|
dy *= speed
|
||||||
dz *= speed
|
dz *= speed
|
||||||
self.world.tracker.append(Asteroid(random.choice(self.asteroid_ids), (c.x, c.y - 3, c.z + 5),
|
self.world.tracker.append(Asteroid((c.x, c.y - 3, c.z + 5), (dx, dy, dz)))
|
||||||
direction=(dx, dy, dz)))
|
|
||||||
|
|
||||||
def on_mouse_press(self, x, y, button, modifiers):
|
def on_mouse_press(self, x, y, button, modifiers):
|
||||||
self.modifiers = modifiers
|
self.modifiers = modifiers
|
||||||
|
@ -313,7 +310,7 @@ class Applet(pyglet.window.Window):
|
||||||
if not self.loaded:
|
if not self.loaded:
|
||||||
return super(Applet, self).on_resize(width, height)
|
return super(Applet, self).on_resize(width, height)
|
||||||
|
|
||||||
height = max(height, 1) # Prevent / by 0
|
height = max(height, 1) # Prevent / by 0
|
||||||
self.label.y = height - 20
|
self.label.y = height - 20
|
||||||
glViewport(0, 0, width, height)
|
glViewport(0, 0, width, height)
|
||||||
glMatrixMode(GL_PROJECTION)
|
glMatrixMode(GL_PROJECTION)
|
||||||
|
@ -402,77 +399,10 @@ class Applet(pyglet.window.Window):
|
||||||
get_distance = entity_distance(x, y, z)
|
get_distance = entity_distance(x, y, z)
|
||||||
if x != world.x or y != world.y or z != world.z:
|
if x != world.x or y != world.y or z != world.z:
|
||||||
world.tracker.sort(key=get_distance, reverse=True)
|
world.tracker.sort(key=get_distance, reverse=True)
|
||||||
world.tracker.sort(key=attrgetter('background'), reverse=True)
|
|
||||||
world.x, world.y, world.z = x, y, z
|
world.x, world.y, world.z = x, y, z
|
||||||
|
|
||||||
for entity in world.tracker:
|
for entity in world.tracker:
|
||||||
x, y, z = entity.location
|
entity.draw(c, self)
|
||||||
pitch, yaw, roll = entity.rotation
|
|
||||||
|
|
||||||
with glMatrix(), glRestore(GL_CURRENT_BIT):
|
|
||||||
if entity.background:
|
|
||||||
glTranslatef(c.x, c.y, c.z)
|
|
||||||
else:
|
|
||||||
glTranslatef(x, y, z)
|
|
||||||
glRotatef(pitch, 1, 0, 0)
|
|
||||||
glRotatef(yaw, 0, 1, 0)
|
|
||||||
glRotatef(roll, 0, 0, 1)
|
|
||||||
glCallList(entity.id)
|
|
||||||
if self.debug:
|
|
||||||
with glMatrix(), glRestore(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LINE_BIT):
|
|
||||||
glLineWidth(0.25)
|
|
||||||
glPolygonOffset(1, 1)
|
|
||||||
glDisable(GL_LIGHTING)
|
|
||||||
glDisable(GL_TEXTURE_2D)
|
|
||||||
glColor3f(0, 1, 0)
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
|
|
||||||
glCallList(entity.id)
|
|
||||||
|
|
||||||
has_corona = hasattr(entity, 'corona') and entity.corona
|
|
||||||
has_atmosphere = hasattr(entity, 'atmosphere') and entity.atmosphere
|
|
||||||
if self.atmosphere and (has_corona or has_atmosphere):
|
|
||||||
with glMatrix(), glRestore(GL_ENABLE_BIT):
|
|
||||||
x0, y0, z0 = entity.location
|
|
||||||
glTranslatef(x0, y0, z0)
|
|
||||||
matrix = glMatrixBuffer()
|
|
||||||
glGetFloatv(GL_MODELVIEW_MATRIX, matrix)
|
|
||||||
matrix[0: 3] = [1, 0, 0]
|
|
||||||
matrix[4: 7] = [0, 1, 0]
|
|
||||||
matrix[8:11] = [0, 0, 1]
|
|
||||||
glLoadMatrixf(matrix)
|
|
||||||
glEnable(GL_BLEND)
|
|
||||||
if has_atmosphere:
|
|
||||||
glCallList(entity.atmosphere)
|
|
||||||
if has_corona:
|
|
||||||
x, y, z = c.direction()
|
|
||||||
glTranslatef(-x, -y, -z)
|
|
||||||
glCallList(entity.corona)
|
|
||||||
|
|
||||||
if self.cloud and hasattr(entity, 'cloudmap') and entity.cloudmap:
|
|
||||||
with glMatrix(), glRestore(GL_ENABLE_BIT):
|
|
||||||
glEnable(GL_BLEND)
|
|
||||||
glEnable(GL_ALPHA_TEST)
|
|
||||||
glTranslatef(*entity.location)
|
|
||||||
pitch, yaw, roll = entity.rotation
|
|
||||||
glRotatef(pitch, 1, 0, 0)
|
|
||||||
glRotatef(yaw, 0, 1, 0)
|
|
||||||
glRotatef(roll, 0, 0, 1)
|
|
||||||
glCallList(entity.cloudmap)
|
|
||||||
|
|
||||||
if self.orbit and hasattr(entity, 'get_orbit') and hasattr(entity, 'parent'):
|
|
||||||
parent = entity.parent
|
|
||||||
distance = get_distance(parent)
|
|
||||||
if distance < parent.orbit_show:
|
|
||||||
with glMatrix(), glRestore(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT):
|
|
||||||
glTranslatef(*entity.parent.location)
|
|
||||||
glDisable(GL_LIGHTING)
|
|
||||||
solid = distance < parent.orbit_opaque
|
|
||||||
glColor4f(1, 1, 1, 1 if solid else
|
|
||||||
(1 - (distance - parent.orbit_opaque) / parent.orbit_blend))
|
|
||||||
if not solid:
|
|
||||||
glEnable(GL_BLEND)
|
|
||||||
glLineWidth(1)
|
|
||||||
glCallList(entity.get_orbit())
|
|
||||||
|
|
||||||
glColor4f(1, 1, 1, 1)
|
glColor4f(1, 1, 1, 1)
|
||||||
glDisable(GL_TEXTURE_2D)
|
glDisable(GL_TEXTURE_2D)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from math import *
|
from math import *
|
||||||
from random import random, gauss, choice
|
from random import random, gauss, choice
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
from pyglet.gl import *
|
from pyglet.gl import *
|
||||||
from pyglet.gl.gl_info import have_extension
|
from pyglet.gl.gl_info import have_extension
|
||||||
|
@ -34,9 +35,22 @@ class glRestore(object):
|
||||||
|
|
||||||
|
|
||||||
class glMatrix(object):
|
class glMatrix(object):
|
||||||
|
def __init__(self, location=None, rotation=None):
|
||||||
|
self.location = location
|
||||||
|
self.rotation = rotation
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
glPushMatrix()
|
glPushMatrix()
|
||||||
|
|
||||||
|
if self.location:
|
||||||
|
glTranslatef(*self.location)
|
||||||
|
|
||||||
|
if self.rotation:
|
||||||
|
pitch, yaw, roll = self.rotation
|
||||||
|
glRotatef(pitch, 1, 0, 0)
|
||||||
|
glRotatef(yaw, 0, 1, 0)
|
||||||
|
glRotatef(roll, 0, 0, 1)
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
glPopMatrix()
|
glPopMatrix()
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
from pyglet import image
|
import itertools
|
||||||
from pyglet.gl import *
|
|
||||||
from ctypes import c_int, byref, c_uint
|
|
||||||
import os.path
|
import os.path
|
||||||
import struct
|
import struct
|
||||||
import itertools
|
from ctypes import c_int, byref, c_uint
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
from pyglet import image
|
||||||
|
from pyglet.gl import *
|
||||||
from six.moves import zip
|
from six.moves import zip
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from punyverse._glgeom import bgr_to_rgb, flip_vertical
|
from punyverse._glgeom import bgr_to_rgb, flip_vertical
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
warnings.warn('Compile _glgeom.c, or double the start up time.')
|
warnings.warn('Compile _glgeom.c, or double the start up time.')
|
||||||
|
|
||||||
# Use magick when _glgeom is not compiled (is actually slower)
|
# Use magick when _glgeom is not compiled (is actually slower)
|
||||||
|
@ -27,6 +28,7 @@ except ImportError:
|
||||||
|
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
|
|
||||||
|
|
||||||
def bgr_to_rgb(source, width, height, alpha=False):
|
def bgr_to_rgb(source, width, height, alpha=False):
|
||||||
length = len(source)
|
length = len(source)
|
||||||
depth = length // (width * height)
|
depth = length // (width * height)
|
||||||
|
@ -37,23 +39,24 @@ except ImportError:
|
||||||
for x in range(width):
|
for x in range(width):
|
||||||
offset = y * row + x * depth
|
offset = y * row + x * depth
|
||||||
for i in range(depth2):
|
for i in range(depth2):
|
||||||
result[offset+i] = source[offset+depth2-i-1]
|
result[offset + i] = source[offset + depth2 - i - 1]
|
||||||
if alpha:
|
if alpha:
|
||||||
result[offset+depth2] = source[offset+depth2]
|
result[offset + depth2] = source[offset + depth2]
|
||||||
return six.binary_type(result)
|
return six.binary_type(result)
|
||||||
|
|
||||||
|
|
||||||
def flip_vertical(source, width, height):
|
def flip_vertical(source, width, height):
|
||||||
length = len(source)
|
length = len(source)
|
||||||
row = length // height
|
row = length // height
|
||||||
result = bytearray(length)
|
result = bytearray(length)
|
||||||
for y1 in range(height):
|
for y1 in range(height):
|
||||||
y2 = height - y1 - 1
|
y2 = height - y1 - 1
|
||||||
result[y1*row:y1*row+row] = source[y2*row:y2*row+row]
|
result[y1 * row:y1 * row + row] = source[y2 * row:y2 * row + row]
|
||||||
return six.binary_type(result)
|
return six.binary_type(result)
|
||||||
else:
|
else:
|
||||||
magick = False
|
magick = False
|
||||||
|
|
||||||
__all__ = ['load_texture', 'load_clouds', 'load_image', 'pil_load']
|
__all__ = ['load_texture', 'load_clouds', 'load_image', 'get_best_texture']
|
||||||
|
|
||||||
id = 0
|
id = 0
|
||||||
cache = {}
|
cache = {}
|
||||||
|
@ -76,11 +79,12 @@ def init():
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn('Please update your graphics drivers if possible')
|
warnings.warn('Please update your graphics drivers if possible')
|
||||||
|
|
||||||
#bgra = gl_info.have_extension('GL_EXT_bgra')
|
# bgra = gl_info.have_extension('GL_EXT_bgra')
|
||||||
|
|
||||||
if power_of_two is None:
|
if power_of_two is None:
|
||||||
power_of_two = gl_info.have_version(2) or gl_info.have_extension('GL_ARB_texture_non_power_of_two')
|
power_of_two = gl_info.have_version(2) or gl_info.have_extension('GL_ARB_texture_non_power_of_two')
|
||||||
|
|
||||||
|
|
||||||
is_power2 = lambda num: num != 0 and ((num & (num - 1)) == 0)
|
is_power2 = lambda num: num != 0 and ((num & (num - 1)) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,7 +138,7 @@ def image_info(data):
|
||||||
h, w = struct.unpack(">HH", jpeg.read(4))
|
h, w = struct.unpack(">HH", jpeg.read(4))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2)
|
jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0]) - 2)
|
||||||
b = jpeg.read(1)
|
b = jpeg.read(1)
|
||||||
width = int(w)
|
width = int(w)
|
||||||
height = int(h)
|
height = int(h)
|
||||||
|
@ -233,17 +237,10 @@ def load_texture(file):
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
|
||||||
gluBuild2DMipmaps(GL_TEXTURE_2D, depth, width, height, mode, GL_UNSIGNED_BYTE, texture)
|
gluBuild2DMipmaps(GL_TEXTURE_2D, depth, width, height, mode, GL_UNSIGNED_BYTE, texture)
|
||||||
|
|
||||||
cache[path] = id
|
cache[path] = id
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
|
||||||
def pil_load(file):
|
|
||||||
from PIL import Image
|
|
||||||
return Image.open(os.path.join(os.path.dirname(__file__), 'assets', 'textures', file))
|
|
||||||
|
|
||||||
|
|
||||||
def load_clouds(file):
|
def load_clouds(file):
|
||||||
if os.path.isabs(file):
|
if os.path.isabs(file):
|
||||||
path = file
|
path = file
|
||||||
|
@ -275,3 +272,15 @@ def load_clouds(file):
|
||||||
cache[path] = id
|
cache[path] = id
|
||||||
|
|
||||||
return id
|
return id
|
||||||
|
|
||||||
|
|
||||||
|
def get_best_texture(info, loader=load_texture):
|
||||||
|
if isinstance(info, list):
|
||||||
|
for item in info:
|
||||||
|
try:
|
||||||
|
return loader(item)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return loader(info)
|
||||||
|
raise ValueError('No texture found')
|
||||||
|
|
|
@ -286,19 +286,6 @@
|
||||||
"rotation": 57996,
|
"rotation": 57996,
|
||||||
"pitch": -90,
|
"pitch": -90,
|
||||||
"yaw": 28.32
|
"yaw": 28.32
|
||||||
},
|
|
||||||
"sky": {
|
|
||||||
"texture": "sky.jpg",
|
|
||||||
"rotation": 0,
|
|
||||||
"optional": true,
|
|
||||||
"lighting": false,
|
|
||||||
"radius": 305000000,
|
|
||||||
"division": 30,
|
|
||||||
"pitch": 90,
|
|
||||||
"yaw": 30,
|
|
||||||
"roll": 180,
|
|
||||||
"delta": 0,
|
|
||||||
"background": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"belts": {
|
"belts": {
|
||||||
|
@ -311,6 +298,15 @@
|
||||||
"rotation": 114536500
|
"rotation": 114536500
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sky": {
|
||||||
|
"texture": "sky.jpg",
|
||||||
|
"rotation": 0,
|
||||||
|
"radius": 305000000,
|
||||||
|
"division": 30,
|
||||||
|
"pitch": 90,
|
||||||
|
"yaw": 30,
|
||||||
|
"roll": 180
|
||||||
|
},
|
||||||
"start": {
|
"start": {
|
||||||
"z": "AU - 400",
|
"z": "AU - 400",
|
||||||
"yaw": 180
|
"yaw": 180
|
||||||
|
|
|
@ -18,27 +18,9 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from punyverse.model import model_list, load_model
|
from punyverse.model import model_list, load_model
|
||||||
|
|
||||||
from punyverse.glgeom import *
|
|
||||||
from punyverse.entity import *
|
from punyverse.entity import *
|
||||||
from punyverse.texture import *
|
|
||||||
from punyverse import texture
|
from punyverse import texture
|
||||||
|
|
||||||
from math import pi, sqrt
|
|
||||||
|
|
||||||
G = 6.67384e-11 # Gravitation Constant
|
|
||||||
|
|
||||||
|
|
||||||
def get_best_texture(info, loader=load_texture):
|
|
||||||
if isinstance(info, list):
|
|
||||||
for item in info:
|
|
||||||
try:
|
|
||||||
return loader(item)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
return loader(info)
|
|
||||||
raise ValueError('No texture found')
|
|
||||||
|
|
||||||
|
|
||||||
def load_world(file, callback=lambda message, completion: None):
|
def load_world(file, callback=lambda message, completion: None):
|
||||||
return World(file, callback)
|
return World(file, callback)
|
||||||
|
@ -61,9 +43,17 @@ class World(object):
|
||||||
self._parse(file)
|
self._parse(file)
|
||||||
del self.callback # So it can't be used after loading finishes
|
del self.callback # So it can't be used after loading finishes
|
||||||
|
|
||||||
def _eval(self, value):
|
def evaluate(self, value):
|
||||||
return eval(str(value), {'__builtins__': None}, self._context)
|
return eval(str(value), {'__builtins__': None}, self._context)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def length(self):
|
||||||
|
return self._length
|
||||||
|
|
||||||
|
@property
|
||||||
|
def au(self):
|
||||||
|
return self._au
|
||||||
|
|
||||||
def _parse(self, file):
|
def _parse(self, file):
|
||||||
self.callback(self._phase, 'Loading configuration file...', 0)
|
self.callback(self._phase, 'Loading configuration file...', 0)
|
||||||
with open(os.path.join(os.path.dirname(__file__), file)) as f:
|
with open(os.path.join(os.path.dirname(__file__), file)) as f:
|
||||||
|
@ -88,12 +78,12 @@ class World(object):
|
||||||
|
|
||||||
if 'start' in root:
|
if 'start' in root:
|
||||||
info = root['start']
|
info = root['start']
|
||||||
x = self._eval(info.get('x', 0))
|
x = self.evaluate(info.get('x', 0))
|
||||||
y = self._eval(info.get('y', 0))
|
y = self.evaluate(info.get('y', 0))
|
||||||
z = self._eval(info.get('z', 0))
|
z = self.evaluate(info.get('z', 0))
|
||||||
pitch = self._eval(info.get('pitch', 0))
|
pitch = self.evaluate(info.get('pitch', 0))
|
||||||
yaw = self._eval(info.get('yaw', 0))
|
yaw = self.evaluate(info.get('yaw', 0))
|
||||||
roll = self._eval(info.get('roll', 0))
|
roll = self.evaluate(info.get('roll', 0))
|
||||||
self.start = (x, y, z)
|
self.start = (x, y, z)
|
||||||
self.direction = (pitch, yaw, roll)
|
self.direction = (pitch, yaw, roll)
|
||||||
|
|
||||||
|
@ -112,134 +102,33 @@ class World(object):
|
||||||
message = 'Loading %s.' % name
|
message = 'Loading %s.' % name
|
||||||
print(message)
|
print(message)
|
||||||
self.callback(self._phase, message, float(self._current_object) / len(root['belts']))
|
self.callback(self._phase, message, float(self._current_object) / len(root['belts']))
|
||||||
self._belt(name, info)
|
self.tracker.append(Belt(name, self, info))
|
||||||
|
|
||||||
def _belt(self, name, info):
|
if 'sky' in root:
|
||||||
x = self._eval(info.get('x', 0))
|
self._phase = 'Loading sky...'
|
||||||
y = self._eval(info.get('y', 0))
|
message = 'Loading sky.'
|
||||||
z = self._eval(info.get('z', 0))
|
print(message)
|
||||||
radius = self._eval(info.get('radius', 0))
|
self.callback(self._phase, message, 0)
|
||||||
cross = self._eval(info.get('cross', 0))
|
self.tracker.append(Sky(self, root['sky']))
|
||||||
count = int(self._eval(info.get('count', 0)))
|
|
||||||
scale = info.get('scale', 1)
|
|
||||||
longitude = info.get('longitude', 0)
|
|
||||||
inclination = info.get('inclination', 0)
|
|
||||||
argument = info.get('argument', 0)
|
|
||||||
rotation = info.get('period', 31536000)
|
|
||||||
theta = 360 / (rotation + .0) if rotation else 0
|
|
||||||
|
|
||||||
models = info['model']
|
|
||||||
if not isinstance(models, list):
|
|
||||||
models = [models]
|
|
||||||
objects = []
|
|
||||||
for model in models:
|
|
||||||
objects.append(model_list(load_model(model), info.get('sx', scale), info.get('sy', scale),
|
|
||||||
info.get('sz', scale), (0, 0, 0)))
|
|
||||||
|
|
||||||
self.tracker.append(Belt(compile(belt, radius, cross, objects, count),
|
|
||||||
(x, y, z), (inclination, longitude, argument),
|
|
||||||
rotation_angle=theta, world=self))
|
|
||||||
|
|
||||||
def _body(self, name, info, parent=None):
|
def _body(self, name, info, parent=None):
|
||||||
lighting = info.get('lighting', True)
|
|
||||||
x = self._eval(info.get('x', 0))
|
|
||||||
y = self._eval(info.get('y', 0))
|
|
||||||
z = self._eval(info.get('z', 0))
|
|
||||||
pitch = self._eval(info.get('pitch', 0))
|
|
||||||
yaw = self._eval(info.get('yaw', 0))
|
|
||||||
roll = self._eval(info.get('roll', 0))
|
|
||||||
rotation = self._eval(info.get('rotation', 86400))
|
|
||||||
radius = self._eval(info.get('radius', self._length)) / self._length
|
|
||||||
background = info.get('background', False)
|
|
||||||
orbit_distance = self._eval(info.get('orbit_distance', self._au))
|
|
||||||
division = info.get('division', max(min(int(radius / 8), 60), 10))
|
|
||||||
|
|
||||||
if 'texture' in info:
|
if 'texture' in info:
|
||||||
texture = get_best_texture(info['texture'])
|
body = SphericalBody(name, self, info, parent)
|
||||||
if self.options.get('normal', False) and 'normal' in info:
|
|
||||||
object_id = compile(normal_sphere, radius, division, texture,
|
|
||||||
info['normal'], lighting=lighting, inside=background)
|
|
||||||
else:
|
|
||||||
object_id = compile(sphere, radius, division, division, texture,
|
|
||||||
lighting=lighting, inside=background)
|
|
||||||
elif 'model' in info:
|
elif 'model' in info:
|
||||||
scale = info.get('scale', 1)
|
body = ModelBody(name, self, info, parent)
|
||||||
object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
|
|
||||||
info.get('sz', scale), (0, 0, 0))
|
|
||||||
else:
|
else:
|
||||||
print('Nothing to load for %s.' % name)
|
print('Nothing to load for %s.' % name)
|
||||||
return
|
return
|
||||||
|
|
||||||
params = {'world': self, 'orbit_distance': orbit_distance, 'radius': None if background else radius}
|
if parent:
|
||||||
if parent is None:
|
parent.satellites.append(body)
|
||||||
type = Body
|
|
||||||
else:
|
else:
|
||||||
x, y, z = parent.location
|
self.tracker.append(body)
|
||||||
distance = self._eval(info.get('distance', 100)) # Semi-major axis when actually displayed in virtual space
|
|
||||||
sma = self._eval(info.get('sma', distance)) # Semi-major axis used to calculate orbital speed
|
|
||||||
if hasattr(parent, 'mass') and parent.mass is not None:
|
|
||||||
period = 2 * pi * sqrt((sma * 1000) ** 3 / (G * parent.mass))
|
|
||||||
speed = 360 / (period + .0)
|
|
||||||
if not rotation: # Rotation = 0 assumes tidal lock
|
|
||||||
rotation = period
|
|
||||||
else:
|
|
||||||
speed = info.get('orbit_speed', 1)
|
|
||||||
type = Satellite
|
|
||||||
params.update(parent=parent, orbit_speed=speed,
|
|
||||||
distance=distance / self._length, eccentricity=info.get('eccentricity', 0),
|
|
||||||
inclination=info.get('inclination', 0), longitude=info.get('longitude', 0),
|
|
||||||
argument=info.get('argument', 0))
|
|
||||||
|
|
||||||
if 'mass' in info:
|
|
||||||
params['mass'] = info['mass']
|
|
||||||
|
|
||||||
atmosphere_id = 0
|
|
||||||
cloudmap_id = 0
|
|
||||||
corona_id = 0
|
|
||||||
if 'atmosphere' in info:
|
|
||||||
atmosphere_data = info['atmosphere']
|
|
||||||
atm_size = self._eval(atmosphere_data.get('diffuse_size', None))
|
|
||||||
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
|
||||||
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
|
||||||
corona_texture = atmosphere_data.get('corona_texture', None)
|
|
||||||
if cloud_texture is not None:
|
|
||||||
cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
|
||||||
cloudmap_id = compile(sphere, radius + 2, division, division, cloud_texture, lighting=False)
|
|
||||||
|
|
||||||
if corona_texture is not None:
|
|
||||||
corona = get_best_texture(corona_texture)
|
|
||||||
corona_size = atmosphere_data.get('corona_size', radius / 2)
|
|
||||||
corona_division = atmosphere_data.get('corona_division', 100)
|
|
||||||
corona_ratio = atmosphere_data.get('corona_ratio', 0.5)
|
|
||||||
corona_id = compile(flare, radius, radius + corona_size, corona_division, corona_ratio, corona)
|
|
||||||
|
|
||||||
if atm_texture is not None:
|
|
||||||
atm_texture = get_best_texture(atm_texture)
|
|
||||||
atmosphere_id = compile(disk, radius, radius + atm_size, 30, atm_texture)
|
|
||||||
|
|
||||||
theta = 360.0 / rotation if rotation else 0
|
|
||||||
object = type(object_id, (x, y, z), (pitch, yaw, roll), rotation_angle=theta,
|
|
||||||
atmosphere=atmosphere_id, cloudmap=cloudmap_id, background=background,
|
|
||||||
corona=corona_id, **params)
|
|
||||||
self.tracker.append(object)
|
|
||||||
|
|
||||||
if 'ring' in info:
|
|
||||||
ring_data = info['ring']
|
|
||||||
texture = ring_data.get('texture', None)
|
|
||||||
distance = self._eval(ring_data.get('distance', radius * 1.2))
|
|
||||||
size = self._eval(ring_data.get('size', radius / 2))
|
|
||||||
pitch = self._eval(ring_data.get('pitch', pitch))
|
|
||||||
yaw = self._eval(ring_data.get('yaw', yaw))
|
|
||||||
roll = self._eval(ring_data.get('roll', roll))
|
|
||||||
|
|
||||||
texture = get_best_texture(texture)
|
|
||||||
self.tracker.append(type(compile(disk, distance, distance + size, 30, texture), (x, y, z),
|
|
||||||
(pitch, yaw, roll), **params))
|
|
||||||
|
|
||||||
for satellite, info in six.iteritems(info.get('satellites', {})):
|
for satellite, info in six.iteritems(info.get('satellites', {})):
|
||||||
message = 'Loading %s, satellite of %s.' % (satellite, name)
|
message = 'Loading %s, satellite of %s.' % (satellite, name)
|
||||||
print(message)
|
print(message)
|
||||||
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
|
self.callback('Loading objects (%d of %d)...' % (self._current_object, self._objects),
|
||||||
message, float(self._current_object) / self._objects)
|
message, float(self._current_object) / self._objects)
|
||||||
self._body(satellite, info, object)
|
self._body(satellite, info, body)
|
||||||
self._current_object += 1
|
self._current_object += 1
|
||||||
|
|
Loading…
Reference in a new issue