punyverse/punyverse/world.py
Quantum b2e3a1d486 Attempts to maintain the balance between correctness and appearance.
Added mip mapping due to the increase in distance.
2013-10-25 20:48:03 -04:00

167 lines
5.9 KiB
Python

from bisect import bisect_left
from collections import OrderedDict
from operator import itemgetter
from functools import partial
import hashlib
import os.path
import random
try:
import json
except ImportError:
try:
import simplejson as json
except ImportError:
print "No compatible JSON decoder found. Translation: you're fucked."
try:
from _model import model_list, load_model
except ImportError:
from model import model_list, load_model
from punyverse.glgeom import *
from punyverse.entity import *
from punyverse.texture import *
AU = 2000
def get_best_texture(info, optional=False):
cheap = False
skip = False
texture = None
if isinstance(info, list):
for item in info:
if isinstance(item, list):
if len(item) == 4:
cheap = True
texture = item
break
continue
try:
texture = load_texture(item)
except ValueError:
pass
else:
break
else:
try:
texture = load_texture(info)
except ValueError:
if optional:
skip = True
else:
cheap = True
texture = [1, 1, 1, 1]
return cheap, skip, texture
def load_world(file):
with open(os.path.join(os.path.dirname(__file__), file)) as f:
root = json.load(f, object_pairs_hook=OrderedDict)
world = World()
e = lambda x: eval(str(x), {'__builtins__': None}, {'AU': root.get('au', 2000)})
if 'start' in root:
info = root['start']
x = e(info.get('x', 0))
y = e(info.get('y', 0))
z = e(info.get('z', 0))
pitch = e(info.get('pitch', 0))
yaw = e(info.get('yaw', 0))
roll = e(info.get('roll', 0))
world.start = (x, y, z)
world.direction = (pitch, yaw, roll)
def body(name, info, parent=None):
lighting = info.get('lighting', True)
x = e(info.get('x', 0))
y = e(info.get('y', 0))
z = e(info.get('z', 0))
pitch = e(info.get('pitch', 0))
yaw = e(info.get('yaw', 0))
roll = e(info.get('roll', 0))
delta = e(info.get('delta', 5))
radius = e(info.get('radius', None))
background = info.get('background', False)
if 'texture' in info:
cheap, skip, texture = get_best_texture(info['texture'], optional=info.get('optional', False))
if skip:
return
if cheap:
object_id = compile(colourball, radius, int(radius / 2), int(radius / 2), texture)
else:
object_id = compile(sphere, radius, int(radius / 2), int(radius / 2), texture, lighting=lighting)
elif 'model' in info:
scale = info.get('scale', 10)
object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),
info.get('sz', scale), (0, 0, 0))
else:
print 'Nothing to load for %s.' % name
if parent is None:
type = Planet
else:
x, y, z = parent.location
distance = e(info.get('distance', 100))
x -= distance
type = partial(Satellite, parent=parent, orbit_speed=info.get('orbit_speed', 1),
distance=distance, eccentricity=info.get('eccentricity', 0),
inclination=info.get('inclination', 0))
atmosphere_id = 0
cloudmap_id = 0
if 'atmosphere' in info:
atmosphere_data = info['atmosphere']
size = e(atmosphere_data.get('diffuse_size', None))
atm_texture = atmosphere_data.get('diffuse_texture', None)
cloud_texture = atmosphere_data.get('cloud_texture', None)
cheap, _, cloud_texture = get_best_texture(cloud_texture)
if not cheap:
cloudmap_id = compile(sphere, radius + 2, int(radius / 2), int(radius / 2), cloud_texture,
lighting=False)
cheap, _, atm_texture = get_best_texture(atm_texture)
if not cheap:
atmosphere_id = compile(disk, radius, radius + size, 30, atm_texture)
object = type(object_id, (x, y, z), (pitch, yaw, roll), delta=delta,
atmosphere=atmosphere_id, cloudmap=cloudmap_id, background=background)
world.tracker.append(object)
if 'ring' in info:
ring_data = info['ring']
texture = ring_data.get('texture', None)
distance = e(ring_data.get('distance', radius * 1.2))
size = e(ring_data.get('size', radius / 2))
pitch = e(ring_data.get('pitch', pitch))
yaw = e(ring_data.get('yaw', yaw))
roll = e(ring_data.get('roll', roll))
cheap, _, texture = get_best_texture(texture)
if not cheap:
world.tracker.append(
type(compile(disk, distance, distance + size, 30, texture), (x, y, z),
(pitch, yaw, roll)))
for satellite, info in info.get('satellites', {}).iteritems():
print "Loading %s, satellite of %s." % (satellite, name)
body(satellite, info, object)
for planet, info in root['planets'].iteritems():
print "Loading %s." % planet
body(planet, info)
return world
class World(object):
def __init__(self):
self.tracker = []
self.start = (0, 0, 0)
self.direction = (0, 0, 0)
self.x = None
self.y = None
self.z = None