class Render(object): def __init__(self, width=None, height=None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point( i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = ceil(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = ceil(self.view['y'] + (self.view['height'] / 2) * (y + 1)) self.glVertexC(self.x, self.y) def glVertexC(self, x, y): self.bmp.point(y, x, self.color) def glColorC(self, r, g, b): self.color = color(r, g, b) def glColorFull(self, color): self.color = color def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) def glFinish(self, name='out'): self.bmp.write(name + '.bmp') def glLine(self, x0p, y0p, x1p, y1p): x0 = round(self.view['x'] + (self.view['width'] / 2) * (x0p + 1)) y0 = round(self.view['y'] + (self.view['height'] / 2) * (y0p + 1)) x1 = round(self.view['x'] + (self.view['width'] / 2) * (x1p + 1)) y1 = round(self.view['y'] + (self.view['height'] / 2) * (y1p + 1)) self.glLineC(x0, y0, x1, y1) def glLineC(self, x0, y0, x1, y1): dx = abs(x1 - x0) dy = abs(y1 - y0) if x1 < x0: x0, x1 = x1, x0 y0, y1 = y1, y0 px = 2 * dy - dx py = 2 * dx - dy if dx >= dy: y = y0 for x in range(x0, x1 + 1): # print(x) # print(y) self.glVertexC(x, y) if px < 0: px += 2 * dy else: y += 1 if y0 < y1 else -1 px += 2 * (dy - dx) else: x = x0 step = 1 if y0 < y1 else -1 for y in range(y0, y1, step): # print(x) # print(y) self.glVertexC(x, y) if py < 0: py += 2 * dx else: x += 1 if x0 < x1 else -1 py += 2 * (dx - dy) def loadObj(self, filename, translate=[0, 0, 0], scale=[1, 1, 1], rotate=[0, 0, 0], texture=None, light=[0, 0, 1]): with open(filename) as file: faces, vertices, textures_coor = obj.processObj(file) self.calcModelMat(rotate, scale, translate) for i in range(len(vertices)): vertices[i] = self.transform(vertices[i]) # light = [0.3, 0.1, 0.6] # light = [0, 0, 1] asdf = 0 for face in faces: asdf += 1 print(asdf) #Se obtienen las coordenadas de los vertices faceLen = len(face) faceVer = [] faceTex = [] for i in range(faceLen): faceVer.append(vertices[face[i][0] - 1]) # faceVer.append(transform_vertex( # vertices[face[i][0] - 1], # translateX=translateX, # translateY=translateY, # scale=scale # )) if texture: faceTex.append(textures_coor[face[i][1] - 1]) #Se obtiene la intensidad dot = cross_product(vector_subs(faceVer[1], faceVer[0]), vector_subs(faceVer[2], faceVer[0])) norm = normalize(dot) light_int = dot_product(norm, light) #Se recorren todos los vertices de cada cara loopLen = faceLen - 2 if faceLen <= 4: for i in range(loopLen): if light_int > 0: if not texture: self.glColor(light_int, light_int, light_int) tex_coor_temp = None else: tex_coor_temp = (faceTex[0], faceTex[i + 1], faceTex[i + 2]) self.barycentric_triangle(faceVer[0], faceVer[i + 1], faceVer[i + 2], tex_coor=tex_coor_temp, texture=texture, intensity=light_int) def calcViewportMat(self, x=0, y=0): res = [[self.width / 2, 0, 0, x + self.width / 2], [0, self.height / 2, 0, y + self.height / 2], [0, 0, 100, 100], [0, 0, 0, 1]] self.viewport_matrix = res def calcModelMat(self, rotate=[0, 0, 0], scale=[1, 1, 1], translate=[0, 0, 0]): rotate_x = [[1, 0, 0, 0], [0, cos(rotate[0]), -sin(rotate[0]), 0], [0, sin(rotate[0]), cos(rotate[0]), 0], [0, 0, 0, 1]] rotate_y = [[cos(rotate[1]), 0, sin(rotate[1]), 0], [0, 1, 0, 0], [-sin(rotate[1]), 0, cos(rotate[1]), 0], [0, 0, 0, 1]] rotate_z = [[cos(rotate[2]), -sin(rotate[2]), 0, 0], [sin(rotate[2]), cos(rotate[2]), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] rotate_all = matmul(matmul(rotate_x, rotate_y), rotate_z) translation = [[1, 0, 0, translate[0]], [0, 1, 0, translate[1]], [0, 0, 1, translate[2]], [0, 0, 0, 1]] scale_mat = [[scale[0], 0, 0, 0], [0, scale[1], 0, 0], [0, 0, scale[2], 0], [0, 0, 0, 1]] self.model_matrix = matmul(matmul(translation, rotate_all), scale_mat) def calcViewMat(self, x, y, z, center): view_mat = [[x[0], x[1], x[2], -center[0]], [y[0], y[1], y[2], -center[1]], [z[0], z[1], z[2], -center[2]], [0, 0, 0, 1]] self.view_matrix = view_mat def calcProjectionMat(self, c): proj = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, c, 1]] self.proj_matrix = proj def transform(self, vertex): vertex = [[vertex[0]], [vertex[1]], [vertex[2]], [1]] homog_mat = matmul( matmul( matmul(matmul(self.viewport_matrix, self.proj_matrix), self.view_matrix), self.model_matrix), vertex) trans_vertex = [ round(homog_mat[0][0] / homog_mat[3][0]), round(homog_mat[1][0] / homog_mat[3][0]), round(homog_mat[2][0] / homog_mat[3][0]) ] return trans_vertex def lookAt(self, cameraPos, cameraTarget, up): z = normalize(vector_subs(cameraPos, cameraTarget)) x = normalize(cross_product(up, z)) y = normalize(cross_product(z, x)) self.calcViewMat(x, y, z, cameraTarget) self.calcProjectionMat( -1 / vec_length(vector_subs(cameraPos, cameraTarget))) self.calcViewportMat() def barycentric_triangle(self, A, B, C, tex_coor=(), texture=None, intensity=1): x_min, x_max, y_min, y_max = bounding_box(A, B, C) for i in range(x_min, x_max + 1): for j in range(y_min, y_max + 1): if i < 0 or j < 0: continue u, v, w = barycentric2(A, B, C, [i, j]) if u >= 0 and v >= 0 and w >= 0: if texture: tex_A, tex_B, tex_C = tex_coor tex_x = tex_A[0] * u + tex_B[0] * v + tex_C[0] * w tex_y = tex_A[1] * u + tex_B[1] * v + tex_C[1] * w self.glColorFull( texture.getColor(tex_x, tex_y, intensity)) P_z = dot_product([u, v, w], [A[2], B[2], C[2]]) if j < len(self.bmp.zbuffer) and i < len( self.bmp.zbuffer[j]) and self.bmp.getZbuffer( i, j) < P_z: self.bmp.setZbuffer(i, j, P_z) self.glVertexC(i, j)
class Render(object): def __init__(self, width=None, height=None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point( i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = trunc(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = trunc(self.view['y'] + (self.view['height'] / 2) * (y + 1)) # print(self.x) # print(self.y) self.bmp.point(self.y, self.x, self.color) def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) # self.bmp.point(self.x, self.y, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glFinish(self, name='out'): self.bmp.write(name + '.bmp') def display(self, name='out'): self.glFinish(name) try: from wand.image import Image from wand.display import display with Image(filename=name + '.bmp') as image: display(image) except Exception as e: print(e) pass # do nothing if no wand is installed
class Render(object): def __init__(self, width = None, height = None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point(i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = ceil(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = ceil(self.view['y'] + (self.view['height'] / 2) * (y + 1)) self.glVertexC(self.x, self.y) def glVertexC(self, x, y): self.bmp.point(y, x, self.color) def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) def glFinish(self, name = 'out'): self.bmp.write(name+'.bmp') def glLine(self, x0p, y0p, x1p, y1p): x0 = round(self.view['x'] + (self.view['width'] / 2) * (x0p + 1)) y0 = round(self.view['y'] + (self.view['height'] / 2) * (y0p + 1)) x1 = round(self.view['x'] + (self.view['width'] / 2) * (x1p + 1)) y1 = round(self.view['y'] + (self.view['height'] / 2) * (y1p + 1)) self.glLineC(x0, y0, x1, y1) def glLineC(self, x0, y0, x1, y1): dx = abs(x1 - x0) dy = abs(y1 - y0) if x1 < x0: x0, x1 = x1, x0 y0, y1 = y1, y0 px = 2 * dy - dx py = 2 * dx - dy if dx >= dy: y = y0 for x in range(x0, x1 + 1): # print(x) # print(y) self.glVertexC(x, y) if px < 0: px += 2 * dy else: y += 1 if y0 < y1 else -1 px += 2 * (dy - dx) else: x = x0 step = 1 if y0 < y1 else -1 for y in range(y0, y1, step): # print(x) # print(y) self.glVertexC(x, y) if py < 0: py += 2 * dx else: x += 1 if x0 < x1 else -1 py += 2 * (dx - dy) def loadObj(self, filename, translateX=0, translateY=0, scale=1, triangle=0): with open(filename) as file: faces, vertices = obj.processObj(file) for face in faces: faceLen = len(face) faceVer = [] for i in range(faceLen): faceVer.append(transform_vertex( vertices[face[i][0] - 1], translateX=translateX, translateY=translateY, scale=scale )) loopLen = faceLen - 2 for i in range(loopLen): self.glColor(ran.random(), ran.random(), ran.random()) if triangle == 0: self.barycentric_triangle(faceVer[0], faceVer[i+1], faceVer[i+2]) elif triangle == 1: self.line_sweeping_triangle2(faceVer[0], faceVer[i+1], faceVer[i+2]) def display(self, name = 'out'): self.glFinish(name) try: from wand.image import Image from wand.display import display with Image(filename = name + '.bmp') as image: display(image) except Exception as e: print(e) pass # do nothing if no wand is installed def line_sweeping_triangle(self, A, B, C): if (A[1] > B[1]): A, B = B, A if (B[1] > C[1]): B, C = C, B if (A[1] > B[1]): A, B = B, A self.glLineC(A[0], A[1], B[0], B[1]) self.glLineC(A[0], A[1], C[0], C[1]) self.glLineC(B[0], B[1], C[0], C[1]) for i in range(A[1], B[1]): x0 = round(x(A, C, i)) x1 = round(x(A, B, i)) self.glLineC(x0, i, x1, i) for i in range(B[1], C[1]): x0 = round(x(A, C, i)) x1 = round(x(B, C, i)) self.glLineC(x0, i, x1, i) def line_sweeping_triangle2(self, A, B, C): if (A[1] > B[1]): A, B = B, A if (B[1] > C[1]): B, C = C, B if (A[1] > B[1]): A, B = B, A total_height = C[1] - A[1] first_height = B[1] - A[1] second_height = C[1] - B[1] if total_height == 0: return # if first_height: for i in range(A[1], B[1]): alpha = (i - A[1]) / total_height beta = (i - A[1]) / first_height v0 = vector_sum(A, vector_linear_mul(vector_subs(C, A), alpha)) v1 = vector_sum(A, vector_linear_mul(vector_subs(B, A), beta)) if v0[0] > v1[0]: v0, v1 = v1, v0 for j in range(round(v0[0]), round(v1[0])): self.glVertexC(j, i) for i in range(B[1], C[1]): alpha = (i - A[1]) / total_height beta = (i - B[1]) / second_height v0 = vector_sum(A, vector_linear_mul(vector_subs(C, A), alpha)) v1 = vector_sum(B, vector_linear_mul(vector_subs(C, B), beta)) if v0[0] > v1[0]: v0, v1 = v1, v0 for j in range(round(v0[0]), round(v1[0])): self.glVertexC(j, i) def barycentric_triangle(self, A, B, C): x_min, x_max, y_min, y_max = bounding_box(A, B, C) for i in range(x_min, x_max + 1): for j in range(y_min, y_max + 1): if barycentric(A, B, C, [i, j, 0]): self.glVertexC(i, j)
class Render(object): def __init__(self, width=None, height=None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point( i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = ceil(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = ceil(self.view['y'] + (self.view['height'] / 2) * (y + 1)) self.glVertexC(self.x, self.y) def glVertexC(self, x, y): self.bmp.point(y, x, self.color) def glColorC(self, r, g, b): self.color = color(r, g, b) def glColorFull(self, color): self.color = color def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) def glFinish(self, name='out'): self.bmp.write(name + '.bmp') def glLine(self, x0p, y0p, x1p, y1p): x0 = round(self.view['x'] + (self.view['width'] / 2) * (x0p + 1)) y0 = round(self.view['y'] + (self.view['height'] / 2) * (y0p + 1)) x1 = round(self.view['x'] + (self.view['width'] / 2) * (x1p + 1)) y1 = round(self.view['y'] + (self.view['height'] / 2) * (y1p + 1)) self.glLineC(x0, y0, x1, y1) def glLineC(self, x0, y0, x1, y1): dx = abs(x1 - x0) dy = abs(y1 - y0) if x1 < x0: x0, x1 = x1, x0 y0, y1 = y1, y0 px = 2 * dy - dx py = 2 * dx - dy if dx >= dy: y = y0 for x in range(x0, x1 + 1): # print(x) # print(y) self.glVertexC(x, y) if px < 0: px += 2 * dy else: y += 1 if y0 < y1 else -1 px += 2 * (dy - dx) else: x = x0 step = 1 if y0 < y1 else -1 for y in range(y0, y1, step): # print(x) # print(y) self.glVertexC(x, y) if py < 0: py += 2 * dx else: x += 1 if x0 < x1 else -1 py += 2 * (dx - dy) def loadObj(self, filename, translateX=0, translateY=0, scale=1, texture=None, light=[0, 0, 1]): with open(filename) as file: faces, vertices, textures_coor = obj.processObj(file) # light = [0.3, 0.1, 0.6] # light = [0, 0, 1] for face in faces: #Se obtienen las coordenadas de los vertices faceLen = len(face) faceVer = [] faceTex = [] for i in range(faceLen): faceVer.append( transform_vertex(vertices[face[i][0] - 1], translateX=translateX, translateY=translateY, scale=scale)) faceTex.append(textures_coor[face[i][1] - 1]) #Se obtiene la intensidad dot = cross_product(vector_subs(faceVer[1], faceVer[0]), vector_subs(faceVer[2], faceVer[0])) norm = normalize(dot) light_int = dot_product(norm, light) #Se recorren todos los vertices de cada cara loopLen = faceLen - 2 for i in range(loopLen): if light_int > 0: if not texture: self.glColor(light_int, light_int, light_int) self.barycentric_triangle(faceVer[0], faceVer[i + 1], faceVer[i + 2], tex_coor=(faceTex[0], faceTex[i + 1], faceTex[i + 2]), texture=texture, intensity=light_int) def display(self, name='out'): self.glFinish(name) try: from wand.image import Image from wand.display import display with Image(filename=name + '.bmp') as image: display(image) except Exception as e: print(e) pass def barycentric_triangle(self, A, B, C, tex_coor=(), texture=None, intensity=1): x_min, x_max, y_min, y_max = bounding_box(A, B, C) for i in range(x_min, x_max + 1): for j in range(y_min, y_max + 1): u, v, w = barycentric2(A, B, C, [i, j]) if u >= 0 and v >= 0 and w >= 0: if texture: tex_A, tex_B, tex_C = tex_coor tex_x = tex_A[0] * u + tex_B[0] * v + tex_C[0] * w tex_y = tex_A[1] * u + tex_B[1] * v + tex_C[1] * w self.glColorFull( texture.getColor(tex_x, tex_y, intensity)) P_z = dot_product([u, v, w], [A[2], B[2], C[2]]) if self.bmp.getZbuffer(i, j) < P_z: self.bmp.setZbuffer(i, j, P_z) self.glVertexC(i, j)
class Render(object): def __init__(self, width = None, height = None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point(i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = ceil(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = ceil(self.view['y'] + (self.view['height'] / 2) * (y + 1)) self.glVertexC(self.x, self.y) def glVertexC(self, x, y): self.bmp.point(y, x, self.color) def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) def glFinish(self, name = 'out'): self.bmp.write(name+'.bmp') def glLine(self, x0p, y0p, x1p, y1p): x0 = round(self.view['x'] + (self.view['width'] / 2) * (x0p + 1)) y0 = round(self.view['y'] + (self.view['height'] / 2) * (y0p + 1)) x1 = round(self.view['x'] + (self.view['width'] / 2) * (x1p + 1)) y1 = round(self.view['y'] + (self.view['height'] / 2) * (y1p + 1)) self.glLineC(x0, y0, x1, y1) def glLineC(self, x0, y0, x1, y1): dx = abs(x1 - x0) dy = abs(y1 - y0) if x1 < x0: x0, x1 = x1, x0 y0, y1 = y1, y0 px = 2 * dy - dx py = 2 * dx - dy if dx >= dy: y = y0 for x in range(x0, x1 + 1): # print(x) # print(y) self.glVertexC(x, y) if px < 0: px += 2 * dy else: y += 1 if y0 < y1 else -1 px += 2 * (dy - dx) else: x = x0 step = 1 if y0 < y1 else -1 for y in range(y0, y1, step): # print(x) # print(y) self.glVertexC(x, y) if py < 0: py += 2 * dx else: x += 1 if x0 < x1 else -1 py += 2 * (dx - dy) def loadObj(self, filename, translateX=0, translateY=0, scale=1, triangle=0): with open(filename) as file: faces, vertices = obj.processObj(file) light = [0.2, 0.3, 0.5] for face in faces: faceLen = len(face) faceVer = [] for i in range(faceLen): faceVer.append(transform_vertex( vertices[face[i][0] - 1], translateX=translateX, translateY=translateY, scale=scale )) loopLen = faceLen - 2 for i in range(loopLen): dot = cross_product(vector_subs(faceVer[i+1], faceVer[0]), vector_subs(faceVer[i+2], faceVer[0])) norm = normalize(dot) light_int = dot_product(norm, light) if light_int > 0: self.glColor(light_int, light_int, light_int) self.barycentric_triangle(faceVer[0], faceVer[i+1], faceVer[i+2]) def display(self, name = 'out'): self.glFinish(name) try: from wand.image import Image from wand.display import display with Image(filename = name + '.bmp') as image: display(image) except Exception as e: print(e) pass # do nothing if no wand is installed # def line_sweeping_triangle(self, A, B, C): # if (A[1] > B[1]): # A, B = B, A # if (B[1] > C[1]): # B, C = C, B # if (A[1] > B[1]): # A, B = B, A # # self.glLineC(A[0], A[1], B[0], B[1]) # self.glLineC(A[0], A[1], C[0], C[1]) # self.glLineC(B[0], B[1], C[0], C[1]) # # for i in range(A[1], B[1]): # x0 = round(x(A, C, i)) # x1 = round(x(A, B, i)) # self.glLineC(x0, i, x1, i) # # for i in range(B[1], C[1]): # x0 = round(x(A, C, i)) # x1 = round(x(B, C, i)) # self.glLineC(x0, i, x1, i) def barycentric_triangle(self, A, B, C): x_min, x_max, y_min, y_max = bounding_box(A, B, C) for i in range(x_min, x_max + 1): for j in range(y_min, y_max + 1): u, v, w = barycentric2(A, B, C, [i, j]) if u >= 0 and v >= 0 and w >= 0: P_z = dot_product([u, v, w], [A[2], B[2], C[2]]) if self.bmp.getZbuffer(i, j) < P_z: self.bmp.setZbuffer(i, j, P_z) self.glVertexC(i, j)
class Render(object): def __init__(self, width = None, height = None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point(i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = ceil(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = ceil(self.view['y'] + (self.view['height'] / 2) * (y + 1)) self.glVertexC(self.x, self.y) def glVertexC(self, x, y): self.bmp.point(y, x, self.color) def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) def glFinish(self, name = 'out'): self.bmp.write(name+'.bmp') def glLine(self, x0p, y0p, x1p, y1p): x0 = round(self.view['x'] + (self.view['width'] / 2) * (x0p + 1)) y0 = round(self.view['y'] + (self.view['height'] / 2) * (y0p + 1)) x1 = round(self.view['x'] + (self.view['width'] / 2) * (x1p + 1)) y1 = round(self.view['y'] + (self.view['height'] / 2) * (y1p + 1)) self.glLineC(x0, y0, x1, y1) def glLineC(self, x0, y0, x1, y1): # print(x0) # print(y0) # print(x1) # print(y1) dx = abs(x1 - x0) dy = abs(y1 - y0) if x1 < x0: x0, x1 = x1, x0 y0, y1 = y1, y0 px = 2 * dy - dx py = 2 * dx - dy if dx >= dy: y = y0 for x in range(x0, x1 + 1): # print(x) # print(y) self.glVertexC(x, y) if px < 0: px += 2 * dy else: y += 1 if y0 < y1 else -1 px += 2 * (dy - dx) else: x = x0 step = 1 if y0 < y1 else -1 for y in range(y0, y1, step): # print(x) # print(y) self.glVertexC(x, y) if py < 0: py += 2 * dx else: x += 1 if x0 < x1 else -1 py += 2 * (dx - dy) def display(self, name = 'out'): self.glFinish(name) try: from wand.image import Image from wand.display import display with Image(filename = name + '.bmp') as image: display(image) except Exception as e: print(e) pass # do nothing if no wand is installed def fillPolygon(self, points, r, g, b): self.glColor(r / 255, g / 255, b / 255) for i in range(-1,len(points)-1): self.glLineC(points[i][0], points[i][1], points[i+1][0], points[i+1][1]) edges = self.createPolygonEdges(points) y_min = min([points[i][1] for i in range(len(points))]) y_max = max([points[i][1] for i in range(len(points))]) x_min = min([points[i][0] for i in range(len(points))]) x_max = max([points[i][0] for i in range(len(points))]) for i in range(y_min, y_max+1): activeEdges = [edges[n] for n in range(len(edges)) if edges[n]['yMin'] <= i <= edges[n]['yMax']] activeEdges = sorted(activeEdges, key=lambda item: item['x']) count = 0 intercepts = [] for j in range(len(activeEdges)): if activeEdges[j]['m'] == 0: adjEdges = [] for k in range(len(activeEdges)): if j != k: if (activeEdges[j]['v0'] == activeEdges[k]['v0'] or activeEdges[j]['v0'] == activeEdges[k]['v1']): adjEdges.append(activeEdges[k]) if (activeEdges[j]['v1'] == activeEdges[k]['v0'] or activeEdges[j]['v1'] == activeEdges[k]['v1']): adjEdges.append(activeEdges[k]) if len(adjEdges) == 2: break if not (adjEdges[0]['yMax'] == adjEdges[1]['yMax'] or adjEdges[0]['yMin'] == adjEdges[1]['yMin']): intercepts.append(activeEdges[j]['x']) elif j < len(activeEdges)-1: if not (( (i == activeEdges[j]['v0'][1] and ( activeEdges[j]['v0'] == activeEdges[j+1]['v0'] or activeEdges[j]['v0'] == activeEdges[j+1]['v1'] )) or (i == activeEdges[j]['v1'][1] and ( activeEdges[j]['v1'] == activeEdges[j+1]['v0'] or activeEdges[j]['v1'] == activeEdges[j+1]['v1'] )) ) and ((activeEdges[j]['yMin'] != activeEdges[j+1]['yMin']) and (activeEdges[j]['yMax'] != activeEdges[j+1]['yMax']))): if activeEdges[j]['m'] == 0: intercepts.append(activeEdges[j]['x']) else: intercepts.append(round( activeEdges[j]['x0'] - ((activeEdges[j]['y0'] - i) / activeEdges[j]['m']) )) else: if activeEdges[j]['m'] == 0: intercepts.append(activeEdges[j]['x']) else: intercepts.append(round( activeEdges[j]['x0'] - ((activeEdges[j]['y0'] - i) / activeEdges[j]['m']) )) # if i == 214: # print('INTERCEPTS') # print('') # print(intercepts) # print('') # break for j in range(x_min, x_max + 1): count = 0 for k in range(len(intercepts)): if intercepts[k] < j: count += 1 if count % 2 == 1: self.glVertexC(j, i) def createPolygonEdges(self, ver): edges = [] for i in range(-1, len(ver)-1): edge = {} # if ver[i][1] - ver[i+1][1] != 0: edge['yMax'] = max([ver[i][1], ver[i+1][1]]) edge['yMin'] = min([ver[i][1], ver[i+1][1]]) edge['x'] = min([ver[i][0], ver[i+1][0]]) edge['x0'] = ver[i][0] edge['y0'] = ver[i][1] edge['v0'] = [ver[i][0], ver[i][1]] edge['v1'] = [ver[i+1][0], ver[i+1][1]] if ver[i][0] - ver[i+1][0] == 0: edge['m'] = 999999999 else: edge['m'] = ((ver[i][1]-ver[i+1][1])/(ver[i][0]-ver[i+1][0])) edges.append(edge) return edges
class Render(object): def __init__(self, width=None, height=None): self.x = 0 self.y = 0 self.view = {} self.color = color(255, 255, 255) if (width == None and height == None): self.bmp = None self.width = width self.height = height else: self.glCreateWindow(width, height) def glInit(self): pass def glCreateWindow(self, width, height): self.bmp = Bitmap(width, height) self.width = width self.height = height def glViewPort(self, x, y, width, height): self.view['x'] = x self.view['y'] = y self.view['width'] = width - 1 self.view['height'] = height - 1 def glClear(self): self.bmp.clear() def glClearColor(self, r, g, b): for i in range(self.height): for j in range(self.width): self.bmp.point( i, j, color(trunc(r * 255), trunc(g * 255), trunc(b * 255))) def glVertex(self, x, y): self.x = ceil(self.view['x'] + (self.view['width'] / 2) * (x + 1)) self.y = ceil(self.view['y'] + (self.view['height'] / 2) * (y + 1)) self.glVertexC(self.x, self.y) def glVertexC(self, x, y): self.bmp.point(y, x, self.color) def glColor(self, r, g, b): self.color = color(floor(r * 255), floor(g * 255), floor(b * 255)) def glFinish(self, name='out'): self.bmp.write(name + '.bmp') def glLine(self, x0p, y0p, x1p, y1p): x0 = round(self.view['x'] + (self.view['width'] / 2) * (x0p + 1)) y0 = round(self.view['y'] + (self.view['height'] / 2) * (y0p + 1)) x1 = round(self.view['x'] + (self.view['width'] / 2) * (x1p + 1)) y1 = round(self.view['y'] + (self.view['height'] / 2) * (y1p + 1)) self.glLineC(x0, y0, x1, y1) def glLineC(self, x0, y0, x1, y1): # print(x0) # print(y0) # print(x1) # print(y1) dx = abs(x1 - x0) dy = abs(y1 - y0) if x1 < x0: x0, x1 = x1, x0 y0, y1 = y1, y0 px = 2 * dy - dx py = 2 * dx - dy if dx >= dy: y = y0 for x in range(x0, x1 + 1): # print(x) # print(y) self.glVertexC(x, y) if px < 0: px += 2 * dy else: y += 1 if y0 < y1 else -1 px += 2 * (dy - dx) else: x = x0 step = 1 if y0 < y1 else -1 for y in range(y0, y1, step): # print(x) # print(y) self.glVertexC(x, y) if py < 0: py += 2 * dx else: x += 1 if x0 < x1 else -1 py += 2 * (dx - dy) def display(self, name='out'): self.glFinish(name) try: from wand.image import Image from wand.display import display with Image(filename=name + '.bmp') as image: display(image) except Exception as e: print(e) pass # do nothing if no wand is installed