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 ModulenControl(PanelModules, ControlBase): def __init__(self, parent, remote): """ remote is instance of HubProtocol for communication with remote""" PanelModules.__init__(self, parent) ControlBase.__init__(self) self.remote = remote self.scaleX = 1 self.scaleY = 1 self.drawMode = 0 self.hubList = hubs.HubListModel(self.scrolledWindowHubs, self) listHubsSizer = wx.BoxSizer(wx.VERTICAL) listHubsSizer.Add(self.hubList, 1, wx.ALL | wx.EXPAND, 5) self.scrolledWindowHubs.SetSizer(listHubsSizer) listHubsSizer.Fit(self.scrolledWindowHubs) self.fanbotList = hubs.FanbotListModel(self.scrolledWindowFanbots, self) listFanbotsSizer = wx.BoxSizer(wx.VERTICAL) listFanbotsSizer.Add(self.fanbotList, 1, wx.ALL | wx.EXPAND, 5) self.scrolledWindowFanbots.SetSizer(listFanbotsSizer) listFanbotsSizer.Fit(self.scrolledWindowFanbots) self.pointCurrent = wx.Point(0, 0) self.pointPrevious = wx.Point(0, 0) self.currenthub = None self.compressedFrame = array.array("B", [0] * 125) self.bitmap = Bitmap(FanbotConfig.width, FanbotConfig.height) self.bitmap.clear() for hub in self.hubList.hubs: self.showHub(hub) self.timerAnimate = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.timerAnimateHandler, self.timerAnimate) self.animateIdx = 0 self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.timerDiscover, self.timer) self.timerDiscoverCount = 0 def buttonResetDiscOnButtonClick(self, event): self.remote.sendCommand(HubProtocol.RESET) self.hubList.resetDiscovery() def buttonDiscoverOnButtonClick(self, event): self.remote.sendCommand(HubProtocol.REQUEST_ID) self.timer.Start(2000) self.timerDiscoverCount = 2 self.sendMessage("Discover module. Even geduld aub... ") def timerDiscover(self, event): if self.timerDiscoverCount == 0: self.timer.Stop() else: self.timerDiscoverCount -= 1 self.remote.sendCommand(HubProtocol.REQUEST_ID) self.hubList.refresh() def buttonClearListOnButtonClick(self, event): self.listModules.Clear() def buttonResetConfigOnButtonClick(self, event): if self.currenthub: self.resetHub(self.currenthub) self.remote.sendConfig(self.currenthub.idAsArray(), self.currenthub.config) def buttonSetConfigOnButtonClick(self, event): if self.currenthub: hub = self.currenthub print "buttonSetConfigOnButtonClick, currenthub: ", hub.id self.remote.sendConfig(hub.idAsArray(), hub.config) def buttonSetConfigAllOnButtonClick(self, event): print "buttonSetConfigAllButtonClick" for hub in self.hubList.hubs: self.remote.sendConfig(hub.idAsArray(), hub.config) time.sleep(0.100) def panelModulesCanvasOnSize(self, event): rect = self.panelModulesCanvas.GetRect() self.scaleX = rect.GetWidth() / self.bitmap.width self.scaleY = rect.GetHeight() / self.bitmap.height # print 'Scale x:y',self.scaleX,':',self.scaleY self.Refresh() def panelModulesCanvasOnPaint(self, event): dc = wx.PaintDC(self.panelModulesCanvas) dc.BeginDrawing() dc.SetUserScale(self.scaleX, self.scaleY) dc.Clear() dc.DrawBitmap(self.bitmap.getBitmap(), 0, 0) dc.EndDrawing() def panelModulesCanvasOnMouseEvents(self, event): point = None canvas = self.panelModulesCanvas if event: # set mouse cursor canvas.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) # get device context of canvas dc = wx.ClientDC(canvas) dc.SetUserScale(self.scaleX, self.scaleY) point = event.GetLogicalPosition(dc) if point.x < 0 or point.x >= FanbotConfig.width or point.y < 0 or point.y >= FanbotConfig.height: # print 'x,y out of bounds: ',point.x ,':',point.y return if self.checkBoxMatrix.IsChecked(): """ set the snapto grid to horizontal 4 and vertical 6""" point.x /= 4 point.x *= 4 point.y /= 6 point.y *= 6 self.labelPosition.SetLabel("%s : %s" % (point.x, point.y)) self.pointCurrent = point # print "mouse event X : " ,point.x , " Y: ",point.y if event.LeftDown(): self.panelModulesCanvas.Refresh() self.pointPrevious = self.pointCurrent if self.checkBoxMatrix.IsChecked(): self.matrixHubConfig(point.x, point.y) else: self.updateHubConfig(point.x, point.y) elif event.LeftIsDown() and not self.checkBoxMatrix.IsChecked(): if self.pointPrevious.x == self.pointCurrent.x and self.pointPrevious.y == self.pointCurrent.y: return self.pointPrevious = self.pointCurrent # print "Dragging to X : " ,point.x , " Y: ",point.y cur = wx.StockCursor(wx.CURSOR_CROSS) canvas.SetCursor(cur) self.updateHubConfig(point.x, point.y) def updateHubConfig(self, x, y): hub = self.currenthub if hub: if hub.canAddConfigItem(): if self.bitmap.pixelSetWhite(x, y): hub.setConfig(x, y) self.panelModulesCanvas.Refresh() def matrixHubConfig(self, x, y): hub = self.currenthub if hub: if hub.canAddConfigItem(): hub.resetConfig() for y in range(self.pointCurrent.y, self.pointCurrent.y + 6): for x in range(self.pointCurrent.x, self.pointCurrent.x + 4): self.bitmap.pixelSetWhite(x, y) self.currenthub.setConfig(x, y) self.panelModulesCanvas.Refresh() def handleCommand(self, opcode, payload): """ Handle incoming data from remote hubs or hubsimulator""" print "Modulen: Received opcode: %04x -- %s" % (opcode, payload) id = "" if len(payload) >= 4: for i in range(4): id = "%02x%s" % (payload[i], id) if opcode == HubProtocol.ID_REPORT: if len(payload) != 4: print "Error: incorrect length from hub received" return self.sendMessage("Discovered hub: " + id) print "Modulen: Received ID_REPORT from %s" % (id) hub = self.hubList.addHub(id) hub.discoverd = True hub.responsive = True # self.remote.sendCommand( HubProtocol.TAG_ID,4,hub.idAsArray() ) # remove tagging, as it messes up frames elif opcode == HubProtocol.STATUS_REPORT: hub = self.currenthub if hub: hub.setFanbots(payload) self.fanbotList.setFanbots(hub.fanbots) self.labelHubId.SetLabel("Hub: " + id) def hubSelected(self, hub): """Callback function called from the hubs list control""" self.showHub(self.currenthub) print "selected hub:", hub.id self.currenthub = hub config = hub.config for i in range(0, len(config)): tuple = hub.getConfigColor(i) if tuple[0] >= 0: x = tuple[0] y = tuple[1] self.bitmap.setPixel(x, y, 0xFFFFFF) self.fanbotList.setFanbots(None) self.labelHubId.SetLabel("Hub: ") self.panelModulesCanvas.Refresh() self.remote.sendCommand(HubProtocol.REQUEST_STATUS, 4, hub.idAsArray()) time.sleep(0.2) if 0 == self.sliderAnimateHub.GetValue(): self.createHubBitmap() self.remote.sendFanbotFrame(self.compressedFrame) def fanbbotSelected(self, item): mappedindex = Hub.fanbotMapping[item] - 1 print "Selected fanbot index: %d mapped onto index %d" % (item, mappedindex) if 0 == self.sliderAnimateHub.GetValue(): self.createFanbotBitmap(mappedindex) self.remote.sendFanbotFrame(self.compressedFrame) def showHub(self, hub): """for the given hub, show the pixels in the bitmap, in the color of he hub""" if hub: config = hub.config for i in range(0, len(config)): tuple = hub.getConfigColor(i) if tuple[0] >= 0: x = tuple[0] y = tuple[1] self.bitmap.setPixel(x, y, tuple[2]) def resetHub(self, hub): """for the given hub, make all its pixels gray, and then reset config""" if hub: print "reset hub:", hub.id config = hub.config for i in range(0, len(config)): tuple = hub.getConfigColor(i) if tuple[0] >= 0: x = tuple[0] y = tuple[1] self.bitmap.pixelSetGray(x, y) hub.resetConfig() self.panelModulesCanvas.Refresh() def sliderAnimateHubOnScroll(self, event): speed = self.sliderAnimateHub.GetValue() if speed == 0: self.timerAnimate.Stop() else: self.timerAnimate.Start(250 - speed * 25) def timerAnimateHandler(self, event): """ """ hub = self.currenthub if hub: self.animateIdx += 1 if self.animateIdx >= 24: self.animateIdx = 0 self.createFanbotBitmap(Hub.fanbotMapping[self.animateIdx] - 1) self.remote.sendFanbotFrame(self.compressedFrame) def createHubBitmap(self): hub = self.currenthub maxFrameLen = len(self.compressedFrame) if hub: for i in range(maxFrameLen): self.compressedFrame[i] = 0 for i in range(24): pixelIdx = hub.config[i] if pixelIdx >= 0: byteIdx = pixelIdx / 8 if byteIdx >= maxFrameLen: return bitIdx = pixelIdx % 8 self.compressedFrame[byteIdx] |= 1 << bitIdx def createFanbotBitmap(self, idx): hub = self.currenthub maxFrameLen = len(self.compressedFrame) if hub: for i in range(maxFrameLen): self.compressedFrame[i] = 0 if idx >= 24: return pixelIdx = hub.config[idx] if pixelIdx >= 0: byteIdx = pixelIdx / 8 if byteIdx >= maxFrameLen: return bitIdx = pixelIdx % 8 self.compressedFrame[byteIdx] = 1 << bitIdx
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, 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)
while (sqr(z.x) + sqr(z.y) < max) and (n < iter) do begin t := z; {z^2 + c} z.x := sqr(t.x) - sqr(t.y) + c.x; z.y := 2*t.x*t.y + c.y; Inc(n); end; if n < iter then begin col := n*6 mod 255; PaintBox1.Canvas.Pixels[mx+x,my+y]:=RGBToColor(col,0,0); end;""" size = 511 b = Bitmap(size + 1, size + 1) b.clear() max = 60 iter = 100 c = complex(0.11, -0.66) Mx = My = size // 2 for y in range(-My, My + 1): for x in range(-Mx, Mx + 1): n = 0 z = complex(x * 0.009, y * 0.009) while (z.real**2 + z.imag**2) < max and n < iter: t = z z = complex(pow(t, 2) + c.real, 2 * t + c.imag) n += 1 if n < iter: col = n * 30 % 255 b.setPixel(Mx + x, My + y, (col, 0, 0))
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