Skip to content

Instantly share code, notes, and snippets.

@pudelkoM
Last active August 29, 2015 14:21
Show Gist options
  • Save pudelkoM/2467647161437849b625 to your computer and use it in GitHub Desktop.
Save pudelkoM/2467647161437849b625 to your computer and use it in GitHub Desktop.
conway 3d edition
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