diff --git a/punyverse/assets/textures/earth_normal.jpg b/punyverse/assets/textures/earth_normal.jpg new file mode 100644 index 0000000..aeae547 Binary files /dev/null and b/punyverse/assets/textures/earth_normal.jpg differ diff --git a/punyverse/glgeom.py b/punyverse/glgeom.py index 921ee12..12c6f38 100644 --- a/punyverse/glgeom.py +++ b/punyverse/glgeom.py @@ -1,11 +1,11 @@ from math import * from pyglet.gl import * -from random import random, uniform, gauss, choice +from random import random, gauss, choice TWOPI = pi * 2 __all__ = ['compile', 'ortho', 'frustrum', 'crosshair', 'circle', 'disk', 'sphere', 'colourball', 'torus', 'belt', - 'flare'] + 'flare', 'normal_sphere'] def compile(pointer, *args, **kwargs): @@ -160,6 +160,66 @@ def colourball(r, lats, longs, colour, fv4=GLfloat * 4): gluDeleteQuadric(sphere) +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 + + 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) + + twopi_divide = TWOPI / divide + pi_divide = pi / divide + glBegin(GL_QUAD_STRIP) + for j in xrange(divide + 1): + phi1 = j * twopi_divide + phi2 = (j + 1) * twopi_divide + + for i in xrange(divide + 1): + theta = i * pi_divide + + s = phi2 / TWOPI + u = min(int(s * width), width - 1) + t = theta / pi + v = min(int(t * height), height - 1) + x, y, z = normal[u, v] + nx, ny, nz = sin(theta) * cos(phi2), sin(theta) * sin(phi2), cos(theta) + #delta = normal[u, v] / 255. + #glNormal3f(nx + delta, ny + delta, nz + delta) + #glNormal3f(nx + x / 64., ny + y / 64., nz + z / 64.) + glNormal3f(nx + x / 128. - 1, ny + y / 128. - 1, nz + z / 128. - 1) + #glNormal3f(nx, ny, nz) + glTexCoord2f(s, 1 - t) + glVertex3f(r * nx, r * ny, r * nz) + + s = phi1 / TWOPI # x + u = min(int(s * width), width - 1) + x, y, z = normal[u, v] + nx, ny, nz = sin(theta) * cos(phi1), sin(theta) * sin(phi1), cos(theta) + #delta = normal[u, v] / 255. + #glNormal3f(nx + delta, ny + delta, nz + delta) + #glNormal3f(nx + x / 64., ny + y / 64., nz + z / 64.) + glNormal3f(nx + x / 128. - 1, ny + y / 128. - 1, nz + z / 128. - 1) + #glNormal3f(nx, ny, nz) + glTexCoord2f(s, 1 - t) + glVertex3f(r * nx, r * ny, r * nz) + glEnd() + + glDisable(GL_TEXTURE_2D) + glEnable(GL_LIGHTING) + glEnable(GL_BLEND) + + def belt(radius, cross, object, count): for i in xrange(count): theta = TWOPI * random() diff --git a/punyverse/texture.py b/punyverse/texture.py index 83145f8..894e29e 100644 --- a/punyverse/texture.py +++ b/punyverse/texture.py @@ -42,7 +42,7 @@ try: except ImportError: from StringIO import StringIO -__all__ = ['load_texture', 'load_clouds', 'load_image'] +__all__ = ['load_texture', 'load_clouds', 'load_image', 'pil_load'] id = 0 cache = {} @@ -227,6 +227,11 @@ def load_texture(file): return id +def pil_load(file): + import Image + return Image.open(os.path.join(os.path.dirname(__file__), 'assets', 'textures', file)) + + def load_clouds(file): if os.path.isabs(file): path = file diff --git a/punyverse/world.json b/punyverse/world.json index 02c9eb2..9da6d1f 100644 --- a/punyverse/world.json +++ b/punyverse/world.json @@ -57,7 +57,8 @@ "roll": -90, "mass": 5.97219e+24, "rotation": 86400, - "division": 70, + "division": 250, + "normal": "earth_normal.jpg", "atmosphere": { "cloud_texture": ["cloudmap.jpg", "cloudmap_small.jpg"], "diffuse_texture": "atmosphere_earth.png", diff --git a/punyverse/world.py b/punyverse/world.py index fa5def2..ed73e0e 100644 --- a/punyverse/world.py +++ b/punyverse/world.py @@ -97,7 +97,10 @@ def load_world(file): if cheap: object_id = compile(colourball, radius, division, division, texture) else: - object_id = compile(sphere, radius, division, division, texture, lighting=lighting) + if '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) elif 'model' in info: scale = info.get('scale', 1) object_id = model_list(load_model(info['model']), info.get('sx', scale), info.get('sy', scale),