Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

glcube: implement rotation and window resizing #18

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 82 additions & 10 deletions glcube.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
import pygame.locals as pgl
import numpy
import cubehelper
import math

vertex_code = """
attribute vec3 position;
uniform mat4 proj;
uniform mat4 rot;
uniform vec3 offset;
void main()
{
gl_Position = proj * vec4(position + offset, 1.0);
gl_Position = proj * rot * vec4(position + offset, 1.0);
}
"""

Expand Down Expand Up @@ -72,18 +74,31 @@ def m0_projection(aspect, n, f):
class Cube(object):
def __init__(self, args):
self.color = True
width = 640
height = 480
self.width = 640
self.height = 480
size = args.size
self.size = size
self.pixels = numpy.zeros((size, size, size, 3), 'f')
pygame.init()
video_flags = pgl.OPENGL | pgl.DOUBLEBUF
pygame.display.set_mode((width, height), video_flags)
pygame.key.set_repeat(20, 20)
self.video_init()
self.shader_init()
self.geometry_init()
self.projection = m0_projection(width/float(height), 1.0, 100.0)
glEnable(GL_DEPTH_TEST)
self.keyboard_speed = math.pi / 32
self.mouse_speed = math.pi / 400
self.alpha = 0
self.beta = 0
self.dragging = False
self.update_rotation()

def video_init(self):
(w, h) = (self.width, self.height)
video_flags = pgl.OPENGL | pgl.DOUBLEBUF | pgl.RESIZABLE
pygame.display.set_mode((w, h), video_flags)
glViewport (0, 0, w, h)
self.projection = m0_projection(w/float(h), 1.0, 100.0)
pygame.display.set_caption(u"Cubulator\u2122".encode('utf8'))

def shader_init(self):
vertex = shaders.compileShader(vertex_code, GL_VERTEX_SHADER)
Expand All @@ -93,11 +108,30 @@ def shader_init(self):
self.attr_position = glGetAttribLocation(program, "position")
self.param_color = glGetUniformLocation(program, "color")
self.param_proj = glGetUniformLocation(program, "proj")
self.param_rot = glGetUniformLocation(program, "rot")
self.param_offset = glGetUniformLocation(program, "offset")

def geometry_init(self):
self.pixel_model = Model("pixel.off")

def update_rotation(self):
self.alpha = max(-math.pi/2, min(self.alpha, math.pi/2))
ca = math.cos(self.alpha)
sa = math.sin(self.alpha)
cb = math.cos(self.beta)
sb = math.sin(self.beta)
rot1 = numpy.array([[1.0, 0.0, 0.0, 0.0],
[0.0, ca, sa, 0.0],
[0.0, -sa, ca, 0.0],
[0.0, 0.0, 0.0, 1.0]
], 'f')
rot2 = numpy.array([[cb, sb, 0.0, 0.0],
[-sb, cb, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
], 'f')
self.rot = numpy.dot(rot1, rot2)

def set_pixel(self, xyz, rgb):
rgb = cubehelper.color_to_float(rgb)
self.pixels[tuple(xyz)] = rgb
Expand All @@ -121,27 +155,65 @@ def render(self):
spacing = 5.0
xoff = (self.size / 2 - 0.5) * -spacing
yoff = (self.size / 2 - 0.5) * -spacing
zoff = (self.size / 2 + 1) * spacing
eye = numpy.array([[1.0, 0.0, 0.0, xoff],
[0.0, 0.0, 1.0, yoff],
zoff = (self.size + 2) * spacing
eye = numpy.array([[1.0, 0.0, 0.0, 0],
[0.0, 0.0, 1.0, 0],
[0.0, 1.0, 0.0, zoff],
[0.0, 0.0, 0.0, 1.0]
], 'f')
eye = numpy.dot(self.projection, eye)
glUniformMatrix4fv(self.param_proj, 1, GL_TRUE, eye)
glUniformMatrix4fv(self.param_rot, 1, GL_TRUE, self.rot)
for x in range(0, self.size):
for y in range(0, self.size):
for z in range(0, self.size):
(r, g, b) = self.pixels[x, y, z]
glUniform3f(self.param_color, r, g, b)
glUniform3f(self.param_offset, x * spacing, y * spacing, z * spacing)
glUniform3f(self.param_offset,
(x - self.size/2 + 0.5) * spacing,
(y - self.size/2 + 0.5) * spacing,
(z - self.size/2 + 0.5) * spacing)
self.pixel_model.render()
pygame.display.flip()
for event in pygame.event.get():
if event.type == pgl.QUIT:
raise KeyboardInterrupt
if event.type == pgl.VIDEORESIZE:
(self.width, self.height) = event.dict['size']
self.video_init()
if event.type == pgl.KEYUP:
if event.key == pgl.K_ESCAPE or event.key == ord('q'):
raise KeyboardInterrupt
if event.key == pgl.K_SPACE:
raise StopIteration
if event.key == ord('r'):
self.alpha = self.beta = 0
self.update_rotation()
if event.type == pgl.MOUSEBUTTONDOWN:
self.dragging = True
pygame.mouse.set_visible(False)
pygame.event.set_grab(True)
pygame.mouse.get_rel()
if event.type == pgl.MOUSEBUTTONUP:
self.dragging = False
pygame.mouse.set_visible(True)
pygame.event.set_grab(False)
if event.type == pgl.MOUSEMOTION and self.dragging:
ms = self.mouse_speed
(dx, dy) = pygame.mouse.get_rel()
self.beta -= dx * ms
self.alpha -= dy * ms
self.update_rotation()
if event.type == pgl.KEYDOWN:
ks = self.keyboard_speed
if event.key == ord('w') or event.key == pgl.K_UP:
self.alpha += ks
elif event.key == ord('s') or event.key == pgl.K_DOWN:
self.alpha -= ks
elif event.key == ord('a') or event.key == pgl.K_LEFT:
self.beta += ks
elif event.key == ord('d') or event.key == pgl.K_RIGHT:
self.beta -= ks
else:
continue
self.update_rotation()