Code archives/Graphics/Polygon

This code has been declared by its author to be Public Domain code.

Download source code

Polygon by skidracer2002
Draws Triangles and Quads
; poly.bb
; by simon@acid.co.nz

Dim xval(20)
Dim yval(20)

Graphics 640,480
Color 255,0,255

Triangle 50,0,80,20,30,20

WaitKey
End

Function Triangle(x0,y0,x1,y1,x2,y2)
	xval(0)=x0
	yval(0)=y0
	xval(1)=x1
	yval(1)=y1
	xval(2)=x2
	yval(2)=y2
	poly(3)
End Function

Function Quad(x0,y0,x1,y1,x2,y2,x3,y3)
	xval(0)=x0
	yval(0)=y0
	xval(1)=x1
	yval(1)=y1
	xval(2)=x2
	yval(2)=y2
	xval(3)=x3
	yval(3)=y3
	poly(4)
End Function

Function poly(vcount)
; get clipping region
	width=GraphicsWidth()
	height=GraphicsHeight()
; find top verticy
	b=vcount-1
	y=yval(0)
	While c<>b
		c=c+1
		yy=yval(c)
		If yy<y y=yy d=c
	Wend
	c=d 
	t=c
; draw top to bottom
	While y<height
; get left gradient
		If y=yval(c)
			While y=yval(c)
				x0=xval(c) Shl 16
				c=c+1
				If c>b c=a
				If c=t Return
				If y>yval(c) Return
			Wend
			h=yval(c)-y
			g0=((xval(c) Shl 16)-x0)/h
		EndIf
; get right gradient
		If y=yval(d)
			While y=yval(d)
				x1=xval(d) Shl 16
				d=d-1
				If d<a d=b
				If y>yval(d) Return
			Wend
			h=yval(d)-y
			g1=((xval(d) Shl 16)-x1)/h
		EndIf
; calc horizontal span
		x=x1 Sar 16
		w=((x0 Sar 16)-x)+1
; draw down to next vert
		If (w>0 And y>-1 And x<width And x+w>0)
			If x<0 w=w+x x=0	;crop left
			If x+w>width w=width-x	;crop right
			Rect x,y,w,1
		EndIf
; next	
		x0=x0+g0
		x1=x1+g1
		y=y+1
	Wend
End Function

Comments

sswift2004
I optimized Simon's code a while back and didn't think to post it till now...

My version of the function is about 4x faster than Simon's, and it's all because Rect is slower than Writepixelfast when doing lots of little horizontal lines. With writepixelfast, I can lock the buffer once before I draw the triangle, whereas with rect it has to lock and unlock the buffer every call.


; poly.bb
; by simon@...
; fastpoly by sswift

Dim xval(20)
Dim yval(20)

Graphics 640,480,16

SetBuffer BackBuffer()

Color 255,0,255

T1 = MilliSecs()
For Loop = 0 To 1000
	Triangle(-10,-10, 180,20, 230,220)
Next
T2 = MilliSecs()


T3 = MilliSecs()
For Loop = 0 To 1000
	FastTriangle(-10,-10, 180,20, 230,220)
Next
T4 = MilliSecs()


Color 255,255,255
Text 16, 16, T2-T1
Text 16, 32, T4-T3


Flip
WaitKey
End



Function Triangle(x0,y0,x1,y1,x2,y2)
	xval(0)=x0
	yval(0)=y0
	xval(1)=x1
	yval(1)=y1
	xval(2)=x2
	yval(2)=y2
	poly(3)
End Function

Function FastTriangle(x0,y0,x1,y1,x2,y2)
	xval(0)=x0
	yval(0)=y0
	xval(1)=x1
	yval(1)=y1
	xval(2)=x2
	yval(2)=y2
	FastPoly(3)
End Function

Function Quad(x0,y0,x1,y1,x2,y2,x3,y3)
	xval(0)=x0
	yval(0)=y0
	xval(1)=x1
	yval(1)=y1
	xval(2)=x2
	yval(2)=y2
	xval(3)=x3
	yval(3)=y3
	poly(4)
End Function

Function poly(vcount)

; get clipping region
	width=GraphicsWidth()
	height=GraphicsHeight()
