mirror of
https://github.com/quantum5/punyverse.git
synced 2025-04-24 13:11:57 -04:00
Added hardware normal mapping, usable with -n/--normal option.
This commit is contained in:
parent
83d8baeb8e
commit
2348e1d275
|
@ -16,6 +16,8 @@ def main():
|
|||
type=int)
|
||||
parser.add_argument('-v', '--no-vsync', help='Disables vsync',
|
||||
action='store_false', dest='vsync')
|
||||
parser.add_argument('-n', '--normal', help='Enables the use of normal maps',
|
||||
action='store_true')
|
||||
args = parser.parse_args()
|
||||
|
||||
import pyglet
|
||||
|
@ -38,10 +40,14 @@ def main():
|
|||
for key in config._attribute_names:
|
||||
print ' %-17s %s' % (key + ':', getattr(config, key))
|
||||
|
||||
world_options = {
|
||||
'normal': args.normal,
|
||||
}
|
||||
|
||||
from punyverse import game
|
||||
game.Applet(width=INITIAL_WIN_WIDTH, height=INITIAL_WIN_HEIGHT,
|
||||
caption=WIN_TITLE, resizable=True, vsync=args.vsync,
|
||||
config=config)
|
||||
config=config, world_options=world_options)
|
||||
pyglet.app.run()
|
||||
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ def entity_distance(x0, y0, z0):
|
|||
|
||||
class Applet(pyglet.window.Window):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.world_options = kwargs.pop('world_options', {})
|
||||
|
||||
super(Applet, self).__init__(*args, **kwargs)
|
||||
texture.init()
|
||||
|
||||
|
@ -79,7 +81,7 @@ class Applet(pyglet.window.Window):
|
|||
|
||||
start = clock()
|
||||
self.fps = 0
|
||||
self.world = World('world.json', callback)
|
||||
self.world = World('world.json', callback, self.world_options)
|
||||
phase = 'Initializing game...'
|
||||
print phase
|
||||
callback(phase, '', 0)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from math import *
|
||||
from pyglet.gl import *
|
||||
from random import random, gauss, choice
|
||||
from pyglet.gl.gl_info import have_extension
|
||||
|
||||
TWOPI = pi * 2
|
||||
|
||||
|
@ -181,23 +182,31 @@ def colourball(r, lats, longs, colour, fv4=GLfloat * 4):
|
|||
gluDeleteQuadric(sphere)
|
||||
|
||||
|
||||
try:
|
||||
from _glgeom import normal_sphere
|
||||
except ImportError:
|
||||
import warnings
|
||||
warnings.warn('Large sphere drawing in Python is slow')
|
||||
def normal_sphere(r, divide, tex, normal, lighting=True, fv4=GLfloat * 4):
|
||||
if (not have_extension('GL_ARB_multitexture') or not
|
||||
have_extension('GL_ARB_texture_env_combine') or not
|
||||
have_extension('GL_EXT_texture_env_dot3')):
|
||||
print 'No hardware normal mapping support. No bumping for you.'
|
||||
return sphere(r, divide, divide, tex, lighting)
|
||||
|
||||
def normal_sphere(r, divide, tex, normal, lighting=True, fv4=GLfloat * 4):
|
||||
from texture import pil_load
|
||||
print 'Loading normal map: %s...' % normal,
|
||||
normal_map = pil_load(normal)
|
||||
normal = normal_map.load()
|
||||
print
|
||||
width, height = normal_map.size
|
||||
gray_scale = len(normal[0, 0]) == 1
|
||||
from texture import load_texture
|
||||
normal = load_texture(normal)
|
||||
|
||||
with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT):
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB)
|
||||
glBindTexture(GL_TEXTURE_2D, normal)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB)
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGBA_ARB)
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB)
|
||||
glBindTexture(GL_TEXTURE_2D, tex)
|
||||
glEnable(GL_TEXTURE_2D)
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB)
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE)
|
||||
|
||||
if lighting:
|
||||
glDisable(GL_BLEND)
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, fv4(1, 1, 1, 0))
|
||||
|
@ -218,33 +227,18 @@ except ImportError:
|
|||
theta = i * pi_divide
|
||||
|
||||
s = phi2 / TWOPI
|
||||
u = min(int(s * width), width - 1)
|
||||
t = theta / pi
|
||||
v = min(int(t * height), height - 1)
|
||||
if gray_scale:
|
||||
x = y = z = normal[u, v]
|
||||
else:
|
||||
x, y, z = normal[u, v]
|
||||
dx, dy, dz = sin(theta) * cos(phi2), sin(theta) * sin(phi2), cos(theta)
|
||||
nx, ny, nz = x / 127.5 - 1, y / 127.5 - 1, z / 127.5 - 1 # Make into [-1, 1]
|
||||
nx, nz = cos(theta) * nx + sin(theta) * nz, -sin(theta) * nx + cos(theta) * nz
|
||||
nx, ny = cos(phi2) * nx - sin(phi2) * ny, sin(phi2) * nx + cos(phi2) * ny
|
||||
glNormal3f(nx, ny, nz)
|
||||
glTexCoord2f(s, 1 - t) # GL is bottom up
|
||||
glNormal3f(dx, dy, dz)
|
||||
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, s, 1 - t)
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, s, 1 - t)
|
||||
glVertex3f(r * dx, r * dy, r * dz)
|
||||
|
||||
s = phi1 / TWOPI # x
|
||||
u = min(int(s * width), width - 1)
|
||||
if gray_scale:
|
||||
x = y = z = normal[u, v]
|
||||
else:
|
||||
x, y, z = normal[u, v]
|
||||
dx, dy = sin(theta) * cos(phi1), sin(theta) * sin(phi1)
|
||||
nx, ny, nz = x / 127.5 - 1, y / 127.5 - 1, z / 127.5 - 1
|
||||
nx, nz = cos(theta) * nx + sin(theta) * nz, -sin(theta) * nx + cos(theta) * nz
|
||||
nx, ny = cos(phi1) * nx - sin(phi1) * ny, sin(phi1) * nx + cos(phi1) * ny
|
||||
glNormal3f(nx, ny, nz)
|
||||
glTexCoord2f(s, 1 - t)
|
||||
glNormal3f(dx, dy, dz)
|
||||
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, s, 1 - t)
|
||||
glMultiTexCoord2fARB(GL_TEXTURE1_ARB, s, 1 - t)
|
||||
glVertex3f(r * dx, r * dy, r * dz)
|
||||
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
"mass": 5.97219e+24,
|
||||
"rotation": 86400,
|
||||
"division": 90,
|
||||
"normal": "earth_normal.jpg",
|
||||
"atmosphere": {
|
||||
"cloud_texture": ["cloudmap.jpg", "cloudmap_small.jpg"],
|
||||
"diffuse_texture": "atmosphere_earth.png",
|
||||
|
|
|
@ -62,7 +62,7 @@ def load_world(file, callback=lambda message, completion: None):
|
|||
|
||||
|
||||
class World(object):
|
||||
def __init__(self, file, callback):
|
||||
def __init__(self, file, callback, options=None):
|
||||
self.tracker = []
|
||||
self.start = (0, 0, 0)
|
||||
self.direction = (0, 0, 0)
|
||||
|
@ -73,6 +73,7 @@ class World(object):
|
|||
self.tick = 0
|
||||
|
||||
self.callback = callback
|
||||
self.options = options or {}
|
||||
self._phase = 'Parsing configuration...'
|
||||
self._parse(file)
|
||||
del self.callback # So it can't be used after loading finishes
|
||||
|
@ -177,7 +178,7 @@ class World(object):
|
|||
if cheap:
|
||||
object_id = compile(colourball, radius, division, division, texture)
|
||||
else:
|
||||
if 'normal' in info:
|
||||
if self.options.get('normal', False) and 'normal' in info:
|
||||
object_id = compile(normal_sphere, radius, division, texture, info['normal'], lighting=lighting)
|
||||
else:
|
||||
object_id = compile(sphere, radius, division, division, texture, lighting=lighting)
|
||||
|
|
Loading…
Reference in a new issue