mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Turned atmosphere and rings into VBOs.
This commit is contained in:
parent
825e2ecf6a
commit
dde4e1541d
Binary file not shown.
Before Width: | Height: | Size: 640 B |
|
@ -5,7 +5,7 @@ from pyglet.gl import *
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
|
|
||||||
from punyverse.glgeom import compile, flare, disk, glMatrix, glRestore, belt, Sphere
|
from punyverse.glgeom import compile, glMatrix, glRestore, belt, Sphere, Disk
|
||||||
from punyverse.orbit import KeplerOrbit
|
from punyverse.orbit import KeplerOrbit
|
||||||
from punyverse.texture import get_best_texture, load_clouds
|
from punyverse.texture import get_best_texture, load_clouds
|
||||||
|
|
||||||
|
@ -266,32 +266,22 @@ class SphericalBody(Body):
|
||||||
self.texture = get_best_texture(info['texture'])
|
self.texture = get_best_texture(info['texture'])
|
||||||
self.sphere = Sphere(self.radius, division, division)
|
self.sphere = Sphere(self.radius, division, division)
|
||||||
|
|
||||||
self.atmosphere_id = 0
|
self.atmosphere = None
|
||||||
self.clouds = None
|
self.clouds = None
|
||||||
self.corona_id = 0
|
self.ring = 0
|
||||||
self.ring_id = 0
|
|
||||||
|
|
||||||
if 'atmosphere' in info:
|
if 'atmosphere' in info:
|
||||||
atmosphere_data = info['atmosphere']
|
atmosphere_data = info['atmosphere']
|
||||||
atm_size = world.evaluate(atmosphere_data.get('diffuse_size', None))
|
atm_size = world.evaluate(atmosphere_data.get('diffuse_size', None))
|
||||||
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
atm_texture = atmosphere_data.get('diffuse_texture', None)
|
||||||
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
cloud_texture = atmosphere_data.get('cloud_texture', None)
|
||||||
corona_texture = atmosphere_data.get('corona_texture', None)
|
|
||||||
if cloud_texture is not None:
|
if cloud_texture is not None:
|
||||||
self.cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
self.cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
||||||
self.clouds = Sphere(self.radius + 2, division, division)
|
self.clouds = Sphere(self.radius + 2, division, division)
|
||||||
|
|
||||||
if corona_texture is not None:
|
|
||||||
corona = get_best_texture(corona_texture, clamp=True)
|
|
||||||
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:
|
if atm_texture is not None:
|
||||||
atm_texture = get_best_texture(atm_texture, clamp=True)
|
self.atm_texture = get_best_texture(atm_texture, clamp=True)
|
||||||
self.atmosphere_id = compile(disk, self.radius, self.radius + atm_size, 30, atm_texture)
|
self.atmosphere = Disk(self.radius, self.radius + atm_size, 30)
|
||||||
|
|
||||||
if 'ring' in info:
|
if 'ring' in info:
|
||||||
distance = world.evaluate(info['ring'].get('distance', self.radius * 1.2))
|
distance = world.evaluate(info['ring'].get('distance', self.radius * 1.2))
|
||||||
|
@ -303,8 +293,8 @@ class SphericalBody(Body):
|
||||||
roll = world.evaluate(info['ring'].get('roll', roll))
|
roll = world.evaluate(info['ring'].get('roll', roll))
|
||||||
self.ring_rotation = pitch, yaw, roll
|
self.ring_rotation = pitch, yaw, roll
|
||||||
|
|
||||||
self.ring_id = compile(disk, distance, distance + size, 30,
|
self.ring_texture = get_best_texture(info['ring'].get('texture', None), clamp=True)
|
||||||
get_best_texture(info['ring'].get('texture', None), clamp=True))
|
self.ring = Disk(distance, distance + size, 30)
|
||||||
|
|
||||||
def _draw_sphere(self, fv4=GLfloat * 4):
|
def _draw_sphere(self, fv4=GLfloat * 4):
|
||||||
with glMatrix(self.location, self.rotation), glRestore(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
with glMatrix(self.location, self.rotation), glRestore(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||||
|
@ -325,7 +315,7 @@ class SphericalBody(Body):
|
||||||
self.sphere.draw()
|
self.sphere.draw()
|
||||||
|
|
||||||
def _draw_atmosphere(self, glMatrixBuffer=GLfloat * 16):
|
def _draw_atmosphere(self, glMatrixBuffer=GLfloat * 16):
|
||||||
with glMatrix(self.location), glRestore(GL_ENABLE_BIT | GL_CURRENT_BIT):
|
with glMatrix(self.location), glRestore(GL_ENABLE_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT):
|
||||||
matrix = glMatrixBuffer()
|
matrix = glMatrixBuffer()
|
||||||
glGetFloatv(GL_MODELVIEW_MATRIX, matrix)
|
glGetFloatv(GL_MODELVIEW_MATRIX, matrix)
|
||||||
matrix[0: 3] = [1, 0, 0]
|
matrix[0: 3] = [1, 0, 0]
|
||||||
|
@ -333,14 +323,13 @@ class SphericalBody(Body):
|
||||||
matrix[8:11] = [0, 0, 1]
|
matrix[8:11] = [0, 0, 1]
|
||||||
glLoadMatrixf(matrix)
|
glLoadMatrixf(matrix)
|
||||||
|
|
||||||
if self.atmosphere_id:
|
glDisable(GL_LIGHTING)
|
||||||
glCallList(self.atmosphere_id)
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
|
||||||
if self.corona_id:
|
|
||||||
x, y, z = self.world.cam.direction()
|
|
||||||
glTranslatef(-x, -y, -z)
|
|
||||||
glEnable(GL_BLEND)
|
glEnable(GL_BLEND)
|
||||||
glCallList(self.corona_id)
|
glDisable(GL_CULL_FACE)
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.atm_texture)
|
||||||
|
self.atmosphere.draw()
|
||||||
|
|
||||||
def _draw_clouds(self):
|
def _draw_clouds(self):
|
||||||
with glMatrix(self.location, self.rotation), glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
with glMatrix(self.location, self.rotation), glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||||
|
@ -355,19 +344,25 @@ class SphericalBody(Body):
|
||||||
self.clouds.draw()
|
self.clouds.draw()
|
||||||
|
|
||||||
def _draw_rings(self):
|
def _draw_rings(self):
|
||||||
with glMatrix(self.location, self.ring_rotation), glRestore(GL_CURRENT_BIT):
|
with glMatrix(self.location, self.ring_rotation), glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||||
glCallList(self.ring_id)
|
glDisable(GL_LIGHTING)
|
||||||
|
glEnable(GL_TEXTURE_2D)
|
||||||
|
glEnable(GL_BLEND)
|
||||||
|
glDisable(GL_CULL_FACE)
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, self.ring_texture)
|
||||||
|
self.ring.draw()
|
||||||
|
|
||||||
def _draw(self, options):
|
def _draw(self, options):
|
||||||
self._draw_sphere()
|
self._draw_sphere()
|
||||||
|
|
||||||
if options.atmosphere and (self.atmosphere_id or self.corona_id):
|
if options.atmosphere and self.atmosphere:
|
||||||
self._draw_atmosphere()
|
self._draw_atmosphere()
|
||||||
|
|
||||||
if options.cloud and self.clouds:
|
if options.cloud and self.clouds:
|
||||||
self._draw_clouds()
|
self._draw_clouds()
|
||||||
|
|
||||||
if self.ring_id:
|
if self.ring:
|
||||||
self._draw_rings()
|
self._draw_rings()
|
||||||
|
|
||||||
def _collides(self, x, y, z):
|
def _collides(self, x, y, z):
|
||||||
|
|
|
@ -9,8 +9,8 @@ from six.moves import range
|
||||||
|
|
||||||
TWOPI = pi * 2
|
TWOPI = pi * 2
|
||||||
|
|
||||||
__all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'Sphere', 'belt',
|
__all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'Sphere', 'belt',
|
||||||
'flare', 'glSection', 'glMatrix', 'glRestore', 'progress_bar']
|
'glSection', 'glMatrix', 'glRestore', 'progress_bar']
|
||||||
|
|
||||||
|
|
||||||
class glContext(object):
|
class glContext(object):
|
||||||
|
@ -79,6 +79,24 @@ class glMatrix(object):
|
||||||
glPopMatrix()
|
glPopMatrix()
|
||||||
|
|
||||||
|
|
||||||
|
def array_to_ctypes(arr):
|
||||||
|
return cast(arr.buffer_info()[0], POINTER({
|
||||||
|
'f': c_float,
|
||||||
|
'i': c_int,
|
||||||
|
'I': c_uint,
|
||||||
|
}[arr.typecode]))
|
||||||
|
|
||||||
|
|
||||||
|
def array_to_gl_buffer(buffer, array_type='f'):
|
||||||
|
vbo = c_uint()
|
||||||
|
glGenBuffers(1, byref(vbo))
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.value)
|
||||||
|
buffer = array(array_type, buffer)
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, buffer.itemsize * len(buffer), array_to_ctypes(buffer), GL_STATIC_DRAW)
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
|
return vbo.value
|
||||||
|
|
||||||
|
|
||||||
def compile(pointer, *args, **kwargs):
|
def compile(pointer, *args, **kwargs):
|
||||||
display = glGenLists(1)
|
display = glGenLists(1)
|
||||||
glNewList(display, GL_COMPILE)
|
glNewList(display, GL_COMPILE)
|
||||||
|
@ -125,69 +143,29 @@ def circle(r, seg, coords):
|
||||||
glVertex2f(cx + cos(theta) * r, cy + sin(theta) * r)
|
glVertex2f(cx + cos(theta) * r, cy + sin(theta) * r)
|
||||||
|
|
||||||
|
|
||||||
def disk(rinner, router, segs, tex):
|
class Disk(object):
|
||||||
with glRestore(GL_ENABLE_BIT):
|
def __init__(self, rinner, router, segs):
|
||||||
glEnable(GL_TEXTURE_2D)
|
|
||||||
glEnable(GL_BLEND)
|
|
||||||
glDisable(GL_LIGHTING)
|
|
||||||
glDisable(GL_CULL_FACE)
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex)
|
|
||||||
res = segs * 5
|
res = segs * 5
|
||||||
|
delta = 2 * pi / res
|
||||||
|
self.vertex_count = (res + 1) * 2
|
||||||
|
# Need padding to make the last vertex render correctly... why?
|
||||||
|
buffer = self.vertex_count * 3 * [0]
|
||||||
|
for i in range(res):
|
||||||
|
theta = delta * i
|
||||||
|
x, y = cos(theta), sin(theta)
|
||||||
|
buffer[6*i:6*i+6] = [rinner * x, rinner * y, 0, router * x, router * y, 1]
|
||||||
|
buffer[6*res:6*res+6] = buffer[:6]
|
||||||
|
self.vbo = array_to_gl_buffer(buffer)
|
||||||
|
|
||||||
with glSection(GL_TRIANGLE_STRIP):
|
def draw(self):
|
||||||
factor = TWOPI / res
|
with glRestoreClient(GL_CLIENT_VERTEX_ARRAY_BIT):
|
||||||
theta = 0
|
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
|
||||||
for n in range(res + 1):
|
glEnableClientState(GL_VERTEX_ARRAY)
|
||||||
theta += factor
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||||
x = cos(theta)
|
glVertexPointer(3, GL_FLOAT, 12, 0)
|
||||||
y = sin(theta)
|
glTexCoordPointer(1, GL_FLOAT, 12, 8)
|
||||||
glTexCoord2f(0, 0)
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.vertex_count)
|
||||||
glVertex2f(rinner * x, rinner * y)
|
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||||
glTexCoord2f(1, 0)
|
|
||||||
glVertex2f(router * x, router * y)
|
|
||||||
|
|
||||||
|
|
||||||
def flare(rinner, router, res, prob, tex):
|
|
||||||
with glRestore(GL_ENABLE_BIT):
|
|
||||||
glEnable(GL_TEXTURE_2D)
|
|
||||||
glDisable(GL_CULL_FACE)
|
|
||||||
glDisable(GL_LIGHTING)
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex)
|
|
||||||
last_x = 1
|
|
||||||
last_y = 0
|
|
||||||
last_theta = 0
|
|
||||||
factor = TWOPI / res
|
|
||||||
rdelta = (router - rinner)
|
|
||||||
with glSection(GL_QUADS):
|
|
||||||
for i in range(res + 1):
|
|
||||||
theta = last_theta + factor
|
|
||||||
x = cos(theta)
|
|
||||||
y = sin(theta)
|
|
||||||
if random() > prob:
|
|
||||||
distance = rinner + rdelta * random()
|
|
||||||
avg_theta = (last_theta + theta) / 2
|
|
||||||
x0, y0 = rinner * last_x, rinner * last_y
|
|
||||||
x1, y1 = rinner * x, rinner * y
|
|
||||||
x2, y2 = distance * cos(avg_theta), distance * sin(avg_theta)
|
|
||||||
glTexCoord2f(0, 0)
|
|
||||||
glVertex2f(x0, y0)
|
|
||||||
glTexCoord2f(0, 1)
|
|
||||||
glVertex2f(x1, y1)
|
|
||||||
glTexCoord2f(1, 0)
|
|
||||||
glVertex2f(x2, y2)
|
|
||||||
glTexCoord2f(1, 1)
|
|
||||||
glVertex2f(x2, y2)
|
|
||||||
last_theta = theta
|
|
||||||
last_x = x
|
|
||||||
last_y = y
|
|
||||||
|
|
||||||
|
|
||||||
def array_to_ctypes(arr):
|
|
||||||
return cast(arr.buffer_info()[0], POINTER({
|
|
||||||
'f': c_float,
|
|
||||||
'i': c_int,
|
|
||||||
'I': c_uint,
|
|
||||||
}[arr.typecode]))
|
|
||||||
|
|
||||||
|
|
||||||
class Sphere(object):
|
class Sphere(object):
|
||||||
|
@ -214,13 +192,7 @@ class Sphere(object):
|
||||||
r * dx2, r * dy2, r * dz, dx2, dy2, dz, phi1 / tau, t]
|
r * dx2, r * dy2, r * dz, dx2, dy2, dz, phi1 / tau, t]
|
||||||
index += 16
|
index += 16
|
||||||
|
|
||||||
vbo = c_uint()
|
self.vbo = array_to_gl_buffer(buffer)
|
||||||
glGenBuffers(1, byref(vbo))
|
|
||||||
self.vbo = vbo.value
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
|
|
||||||
buffer = array('f', buffer)
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, buffer.itemsize * len(buffer), array_to_ctypes(buffer), GL_STATIC_DRAW)
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
with glRestoreClient(GL_CLIENT_VERTEX_ARRAY_BIT):
|
with glRestoreClient(GL_CLIENT_VERTEX_ARRAY_BIT):
|
||||||
|
|
|
@ -257,5 +257,5 @@ def get_best_texture(info, loader=load_texture, **kwargs):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return loader(info)
|
return loader(info, **kwargs)
|
||||||
raise ValueError('No texture found')
|
raise ValueError('No texture found')
|
||||||
|
|
|
@ -23,10 +23,6 @@
|
||||||
"rotation": 2164320,
|
"rotation": 2164320,
|
||||||
"light_source": true,
|
"light_source": true,
|
||||||
"atmosphere": {
|
"atmosphere": {
|
||||||
"corona_texture": "sun_corona.png",
|
|
||||||
"corona_size": 1500,
|
|
||||||
"corona_division": 100,
|
|
||||||
"corona_prob": 0.5,
|
|
||||||
"diffuse_texture": "sun_diffuse.png",
|
"diffuse_texture": "sun_diffuse.png",
|
||||||
"diffuse_size": 300
|
"diffuse_size": 300
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue