Exemple #1
0
class Render:
	def __init__(self,width,height):
		self.globalLight = 0.45
		self.accelerate = True

		self.width = width
		self.height = height

		# world
		self.world = World()
		self.world.setCube()
		#self.world.setTest()

		# Viewport Transformation
		nx = self.width  # number of x in screen
		ny = self.height # number of y in screen
		self.Tvp = ViewportTransformation(nx,ny)

		# Camera Transformation
		self.viewDist = 200
		self.Tcam = CamaraTransformation(self.viewDist)

		# Perspective Projection
		self.Tper = PerspectiveProjection(l=-100,r=100,b=-100,t=100,n=-100,f=-300)

		# background
		self.backgound = Color(255,255,255)
		self.lineColor = Color(0,0,0)

	def toggleAccelerate(self):
		self.accelerate = not self.accelerate

	def changeViewDist(self,deltaViewDist):
		newViewDist = self.viewDist + deltaViewDist
		if newViewDist < 142 or newViewDist > 1000:
			return
		self.viewDist = newViewDist
		self.Tcam = CamaraTransformation(self.viewDist)

	def naiveDrawLine(self,window,p,q):
		# see https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
		x0,y0 = p
		x1,y1 = q

		if x0 > x1:
			p,q = q,p
			x0,y0 = p
			x1,y1 = q
		# x0 <= x1
		x0,y0,x1,y1 = int(x0),int(y0),int(x1),int(y1)

		dx = abs(x1-x0)
		dy = abs(y1-y0)
		if x0 < x1: 
			sx = 1 
		else:
			sx = -1
		if y0 < y1:
			sy = 1
		else:
			sy = -1
		err = dx-dy

		while True:
			p = [x0,y0]
			pygame.draw.line(window,self.lineColor,p,p)

			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:
				p = [x0,y0]
				pygame.draw.line(window,self.lineColor,p,p)
				break
			if e2 < dx:
				err = err + dx
				y0 = y0 + sy



	def drawLine(self,window,p,q):
		if self.accelerate:
			pygame.draw.aaline(window,self.lineColor,p,q, 2)
		else:
			self.naiveDrawLine(window,p,q)

	def naiveDrawPolygon(self,window,color,pointList):
		if len(pointList) > 3:
			self.naiveDrawPolygon(window,color,pointList[:3])
			self.naiveDrawPolygon(window,color,[pointList[0]]+pointList[2:])
			return

		x1,y1 = pointList[0][0], pointList[0][1]
		x2,y2 = pointList[1][0], pointList[1][1]
		x3,y3 = pointList[2][0], pointList[2][1]

		x2,y2 = x2-x1, y2-y1
		x3,y3 = x3-x1, y3-y1
		if x2*y3 - x3*y2 > 0:
			pointList[2],pointList[1] = pointList[1], pointList[2]


		#print(pointList)
		x1,y1 = pointList[0][0], pointList[0][1]
		x2,y2 = pointList[1][0], pointList[1][1]
		x3,y3 = pointList[2][0], pointList[2][1]
		minx = int(min(x1,x2,x3))
		maxx = int(max(x1,x2,x3))
		miny = int(min(y1,y2,y3))
		maxy = int(max(y1,y2,y3))

		for x in range(minx,maxx+1):
			for y in range(miny,maxy+1):
				if (x1 - x2) * (y - y1) - (y1 - y2) * (x - x1) >= 0 and \
					(x2 - x3) * (y - y2) - (y2 - y3) * (x - x2) >= 0 and \
					(x3 - x1) * (y - y3) - (y3 - y1) * (x - x3) >= 0:
					p = [x,y]
					pygame.draw.line(window,color,p,p)


	def drawPolygon(self,window,color,pointList):
		if self.accelerate:
			pygame.draw.polygon( window, color, pointList )
		else:
			self.naiveDrawPolygon( window, color, pointList )

	def draw(self,window):
		window.fill( self.backgound )		

		shapes = self.world.geometryObjects
		shapes.sort(key=lambda t:-t.getDist(matrix([0,0,self.viewDist]).transpose()))

		M = self.Tvp.M*self.Tper.M*self.Tcam.M
		
		for shape in shapes:

			pointList = []
			for a in shape.vertices:
				ext_a = vstack([a.coordinate,[1]])
				p = M * ext_a
				px, py = p[0]/p[3], p[1]/p[3]
				pointList.append( [int(px),self.height-int(py)] )
			
			# calculate color
			n1 = shape.vertices[1].coordinate - shape.vertices[0].coordinate
			n2 = shape.vertices[2].coordinate - shape.vertices[0].coordinate
			n = cross(n1.transpose(),n2.transpose()).transpose()
			n = n / linalg.norm(n)
			p = matrix([0,0,self.viewDist]).transpose()
			p = p / linalg.norm(p)
			colorScale = 1.0-abs(linalg.norm( cross(n.transpose(),p.transpose()) ))
			colorScale = self.globalLight+(1-self.globalLight)*colorScale
			color = Color( int(shape.color.r*colorScale), int(shape.color.g*colorScale), int(shape.color.b*colorScale) ) 

			self.drawPolygon( window, color, pointList )

			lines = shape.getLines();
			for line in lines:
				a, b = line[0], line[1]
				ext_a = vstack([a.coordinate,[1]])
				ext_b = vstack([b.coordinate,[1]])
				p = M * ext_a
				q = M * ext_b
				px, py = p[0]/p[3], p[1]/p[3]
				qx, qy = q[0]/q[3], q[1]/q[3]

				self.drawLine(window,[px,self.height-py],[qx,self.height-qy])