Last active
August 29, 2015 14:21
-
-
Save pudelkoM/2467647161437849b625 to your computer and use it in GitHub Desktop.
conway 3d edition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
from PyQt5 import QtGui, QtWidgets | |
import time | |
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QEvent | |
import itertools | |
class OpenGLWindow(QtGui.QWindow): | |
def __init__(self, parent=None): | |
super(OpenGLWindow, self).__init__(parent) | |
#quitAction = QAction("Exit", self, shortcut="Ctrl+Q", triggered=QApplication.instance().quit) | |
#self.addAction(quitAction) | |
#self.setAttribute(QtCore.Qt.WA_TranslucentBackground) | |
self.m_update_pending = False | |
self.m_animating = False | |
self.m_context = None | |
self.m_gl = None | |
self.setSurfaceType(QtGui.QWindow.OpenGLSurface) | |
def initialize(self): | |
pass | |
def setAnimating(self, animating): | |
self.m_animating = animating | |
if animating: | |
self.renderLater() | |
def renderLater(self): | |
if not self.m_update_pending: | |
self.m_update_pending = True | |
QtGui.QGuiApplication.postEvent(self, QEvent(QEvent.UpdateRequest)) | |
def renderNow(self): | |
if not self.isExposed(): | |
return | |
self.m_update_pending = False | |
needsInitialize = False | |
if self.m_context is None: | |
self.m_context = QtGui.QOpenGLContext(self) | |
self.m_context.setFormat(self.requestedFormat()) | |
self.m_context.create() | |
needsInitialize = True | |
self.m_context.makeCurrent(self) | |
if needsInitialize: | |
version = QtGui.QOpenGLVersionProfile() | |
version.setVersion(2, 0) | |
self.m_gl = self.m_context.versionFunctions(version) | |
self.m_gl.initializeOpenGLFunctions() | |
self.initialize() | |
self.render(self.m_gl) | |
self.m_context.swapBuffers(self) | |
if self.m_animating: | |
self.renderLater() | |
def event(self, event): | |
if event.type() == QEvent.UpdateRequest: | |
self.renderNow() | |
return True | |
return super(OpenGLWindow, self).event(event) | |
def exposeEvent(self, event): | |
self.renderNow() | |
def resizeEvent(self, event): | |
self.renderNow() | |
def t_add3(a, b): | |
return round(a[0] + b[0], 2), round(a[1] + b[1], 2), round(a[2] + b[2], 2) | |
def t_abs3(a): | |
return abs(a[0]), abs(a[1]), abs(a[2]) | |
def calc_neighbors(cells): | |
t = time.clock() | |
for cell in cells.items(): | |
pos = cell[0] | |
count = -1 # because itertools.product includes offset (0,0,0) aka itself which is always there | |
for offset in itertools.product([0.2, 0.0, -0.2], repeat=3): | |
newpos = t_add3(pos, offset) | |
if newpos in cells: # neighbour is present | |
count += 1 | |
cells[pos] = count | |
print("done") | |
def faststep3D(cells): | |
t = time.clock() | |
commitlist = [] | |
# For every position in the matrix | |
for pos in itertools.product([x/5 for x in range(-5, 5)], repeat=3): | |
count = 0 | |
for offset in itertools.product([0.2, 0.0, -0.2], repeat=3): | |
if offset == (0, 0, 0): continue | |
newpos = t_add3(pos, offset) | |
if newpos in cells: | |
count += 1 | |
commitlist.append((pos, count)) | |
for update in commitlist: | |
if update[1] < 5 or update[1] > 8: | |
cells.pop(update[0], 0) | |
elif update[1] == 6 and update[0] not in cells: | |
cells[update[0]] = update[1] | |
class Worker(QThread): | |
trigger = pyqtSignal() | |
def __init__(self, cells, parent=None): | |
super(Worker, self).__init__(parent) | |
self.cells = cells | |
def run(self): | |
while True: | |
faststep3D(self.cells) | |
time.sleep(1) | |
class Conway3DWindow(OpenGLWindow): | |
def __init__(self, parent=None): | |
super(Conway3DWindow, self).__init__(parent) | |
self.current_blend = 0.0 | |
self.step_blend = 0.01 | |
self.vertices = {} | |
self.init_vertices() | |
self.worker = Worker(self.vertices) | |
self.worker.start() | |
self.trans_matrix = [0, 0, -3.0] | |
self.rot_matrix_y = [0, 0, 1, 0] | |
self.rot_matrix_x = [0, 1, 0, 0] | |
def keyPressEvent(self, event): | |
if event.key() == Qt.Key_W: | |
self.trans_matrix[2] += 0.1 | |
if event.key() == Qt.Key_S: | |
self.trans_matrix[2] -= 0.1 | |
if event.key() == Qt.Key_A: | |
self.trans_matrix[0] += 0.1 | |
if event.key() == Qt.Key_D: | |
self.trans_matrix[0] -= 0.1 | |
def mouseMoveEvent(self, event): | |
self.rot_matrix_y[0] = (event.pos().x() / self.width() + 0.5) * 180 | |
self.rot_matrix_x[0] = -(event.pos().y() / self.height() + 0.5) * 180 | |
def initialize(self): | |
self.m_gl.glEnable(self.m_gl.GL_CULL_FACE) | |
self.m_gl.glEnable(self.m_gl.GL_DEPTH_TEST) | |
self.m_gl.glViewport(0, 0, self.width(), self.height()) | |
self.m_gl.glMatrixMode(self.m_gl.GL_PROJECTION) | |
self.m_gl.glLoadIdentity() | |
self.m_gl.glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 5.0) | |
def set_uniforms(self): | |
self.program.bind() | |
light = QtGui.QVector3D(0.0, 0.0, 5.0) | |
self.program.setUniformValue("LightPosition", light) | |
surfaceCol = QtGui.QVector3D(0.2, 0.4, 1.0) | |
self.program.setUniformValue("SurfaceColor", surfaceCol) | |
self.program.setUniformValue("Blend", self.current_blend) | |
self.program.setUniformValue("Radius", 0.8) | |
# self.matrixUniform = self.program.uniformLocation('matrix') | |
# matrix = QtGui.QMatrix4x4() | |
# matrix.perspective(60, 4.0/3.0, 0.1, 100.0) | |
# matrix.translate(0, 0, -2) | |
# self.program.setUniformValue(self.matrixUniform, matrix) | |
self.program.release() | |
def init_vertices(self): | |
self.vertices = {} | |
for i in range(200): | |
pos = (random.randrange(-5, 5) / 5, | |
random.randrange(-5, 5) / 5, | |
random.randrange(-5, 5) / 5) | |
self.vertices[pos] = 0 | |
calc_neighbors(self.vertices) | |
def render(self, gl): | |
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) | |
gl.glMatrixMode(gl.GL_MODELVIEW) | |
# gl.glLightfv(gl.GL_LIGHT0, gl.GL_AMBIENT, (1, 1, 1, 1)) | |
# gl.glLightfv(gl.GL_LIGHT0, gl.GL_POSITION, (1, 1, 1, 1)) | |
# gl.glMaterialfv(gl.GL_FRONT, gl.GL_SPECULAR, (1, 1, 1, 1)) | |
# gl.glMaterialfv(gl.GL_FRONT, gl.GL_SHININESS, (50, )) | |
# gl.glEnable(gl.GL_LIGHTING) | |
# gl.glEnable(gl.GL_LIGHT0) | |
gl.glLoadIdentity() | |
gl.glTranslatef(*self.trans_matrix) | |
#t = (time.clock() * 10) % 360 | |
#gl.glRotatef(t, 0.0, 1.0, 0.0) | |
gl.glRotatef(*self.rot_matrix_y) | |
gl.glRotatef(*self.rot_matrix_x) | |
# gl.glColor3f(1, 0, 0) | |
gl.glEnable(gl.GL_COLOR_MATERIAL) | |
gl.glBegin(gl.GL_QUADS) | |
for cell in list(self.vertices.items()): | |
gl.glColor3f(*t_abs3(cell[0])) | |
p0 = cell[0] | |
p1 = t_add3(cell[0], (0.2, 0, 0)) | |
p2 = t_add3(cell[0], (0.2, 0.2, 0)) | |
p3 = t_add3(cell[0], (0, 0.2, 0)) | |
p4 = t_add3(cell[0], (0, 0, 0.2)) | |
p5 = t_add3(cell[0], (0.2, 0, 0.2)) | |
p6 = t_add3(cell[0], (0.2, 0.2, 0.2)) | |
p7 = t_add3(cell[0], (0, 0.2, 0.2)) | |
gl.glVertex3f(*p0) | |
gl.glVertex3f(*p3) | |
gl.glVertex3f(*p2) | |
gl.glVertex3f(*p1) | |
gl.glVertex3f(*p1) | |
gl.glVertex3f(*p2) | |
gl.glVertex3f(*p6) | |
gl.glVertex3f(*p5) | |
gl.glVertex3f(*p4) | |
gl.glVertex3f(*p5) | |
gl.glVertex3f(*p6) | |
gl.glVertex3f(*p7) | |
gl.glVertex3f(*p0) | |
gl.glVertex3f(*p4) | |
gl.glVertex3f(*p7) | |
gl.glVertex3f(*p3) | |
gl.glVertex3f(*p2) | |
gl.glVertex3f(*p3) | |
gl.glVertex3f(*p7) | |
gl.glVertex3f(*p6) | |
gl.glVertex3f(*p0) | |
gl.glVertex3f(*p1) | |
gl.glVertex3f(*p5) | |
gl.glVertex3f(*p4) | |
gl.glEnd() | |
# Border Box | |
gl.glBegin(gl.GL_LINE_STRIP) | |
gl.glColor3f(1.0, 1.0, 1.0) | |
gl.glVertex3f(1.0, 1.0, 1.0) | |
gl.glVertex3f(1.0, 1.0, -1.0) | |
gl.glVertex3f(1.0, -1.0, -1.0) | |
gl.glVertex3f(1.0, -1.0, 1.0) | |
gl.glVertex3f(1.0, 1.0, 1.0) | |
gl.glEnd() | |
gl.glBegin(gl.GL_LINE_STRIP) | |
gl.glColor3f(1.0, 1.0, 1.0) | |
gl.glVertex3f(-1.0, 1.0, 1.0) | |
gl.glVertex3f(-1.0, 1.0, -1.0) | |
gl.glVertex3f(-1.0, -1.0, -1.0) | |
gl.glVertex3f(-1.0, -1.0, 1.0) | |
gl.glVertex3f(-1.0, 1.0, 1.0) | |
gl.glEnd() | |
class Cell3D: | |
def __init__(self, neighbors=0): | |
super(Cell3D, self).__init__() | |
self.neighbors = neighbors | |
if __name__ == '__main__': | |
import sys | |
app = QtWidgets.QApplication(sys.argv) | |
s_format = QtGui.QSurfaceFormat() | |
s_format.setSamples(4) | |
# window = BarWindow() | |
window = Conway3DWindow() | |
window.setFormat(s_format) | |
window.resize(800, 600) | |
window.show() | |
window.setAnimating(True) | |
sys.exit(app.exec_()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment