#!/usr/bin/python2 from math import sin, cos from sdl2 import SDL_QUIT, SDL_MOUSEMOTION, SDL_MOUSEWHEEL import sdl2.ext as sdl2ext from sys import stdout import time BLACK = sdl2ext.Color(0, 0, 0) WHITE = sdl2ext.Color(255, 255, 255) sdl2ext.init() CanvasWidth = 800 CanvasHeight = 600 win = sdl2ext.Window("PySDL2 test", size=(CanvasWidth, CanvasHeight)) win.show() winsurf = win.get_surface() def line(x0, y0, x1, y1): #print "x0:{} y0:{} x1:{} y1:{}".format(x0, y0, x1, y1) """draw a line http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm""" #sdl2ext.fill(winsurf, BLACK) pixelview = sdl2ext.PixelView(winsurf) #pixelview[event.motion.y][event.motion.x] = WHITE # dont draw put of screen # this check should be in "while true" loop but for some reason it # didn't work there x0 = 0 if x0 < 0 else x0 x0 = CanvasWidth -1 if x0 >= CanvasWidth else x0 x1 = 0 if x1 < 0 else x1 x1 = CanvasWidth -1 if x1 >= CanvasWidth else x1 y0 = 0 if y0 < 0 else y0 y0 = CanvasHeight -1 if y0 >= CanvasHeight else y0 y1 = 0 if y1 < 0 else y1 y1 = CanvasHeight -1 if y1 >= CanvasHeight else y1 dx = abs(x1-x0) dy = abs(y1-y0) sx = 1 if (x0 < x1) else -1 sy = 1 if (y0 < y1) else -1 err = dx-dy while True: pixelview[y0][x0] = WHITE if x0 == x1 and y0 == y1: break e2 = 2*err if e2 > -dy: err = err - dy x0 = x0 + sx if x0 == x1 and y0 == y1: pixelview[y0][x0] = WHITE break if e2 < dx: err = err + dx y0 =y0 + sy del pixelview def draw_box(CameraPos = {"x": 0, "y": 0, "z": -15}, CameraRot = {"x": 0, "y": 0, "z": 0}): """Draws a rotating box, CameraRot variable is presistant if nobody outside this function doesn't touch it http://www.cores2.com/3D_Tutorial/""" sdl2ext.fill(winsurf, BLACK) #fill screen with black # draw a 2D box #box={"x0":100,"y0":100, "x1":200, "y1":200} #line(box["x0"], box["y0"], box["x0"], box["y1"]) #line(box["x0"], box["y0"], box["x1"], box["y0"]) #line(box["x1"], box["y1"], box["x0"], box["y1"]) #line(box["x1"], box["y1"], box["x1"], box["y0"]) # our 3D model CubeVertex = [ {"x":-1, "y":-1, "z":1}, {"x":-1, "y":1, "z":1}, {"x":1, "y":1, "z":1}, {"x":1, "y":-1, "z":1}, {"x":-1, "y":-1, "z":-1}, {"x":-1, "y":1, "z":-1}, {"x":1, "y":1, "z":-1}, {"x":1, "y":-1, "z":-1}, ] CubeEdges = [ {"i":0, "j":1}, {"i":1, "j":2}, {"i":2, "j":3}, {"i":3, "j":0}, {"i":4, "j":5}, {"i":5, "j":6}, {"i":6, "j":7}, {"i":7, "j":4}, {"i":0, "j":4}, {"i":1, "j":5}, {"i":2, "j":6}, {"i":3, "j":7}, ] #CameraPos = {"x": 0, "y": 0, "z": -10}; #CameraRot = {"x": 0, "y": 0, "z": 0}; RatioConst = 320 CenterX = CanvasWidth / 2 CenterY = CanvasHeight / 2 #Rotate camera CameraRot["x"] += 0.02 CameraRot["y"] += 0.02 CameraRot["z"] += 0.02 PointList = [] for ccv in CubeVertex: WorkingVertex = { "x":ccv["x"], "y":ccv["y"], "z":ccv["z"] } Temp = WorkingVertex["z"] WorkingVertex["z"] = -WorkingVertex["x"] * sin(CameraRot["y"]) - WorkingVertex["z"] * cos(CameraRot["y"]) WorkingVertex["x"] = -WorkingVertex["x"] * cos(CameraRot["y"]) + Temp * sin(CameraRot["y"]) Temp = WorkingVertex["z"] WorkingVertex["z"] = -WorkingVertex["y"] * sin(CameraRot["x"]) + WorkingVertex["z"] * cos(CameraRot["x"]) WorkingVertex["y"] = WorkingVertex["y"] * cos(CameraRot["x"]) + Temp * sin(CameraRot["x"]) Temp = WorkingVertex["x"] WorkingVertex["x"] = WorkingVertex["x"] * cos(CameraRot["z"]) - WorkingVertex["y"] * sin(CameraRot["z"]) WorkingVertex["y"] = WorkingVertex["y"] * cos(CameraRot["z"]) + Temp * sin(CameraRot["z"]) WorkingVertex["x"] -= CameraPos["x"]; WorkingVertex["y"] -= CameraPos["y"]; WorkingVertex["z"] -= CameraPos["z"]; # Convert from x,y,z to x,y # This is called a projection transform # We are projecting from 3D back to 2D ScreenX = (RatioConst * (WorkingVertex["x"])) / WorkingVertex["z"]; ScreenY = (RatioConst * (WorkingVertex["y"])) / WorkingVertex["z"]; # Save this on-screen position to render the line locations PointList.append({"x":int(CenterX + ScreenX), "y":int(CenterY + ScreenY)}) for cce in CubeEdges: # Find the two points we are working on Point1 = PointList[cce["i"]]; Point2 = PointList[cce["j"]]; # Render the edge by looking up our vertex list line(Point1["x"], Point1["y"], Point2["x"], Point2["y"]); draw_box() running = True lastm=(0,0) #last mouse position CameraPos = {"x": 0, "y": 0, "z": -5} CameraRot = {"x": 0, "y": 0, "z": 0} print "hold down mouse button to move camera" print "use scroll wheel to change how far camera is" fps=0 while running: t = time.time() events = sdl2ext.get_events() for event in events: if event.type == SDL_QUIT: running = False break if event.type == SDL_MOUSEMOTION: if event.motion.state == 1:# 1st mouse button is down # paint a line #line(lastm[0], lastm[1], event.motion.x, event.motion.y) # change camera pos mouse_sens = 50.0 # mouse sensitivity CameraPos["x"] = (event.motion.x - CanvasHeight / 2)/ mouse_sens CameraPos["y"] = (event.motion.y - CanvasWidth / 2)/ mouse_sens lastm=event.motion.x, event.motion.y else: #no buttons pressed lastm=event.motion.x, event.motion.y elif event.type == SDL_MOUSEWHEEL: # change how far camera is CameraPos["z"] += event.motion.x print "fps:", fps, " CameraPos:", CameraPos, "\r", stdout.flush() draw_box(CameraPos=CameraPos) win.refresh() fps = 1000 / int((time.time() - t)*1000) sdl2ext.quit() print # make a empty line