; find top verticy
	b=vcount-1
	y=yval(0)
	While c<>b
		c=c+1
		yy=yval(c)
		If yy<y y=yy d=c
	Wend
	c=d 
	t=c
; draw top to bottom
	While y<height
; get left gradient
		If y=yval(c)
			While y=yval(c)
				x0=xval(c) Shl 16
				c=c+1
				If c>b c=a
				If c=t Return
				If y>yval(c) Return
			Wend
			h=yval(c)-y
			g0=((xval(c) Shl 16)-x0)/h
		EndIf
; get right gradient
		If y=yval(d)
			While y=yval(d)
				x1=xval(d) Shl 16
				d=d-1
				If d<a d=b
				If y>yval(d) Return
			Wend
			h=yval(d)-y
			g1=((xval(d) Shl 16)-x1)/h
		EndIf
; calc horizontal span
		x=x1 Sar 16
		w=((x0 Sar 16)-x)+1
; draw down to next vert
		If (w>0 And y>-1 And x<width And x+w>0)
			If x<0 w=w+x x=0	;crop left
			If x+w>width w=width-x	;crop right
			Rect x,y,w,1
		EndIf
; next	
		x0=x0+g0
		x1=x1+g1
		y=y+1
	Wend
End Function



Function FastPoly(vcount)

	RGBColor = ColorBlue() Or (ColorGreen() Shl 8) Or (ColorRed() Shl 16) Or ($ff000000)

	; get clipping region
	width=GraphicsWidth()
	height=GraphicsHeight()
	
	; Lock the current drawing buffer.
	LockBuffer()
	
	; find top verticy
	b=vcount-1
	y=yval(0)
	While c<>b
		c=c+1
		yy=yval(c)
		If yy<y y=yy d=c
	Wend
	c=d 
	t=c

	; draw top to bottom
	While y<height
		
		; get left gradient
		If y=yval(c)
			While y=yval(c)
				x0=xval(c) Shl 16
				c=c+1
				If c>b c=a
				If c=t Goto Finish
				If y>yval(c) Goto Finish
			Wend
			h=yval(c)-y
			g0=((xval(c) Shl 16)-x0)/h
		EndIf

		; get right gradient
		If y=yval(d)
			While y=yval(d)
				x1=xval(d) Shl 16
				d=d-1
				If d<a d=b
				If y>yval(d) Goto Finish
			Wend
			h=yval(d)-y
			g1=((xval(d) Shl 16)-x1)/h
		EndIf

		; calc horizontal span
		x=x1 Sar 16
		w=((x0 Sar 16)-x)+1

		; draw down to next vert
		If (w > 0) And (y > -1) And (x < width) And ((x+w) > 0)
	
			;crop left
			If x < 0 
				w=w+x
				x=0		
			EndIf
			
			;crop right
			If (x+w) > width
				w=width-x
			EndIf	
			
			; Draw scanline.
			For Lx = x To (x+w)
				WritePixelFast Lx, y, RGBColor
			Next
			
		EndIf
		
		; next	
		x0=x0+g0
		x1=x1+g1
		y=y+1
		
	Wend

	.Finish
	
	; Unlock the draw buffer.
	UnlockBuffer()
	
End Function



DJWoodgate2004
Strange then how yours seems about 4 times slower here. But that may be because I have an old machine; slow CPU, Slow AGP bus, stuff done by the GPU is going to be faster I suppose.


sswift2004
Yeah that is strange.

soemone posted a version on the forums today which uses line... Simon and I didn't use line because it was slower than rect. But this fellow discovered that you can call lockbuffer before calling line, and line will still work and it will be nearly as fast as my version is on my PC. I suspect that line would be fast for your system as well. Faster than rect even. So perhaps it is worth a tiny speed loss to make the funciton 4x faster on older CPU's. So try my version of the function, that has the lockbuffer stuff, but replace the writepixel loop with a line command instead.


skidracer2004
If you are targetting the backbuffer Rects avoid any locking whatsoever, if you are drawing to textures the writepixel operation may be faster on some cards, although a simple optimization with the Rect version maybe to Lock the buffer anyway which I assume will avoid Blitz locking and unlocking with each call of Rect(). I'm on Linux this week so won't get distracted trying it out...


starfox2004
The bad thing about this is that you have to declare the points moving in clockwise direction.

Other than that, its fast and good


Code Archives Forum