mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 05:01:57 -04:00
Use VBOs for spheres.
This commit is contained in:
parent
338b7fb66c
commit
825e2ecf6a
|
@ -5,7 +5,7 @@ from pyglet.gl import *
|
|||
# noinspection PyUnresolvedReferences
|
||||
from six.moves import range
|
||||
|
||||
from punyverse.glgeom import compile, sphere, flare, disk, glMatrix, glRestore, belt
|
||||
from punyverse.glgeom import compile, flare, disk, glMatrix, glRestore, belt, Sphere
|
||||
from punyverse.orbit import KeplerOrbit
|
||||
from punyverse.texture import get_best_texture, load_clouds
|
||||
|
||||
|
@ -118,15 +118,20 @@ class Sky(Entity):
|
|||
super(Sky, self).__init__('Sky', (0, 0, 0), (pitch, yaw, roll))
|
||||
self.world = world
|
||||
|
||||
texture = get_best_texture(info['texture'])
|
||||
self.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)
|
||||
self.sphere = Sphere(info.get('radius', 1000000), division, division)
|
||||
|
||||
def draw(self, options):
|
||||
cam = self.world.cam
|
||||
with glMatrix((-cam.x, -cam.y, -cam.z), self.rotation), glRestore(GL_CURRENT_BIT):
|
||||
glCallList(self.sky_id)
|
||||
with glMatrix((-cam.x, -cam.y, -cam.z), self.rotation), glRestore(GL_TEXTURE_BIT | GL_ENABLE_BIT):
|
||||
glEnable(GL_CULL_FACE)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
glDisable(GL_LIGHTING)
|
||||
|
||||
glCullFace(GL_FRONT)
|
||||
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||
self.sphere.draw()
|
||||
|
||||
|
||||
class Body(Entity):
|
||||
|
@ -258,11 +263,11 @@ class SphericalBody(Body):
|
|||
division = info.get('division', max(min(int(self.radius / 8), 60), 10))
|
||||
self.light_source = info.get('light_source', False)
|
||||
|
||||
texture = get_best_texture(info['texture'])
|
||||
self.sphere_id = compile(sphere, self.radius, division, division, texture)
|
||||
self.texture = get_best_texture(info['texture'])
|
||||
self.sphere = Sphere(self.radius, division, division)
|
||||
|
||||
self.atmosphere_id = 0
|
||||
self.cloudmap_id = 0
|
||||
self.clouds = None
|
||||
self.corona_id = 0
|
||||
self.ring_id = 0
|
||||
|
||||
|
@ -273,8 +278,8 @@ class SphericalBody(Body):
|
|||
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)
|
||||
self.cloud_texture = get_best_texture(cloud_texture, loader=load_clouds)
|
||||
self.clouds = Sphere(self.radius + 2, division, division)
|
||||
|
||||
if corona_texture is not None:
|
||||
corona = get_best_texture(corona_texture, clamp=True)
|
||||
|
@ -301,11 +306,23 @@ class SphericalBody(Body):
|
|||
self.ring_id = compile(disk, distance, distance + size, 30,
|
||||
get_best_texture(info['ring'].get('texture', None), clamp=True))
|
||||
|
||||
def _draw_sphere(self):
|
||||
with glMatrix(self.location, self.rotation), glRestore(GL_CURRENT_BIT | GL_ENABLE_BIT):
|
||||
def _draw_sphere(self, fv4=GLfloat * 4):
|
||||
with glMatrix(self.location, self.rotation), glRestore(GL_LIGHTING_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||
glEnable(GL_CULL_FACE)
|
||||
glCullFace(GL_BACK)
|
||||
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
glBindTexture(GL_TEXTURE_2D, self.texture)
|
||||
|
||||
if self.light_source:
|
||||
glDisable(GL_LIGHTING)
|
||||
glCallList(self.sphere_id)
|
||||
else:
|
||||
glDisable(GL_BLEND)
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(1, 1, 1, 0))
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(1, 1, 1, 0))
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125)
|
||||
|
||||
self.sphere.draw()
|
||||
|
||||
def _draw_atmosphere(self, glMatrixBuffer=GLfloat * 16):
|
||||
with glMatrix(self.location), glRestore(GL_ENABLE_BIT | GL_CURRENT_BIT):
|
||||
|
@ -326,10 +343,16 @@ class SphericalBody(Body):
|
|||
glCallList(self.corona_id)
|
||||
|
||||
def _draw_clouds(self):
|
||||
with glMatrix(self.location, self.rotation), glRestore(GL_ENABLE_BIT | GL_CURRENT_BIT):
|
||||
with glMatrix(self.location, self.rotation), glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||
glEnable(GL_BLEND)
|
||||
glEnable(GL_ALPHA_TEST)
|
||||
glCallList(self.cloudmap_id)
|
||||
glEnable(GL_CULL_FACE)
|
||||
glDisable(GL_LIGHTING)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
|
||||
glCullFace(GL_BACK)
|
||||
glBindTexture(GL_TEXTURE_2D, self.cloud_texture)
|
||||
self.clouds.draw()
|
||||
|
||||
def _draw_rings(self):
|
||||
with glMatrix(self.location, self.ring_rotation), glRestore(GL_CURRENT_BIT):
|
||||
|
@ -341,7 +364,7 @@ class SphericalBody(Body):
|
|||
if options.atmosphere and (self.atmosphere_id or self.corona_id):
|
||||
self._draw_atmosphere()
|
||||
|
||||
if options.cloud and self.cloudmap_id:
|
||||
if options.cloud and self.clouds:
|
||||
self._draw_clouds()
|
||||
|
||||
if self.ring_id:
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from array import array
|
||||
from ctypes import c_int, c_float, byref, cast, POINTER, c_uint
|
||||
from math import *
|
||||
from random import random, gauss, choice
|
||||
|
||||
|
@ -7,7 +9,7 @@ from six.moves import range
|
|||
|
||||
TWOPI = pi * 2
|
||||
|
||||
__all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'sphere', 'colourball', 'belt',
|
||||
__all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'Sphere', 'belt',
|
||||
'flare', 'glSection', 'glMatrix', 'glRestore', 'progress_bar']
|
||||
|
||||
|
||||
|
@ -45,6 +47,17 @@ class glRestore(object):
|
|||
glPopAttrib()
|
||||
|
||||
|
||||
class glRestoreClient(object):
|
||||
def __init__(self, flags):
|
||||
self.flags = flags
|
||||
|
||||
def __enter__(self):
|
||||
glPushClientAttrib(self.flags)
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
glPopClientAttrib()
|
||||
|
||||
|
||||
class glMatrix(object):
|
||||
def __init__(self, location=None, rotation=None):
|
||||
self.location = location
|
||||
|
@ -169,49 +182,57 @@ def flare(rinner, router, res, prob, tex):
|
|||
last_y = y
|
||||
|
||||
|
||||
def sphere(r, lats, longs, tex, lighting=True, inside=False, fv4=GLfloat * 4):
|
||||
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||
sphere = gluNewQuadric()
|
||||
gluQuadricDrawStyle(sphere, GLU_FILL)
|
||||
gluQuadricTexture(sphere, True)
|
||||
if lighting:
|
||||
gluQuadricNormals(sphere, GLU_SMOOTH)
|
||||
|
||||
glEnable(GL_CULL_FACE)
|
||||
glCullFace(GL_FRONT if inside else GL_BACK)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
if lighting:
|
||||
glDisable(GL_BLEND)
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(1, 1, 1, 0))
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(1, 1, 1, 0))
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125)
|
||||
else:
|
||||
glDisable(GL_LIGHTING)
|
||||
glBindTexture(GL_TEXTURE_2D, tex)
|
||||
|
||||
gluSphere(sphere, r, lats, longs)
|
||||
|
||||
gluDeleteQuadric(sphere)
|
||||
def array_to_ctypes(arr):
|
||||
return cast(arr.buffer_info()[0], POINTER({
|
||||
'f': c_float,
|
||||
'i': c_int,
|
||||
'I': c_uint,
|
||||
}[arr.typecode]))
|
||||
|
||||
|
||||
def colourball(r, lats, longs, colour, fv4=GLfloat * 4):
|
||||
"""
|
||||
Sphere function from the OpenGL red book.
|
||||
"""
|
||||
with glRestore(GL_ENABLE_BIT):
|
||||
sphere = gluNewQuadric()
|
||||
class Sphere(object):
|
||||
def __init__(self, r, lats, longs):
|
||||
tau = pi * 2
|
||||
phi_div = tau / longs
|
||||
theta_div = pi / lats
|
||||
|
||||
glDisable(GL_BLEND)
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(*colour))
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, fv4(1, 1, 1, 1))
|
||||
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125)
|
||||
glEnable(GL_CULL_FACE)
|
||||
glCullFace(GL_BACK)
|
||||
self.vertex_count = (lats + 1) * (longs + 1) * 2
|
||||
buffer = self.vertex_count * 8 * [0]
|
||||
index = 0
|
||||
for i in range(longs + 1):
|
||||
phi1, phi2 = i * phi_div, (i + 1) * phi_div
|
||||
for j in range(lats + 1):
|
||||
theta = j * theta_div
|
||||
sine = sin(theta)
|
||||
dz = cos(theta)
|
||||
t = 1 - theta / pi
|
||||
dx1 = sine * cos(phi2)
|
||||
dy1 = sine * sin(phi2)
|
||||
dx2 = sine * cos(phi1)
|
||||
dy2 = sine * sin(phi1)
|
||||
buffer[index:index + 16] = [r * dx1, r * dy1, r * dz, dx1, dy1, dz, phi2 / tau, t,
|
||||
r * dx2, r * dy2, r * dz, dx2, dy2, dz, phi1 / tau, t]
|
||||
index += 16
|
||||
|
||||
gluSphere(sphere, r, lats, longs)
|
||||
vbo = c_uint()
|
||||
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)
|
||||
|
||||
glEnable(GL_BLEND)
|
||||
gluDeleteQuadric(sphere)
|
||||
def draw(self):
|
||||
with glRestoreClient(GL_CLIENT_VERTEX_ARRAY_BIT):
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
|
||||
glEnableClientState(GL_VERTEX_ARRAY)
|
||||
glEnableClientState(GL_NORMAL_ARRAY)
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY)
|
||||
glVertexPointer(3, GL_FLOAT, 32, 0)
|
||||
glNormalPointer(GL_FLOAT, 32, 3 * 4)
|
||||
glTexCoordPointer(3, GL_FLOAT, 32, 6 * 4)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, self.vertex_count)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
|
||||
|
||||
def belt(radius, cross, object, count):
|
||||
|
|
|
@ -306,7 +306,7 @@
|
|||
"division": 30,
|
||||
"pitch": 90,
|
||||
"yaw": 30,
|
||||
"roll": 180
|
||||
"roll": -90
|
||||
},
|
||||
"asteroids": ["asteroids/01.obj", "asteroids/02.obj", "asteroids/03.obj"],
|
||||
"start": {
|
||||
|
|
Loading…
Reference in a new issue