diff --git a/punyverse/_glgeom.pyx b/punyverse/_glgeom.pyx index 68510ff..87af17a 100644 --- a/punyverse/_glgeom.pyx +++ b/punyverse/_glgeom.pyx @@ -66,96 +66,31 @@ cpdef torus(float major_radius, float minor_radius, int n_major, int n_minor, tu glPopAttrib() -@cython.cdivision(True) -cpdef normal_sphere(double r, int divide, GLuint tex, normal, bint lighting=True): - from texture import pil_load - print 'Loading normal map: %s...' % normal, - normal_map = pil_load(normal) - normal = normal_map.load() - print 'Loaded' - - cdef int width, height - width, height = normal_map.size - cdef bint gray_scale = len(normal[0, 0]) == 1 - - glEnable(GL_TEXTURE_2D) - if lighting: - glDisable(GL_BLEND) - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, [1, 1, 1, 0]) - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, [1, 1, 1, 0]) - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 125) - else: - glDisable(GL_LIGHTING) - glBindTexture(GL_TEXTURE_2D, tex) - - cdef double twopi_divide, pi_divide - cdef int i, j - cdef double phi1, phi2 - cdef double theta, s, t - cdef int u, v - cdef double x, y, z - cdef double dx, dy, xz - cdef double nx, ny, nz - twopi_divide = TWOPI / divide - pi_divide = PI / divide - glBegin(GL_TRIANGLE_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((s * width), width - 1) - t = theta / PI - v = min((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 - glVertex3f(r * dx, r * dy, r * dz) - - s = phi1 / TWOPI # x - u = min((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) - glVertex3f(r * dx, r * dy, r * dz) - glEnd() - - glDisable(GL_TEXTURE_2D) - glEnable(GL_LIGHTING) - glEnable(GL_BLEND) - - -cpdef bytes bgr_to_rgb(bytes buffer, int width, int height, bint alpha=0, bint bottom_up=1): +cpdef bytes bgr_to_rgb(bytes buffer, int width, int height, bint alpha=0): cdef int length = len(buffer) cdef int depth = length / (width * height) cdef int depth2 = depth - alpha cdef object final = PyBytes_FromStringAndSize(NULL, length) cdef char *result = PyBytes_AsString(final) cdef const char *source = PyBytes_AsString(buffer) - cdef int x, y, ioffset, ooffset, i, row = width * depth + cdef int x, y, offset, i, row = width * depth for y in xrange(height): for x in xrange(width): - ioffset = y * width * depth + x * depth - ooffset = (height - y - 1 if bottom_up else y) * row + x * depth + offset = y * row + x * depth for i in xrange(depth2): - result[ooffset+i] = source[ioffset+depth2-i-1] + result[offset+i] = source[offset+depth2-i-1] if alpha: - result[ooffset+depth2] = source[ioffset+depth2] + result[offset+depth2] = source[offset+depth2] + return final + + +cpdef bytes flip_vertical(bytes buffer, int width, int height): + cdef int length = len(buffer) + cdef object final = PyBytes_FromStringAndSize(NULL, length) + cdef char *result = PyBytes_AsString(final) + cdef const char *source = PyBytes_AsString(buffer) + cdef int y1, y2, row = length / height + for y1 in xrange(height): + y2 = height - y1 - 1 + memcpy(result + y1 * row, source + y2 * row, row) return final diff --git a/punyverse/assets/models/satellites/hst.obj b/punyverse/assets/models/satellites/hst.obj index 6475558..77e4bb4 100644 --- a/punyverse/assets/models/satellites/hst.obj +++ b/punyverse/assets/models/satellites/hst.obj @@ -1,6 +1,6 @@ # Blender v2.68 (sub 0) OBJ File: '' # www.blender.org -mtllib HST.mtl +mtllib hst.mtl v 0.325496 -2.594603 -0.788680 v 0.472583 -2.594603 -0.710061 v 0.601506 -2.594603 -0.604257 diff --git a/punyverse/glgeom.py b/punyverse/glgeom.py index b028f74..aa7beeb 100644 --- a/punyverse/glgeom.py +++ b/punyverse/glgeom.py @@ -144,10 +144,7 @@ def flare(rinner, router, res, prob, tex): last_y = y -def sphere(r, lats, longs, tex, lighting=True, fv4=GLfloat * 4, inside=False): - """ - Sphere function from the OpenGL red book. - """ +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) @@ -192,19 +189,19 @@ def colourball(r, lats, longs, colour, fv4=GLfloat * 4): gluDeleteQuadric(sphere) -def normal_sphere(r, divide, tex, normal, lighting=True, fv4=GLfloat * 4): +def normal_sphere(r, divide, tex, normal, lighting=True, inside=False, 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) + return sphere(r, divide, divide, tex, lighting, inside) - from texture import load_texture + from .texture import load_texture normal = load_texture(normal) with glRestore(GL_ENABLE_BIT | GL_TEXTURE_BIT): glEnable(GL_CULL_FACE) - glCullFace(GL_BACK) + glCullFace(GL_FRONT if inside else GL_BACK) glActiveTextureARB(GL_TEXTURE0_ARB) glBindTexture(GL_TEXTURE_2D, normal) diff --git a/punyverse/texture.py b/punyverse/texture.py index 1c3539c..cf2e706 100644 --- a/punyverse/texture.py +++ b/punyverse/texture.py @@ -2,7 +2,7 @@ from __future__ import print_function from pyglet import image from pyglet.gl import * -from ctypes import c_int, byref, c_ulong +from ctypes import c_int, byref, c_uint import os.path import struct import itertools @@ -12,11 +12,11 @@ import six from six.moves import zip try: - from punyverse._glgeom import bgr_to_rgb + from punyverse._glgeom import bgr_to_rgb, flip_vertical except ImportError: import warnings warnings.warn('Compile _glgeom.c, or double the start up time.') - + # Use magick when _glgeom is not compiled (is actually slower) try: from pgmagick import Blob, Image @@ -27,7 +27,7 @@ except ImportError: from six.moves import range - def bgr_to_rgb(source, width, height, alpha=False, bottom_up=True): + def bgr_to_rgb(source, width, height, alpha=False): length = len(source) depth = length // (width * height) depth2 = depth - alpha @@ -35,13 +35,21 @@ except ImportError: row = width * depth for y in range(height): for x in range(width): - ioffset = y * width * depth + x * depth - ooffset = (height - y - 1 if bottom_up else y) * row + x * depth + offset = y * row + x * depth for i in range(depth2): - result[ooffset+i] = source[ioffset+depth2-i-1] + result[offset+i] = source[offset+depth2-i-1] if alpha: - result[ooffset+depth2] = source[ioffset+depth2] - return str(result) + result[offset+depth2] = source[offset+depth2] + return six.binary_type(result) + + def flip_vertical(source, width, height): + length = len(source) + row = length // height + result = bytearray(length) + for y1 in range(height): + y2 = height - y1 - 1 + result[y1*row:y1*row+row] = source[y2*row:y2*row+row] + return six.binary_type(result) else: magick = False @@ -67,8 +75,8 @@ def init(): if badcard: import warnings warnings.warn('Please update your graphics drivers if possible') - # Currently, BGRA images are flipped. - # bgra = gl_info.have_extension('GL_EXT_bgra') + + #bgra = gl_info.have_extension('GL_EXT_bgra') if power_of_two is None: power_of_two = gl_info.have_version(2) or gl_info.have_extension('GL_ARB_texture_non_power_of_two') @@ -196,7 +204,7 @@ def load_image(file, path): texture = raw.data else: texture = raw.get_data('RGBA', width * 4) - return path, width, height, len(raw.format), mode, texture + return path, width, height, len(raw.format), mode, flip_vertical(texture, width, height) def load_texture(file): @@ -211,7 +219,7 @@ def load_texture(file): path, width, height, depth, mode, texture = load_image(file, path) - buffer = c_ulong() + buffer = c_uint() glGenTextures(1, byref(buffer)) id = buffer.value @@ -232,7 +240,7 @@ def load_texture(file): def pil_load(file): - import Image + from PIL import Image return Image.open(os.path.join(os.path.dirname(__file__), 'assets', 'textures', file)) @@ -248,7 +256,7 @@ def load_clouds(file): path, width, height, depth, mode, texture = load_image(file, path) - buffer = c_ulong() + buffer = c_uint() glGenTextures(1, byref(buffer)) id = buffer.value diff --git a/setup.py b/setup.py index 5bf7c0d..24e4e52 100644 --- a/setup.py +++ b/setup.py @@ -16,12 +16,15 @@ except ImportError: sys.exit(1) cythonize = lambda x: x - if has_pyx: pyx_path = lambda x: x else: pyx_path = lambda x: x.replace('.pyx', '.c') +if os.name == 'nt': + gl_libs = ['opengl32'] +else: + gl_libs = ['GL'] with open(os.path.join(os.path.dirname(__file__), 'README.md')) as f: long_description = f.read() @@ -46,8 +49,8 @@ setup( ], }, ext_modules=cythonize([ - Extension('punyverse._glgeom', sources=[pyx_path('punyverse/_glgeom.pyx')], libraries=['opengl32']), - Extension('punyverse._model', sources=[pyx_path('punyverse/_model.pyx')], libraries=['opengl32']), + Extension('punyverse._glgeom', sources=[pyx_path('punyverse/_glgeom.pyx')], libraries=gl_libs), + Extension('punyverse._model', sources=[pyx_path('punyverse/_model.pyx')], libraries=gl_libs), ]), entry_points={