From 1e452ca41e3676aeb6d323360ecebd555ece6ed6 Mon Sep 17 00:00:00 2001 From: Jonas Weinz Date: Thu, 18 May 2017 20:58:15 +0200 Subject: [PATCH] first try with render thread --- field.py | 42 +++++++++++++++---- glField.py | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ glMain.py | 24 +++++++++++ rule.py | 9 ++-- 4 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 glField.py create mode 100644 glMain.py diff --git a/field.py b/field.py index e0de2f9..05d8732 100644 --- a/field.py +++ b/field.py @@ -1,19 +1,33 @@ -import numpy as np import rule +import time class Field(object): def __init__(self, shape = (32,32)): self.resize(shape) self.a_to_b = True self.rule = rule.Rule(0) + self.updatedValues = [] # tuple (i,j, newValue) def setRule(self, rule): self.rule = rule def resize(self, shape): self.shape = shape - self.matrix_a = np.matrix(np.zeros(shape, int)) - self.matrix_b = np.matrix(np.zeros(shape, int)) + + self.matrix_a = [] + self.matrix_b = [] + + for i in range(shape[0]): + row_a = [] + row_b = [] + for j in range(shape[1]): + row_a.append(0) + row_b.append(0) + self.matrix_a.append(row_a) + self.matrix_b.append(row_b) + + def getUpdatedValues(self): + return self.updatedValues def update(self): self.a_to_b = False if self.a_to_b else True @@ -24,14 +38,17 @@ class Field(object): h, w = self.shape for i in range(h): for j in range(w): - b[i,j] = self.rule.applyRule(a, i, j) + #b[i,j] = self.rule.applyRule(a, i, j) + b[i][j] = self.rule.applyRule(a, self.shape, i, j) + if a[i][j] != b[i][j]: + self.updatedValues.append((i,j,b[i][j])) def getField(self): return self.matrix_b if self.a_to_b else self.matrix_a def setValue(self, y, x, val): - self.matrix_a[y,x] = val - self.matrix_b[y,x] = val + self.matrix_a[y][x] = val + self.matrix_b[y][x] = val # some testing if __name__ == "__main__": @@ -40,6 +57,13 @@ if __name__ == "__main__": f.setRule(r) f.setValue(2,2,1) - for i in range(10): - print(f.getField()) - f.update() \ No newline at end of file + steps = 10 + t_start = time.time() + + for i in range(steps): + #print(f.getField()) + f.update() + + t_end = time.time() + + print("average time per update: " + str((t_end - t_start) / steps) ) \ No newline at end of file diff --git a/glField.py b/glField.py new file mode 100644 index 0000000..5882e87 --- /dev/null +++ b/glField.py @@ -0,0 +1,121 @@ +import pygame +from OpenGL.GL import * +from pygame.locals import * +import threading + +class GLField(threading.Thread): + + def __init__(self, w, h, win_w, win_h, fullscreen = False): + super(GLField, self).__init__() + self.input = [] + self.changed_values = [] + + self.inputLock = threading.Lock() + + self.queue = [] + + + self.fullscreen = fullscreen + + self.w = w + self.h = h + self.win_w = win_w + self.win_h = win_h + self.rect_w = self.win_w / self.w + self.rect_h = self.win_h / self.h + + self.colors = [] + + self.FPS = 30 + + self.drawBuffer = [] + + def initFieldColors(self): + for i in range(self.w): + self.colors.append([]) + for j in range(self.h): + rgba = [float(j) / float(self.h), float(self.w - j) / float(self.w), + float(i) / float(self.h), 0.15] + self.colors[i].append(rgba) + + def resize(self): + glViewport(0,0, self.win_w, self.win_h) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + glOrtho(0.0, self.w * self.rect_w, self.h * self.rect_h, 0.0, -6.0, 0.0) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + + glClearColor(0.0, 0.0, 0.0, 0.0) + + def drawQuadInternally(self, pX, pY): + r,g,b,a = self.colors[pY][pX] + glColor4f(a*r, a*g, a*b, 1.0) + y = pY * self.rect_w + x = pX * self.rect_h + + glVertex3f(x,y,0.0) + glVertex3f(x + self.rect_w - 1.0, y, 0.0) + glVertex3f(x + self.rect_w - 1.0, y + self.rect_h - 1.0, 0.0) + glVertex3f(x, y + self.rect_h - 1.0, 0.0) + + def appendChanges(self, changes): + self.inputLock.acquire() + self.changed_values += changes + self.inputLock.release() + + + def draw(self): + self.inputLock.acquire() + for c in self.changed_values: + i,j,v = c + self.colors[i][j][3] = v + self.queue.append((i,j)) + self.inputLock.release() + + glBegin(GL_QUADS) + for i,j in self.queue + self.drawBuffer: + self.drawQuadInternally(j,i) + glEnd() + + self.drawBuffer = self.queue + self.queue = [] + self.changed_values = [] + + def run(self): + pygame.init() + + video_flags = OPENGL | HWSURFACE | DOUBLEBUF | FULLSCREEN if self.fullscreen else OPENGL | HWSURFACE | DOUBLEBUF + dinfo = pygame.display.Info() + window_w = dinfo.current_w if self.fullscreen else self.win_w + window_h = dinfo.current_h if self.fullscreen else self.win_h + + self.win_w = window_w + self.win_h = window_h + + self.rect_w = self.win_w / self.w + self.rect_h = self.win_h / self.h + + pygame.display.set_mode((self.win_w, self.win_h), video_flags) + + self.initFieldColors() + self.resize() + + clock = pygame.time.Clock() + + counter = 0 + + while True: + print("render main #" + str(counter)) + counter += 1 + ticktime = clock.tick(self.FPS) + # print ticktime + event = pygame.event.poll() + if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): + break + self.draw() + + pygame.display.flip() + + + diff --git a/glMain.py b/glMain.py new file mode 100644 index 0000000..ddbf387 --- /dev/null +++ b/glMain.py @@ -0,0 +1,24 @@ +from field import * +from glField import * + +def main(): + f = Field((160, 90)) + r = rule.Rule(2) + f.setRule(r) + f.setValue(2, 2, 1) + + screen = GLField(160, 90, 800,600, False) + + screen.start() + + counter = 0 + + while screen.is_alive(): + f.update() + c = f.getUpdatedValues() + screen.appendChanges(c) + print("master thread #" + str(counter)) + counter += 1 + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/rule.py b/rule.py index bb9e895..612d4b0 100644 --- a/rule.py +++ b/rule.py @@ -1,4 +1,3 @@ -import numpy as np class Rule(object): @@ -7,7 +6,7 @@ class Rule(object): self.k = k self.a = 2 * r + 1 self.a2 = self.a**2 - self.rule_table = np.zeros(k**self.a2, int) + self.rule_table = k**self.a2 * [0] self.setRule(rule_id) def setRule(self, rule_id): @@ -19,18 +18,18 @@ class Rule(object): self.rule_id = rule_id self.generateRuleTable() - def applyRule(self, matrix_field, pos_y, pos_x): + def applyRule(self, matrix_field, shape, pos_y, pos_x): e = 0 sum = 0 - h, w = matrix_field.shape + h, w = shape for i in range(pos_y - self.r, pos_y + self.r + 1): for j in range(pos_x - self.r, pos_x + self.r + 1): y = i if i < h else i - h x = j if j < w else j - w - sum += matrix_field[y,x] * self.k**e + sum += matrix_field[y][x] * self.k**e e += 1 return self.rule_table[sum]