Triangles
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Triangles
That's fast.
-
- Posts: 2958
- Joined: Jun 02, 2015 16:24
Re: Triangles
I adapted your code (with also Joshy's tweaks) to make it draw a laser line. Can I use it in my game project dear friend? ( edit: so I guess I can ;) )Stonemonkey wrote:Over time my triangle code has slowly evolved, this is it's current state. I want to change it to fixed point but my attempts so far haven't been totally successful with some errors in the resuilts.
Code: Select all
type vertex
as single x,y,r,g,b
end type
type triangle
as vertex ptr v0,v1,v2
end type
type edge
as single x,e,r,g,b,dx,de,dr,dg,db
end type
type gfx_buffer
as integer w,h,b,p
as ulong ptr pixels
end type
dim shared as gfx_buffer ptr buffer
sub gtriangle(byval tri as triangle ptr)
dim as edge edge=any
dim as edge scan=any
dim as single d1=any,d2=any
dim as vertex ptr v0=tri->v0
dim as vertex ptr v1=tri->v1
dim as vertex ptr v2=tri->v2
if v1->y<v0->y then swap v1,v0
if v2->y<v0->y then swap v2,v0
if v2->y<v1->y then swap v2,v1
d1=1.0/(v2->y-v0->y)
edge.dx=(v2->x-v0->x)*d1
edge.dr=(v2->r-v0->r)*d1
edge.dg=(v2->g-v0->g)*d1
edge.db=(v2->b-v0->b)*d1
d1=v1->y-v0->y
edge.de=(v1->x-v0->x)/d1
d2=1.0 /(v1->x-(v0->x+d1*edge.dx))
scan.dr=(v1->r-(v0->r+d1*edge.dr))*d2
scan.dg=(v1->g-(v0->g+d1*edge.dg))*d2
scan.db=(v1->b-(v0->b+d1*edge.db))*d2
dim as single ptr xl=@edge.x,xr=@edge.e
if edge.dx>edge.de then swap xl,xr
dim as integer y_start=v0->y-0.4999
if y_start<0 then y_start=0
dim as integer y_end=v1->y-0.4999
if y_end>=buffer->h then y_end=buffer->h-1
dim as integer y_fin=v2->y-0.4999
if y_fin>=buffer->h then y_fin=buffer->h-1
d1=y_start-v0->y
edge.x=v0->x+edge.dx*d1
edge.e=v0->x+edge.de*d1
edge.r=v0->r+edge.dr*d1
edge.g=v0->g+edge.dg*d1
edge.b=v0->b+edge.db*d1
while (y_start<=y_fin)
while (y_start<=y_end)
dim as integer x_start=*xl-0.4999
if x_start<0 then x_start=0
dim as integer x_end =*xr-0.4999
if x_end>=buffer->w then x_end=buffer->w-1
d1=x_start-edge.x
dim as single r=edge.r+scan.dr*d1
dim as single g=edge.g+scan.dg*d1
dim as single b=edge.b+scan.db*d1
dim as ulong ptr p_start=buffer->pixels+x_start+y_start*buffer->p
dim as ulong ptr p_end =buffer->pixels+x_end +y_start*buffer->p
while (p_start<=p_end)
*p_start=(r shl 16) or (g shl 8) or b
r+=scan.dr
g+=scan.dg
b+=scan.db
p_start+=1
wend
edge.x+=edge.dx
edge.e+=edge.de
edge.r+=edge.dr
edge.g+=edge.dg
edge.b+=edge.db
y_start+=1
wend
if y_start<=y_fin then
y_end=y_fin
edge.de=(v2->x-v1->x)/(v2->y-v1->y)
d1=y_start-v2->y
edge.e=v2->x+edge.de*d1
end if
wend
end sub
screenres 800,600,32,2
screenset 1,0
buffer=new gfx_buffer
screeninfo _
buffer->w, _ ' width
buffer->h,, _ ' height
buffer->b, _ ' bytes
buffer->p ' pitch
buffer->pixels=screenptr()
' bytes to pixels
buffer->p shr=2
dim as triangle ptr tri= new triangle
dim as triangle ptr tri2= new triangle
tri->v0 = new vertex
tri->v1 = new vertex
tri->v2 = new vertex
tri2->v0 = new vertex
tri2->v1 = new vertex
tri2->v2 = new vertex
tri->v0->r=255 : tri->v0->g=155 : tri->v0->b=55
tri->v1->r=255 : tri->v1->g=155 : tri->v1->b=55
tri->v2->r=255 : tri->v2->g=155 : tri->v2->b=55
tri2->v0->r=255 : tri2->v0->g=55 : tri2->v0->b=55
tri2->v1->r=255 : tri2->v1->g=55 : tri2->v1->b=55
tri2->v2->r=255 : tri2->v2->g=55 : tri2->v2->b=55
randomize TIMER
dim as integer frames,fps
dim as double tStart=timer()
while inkey<>chr(27)
'for i as integer=0 to 9
line (0,0)-step(buffer->w-1,buffer->h-1),0,BF
tri->v0->x=buffer->w/2
tri->v0->y=buffer->h/2
tri->v1->x=-buffer->w/2+rnd*buffer->w*2
tri->v1->y=-buffer->h/2+rnd*buffer->h*2
dim as single a = tri->v1->x - tri->v0->x
dim as single b = tri->v1->y - tri->v0->y
tri->v2->x= tri->v0->x - 2*b/sqr(a^2 + b^2)
tri->v2->y= tri->v0->y + 2*a/sqr(a^2 + b^2)
tri2->v0->x= tri->v0->x - 2*b/sqr(a^2 + b^2)
tri2->v0->y= tri->v0->y + 2*a/sqr(a^2 + b^2)
tri2->v1->x= tri->v1->x - 2*b/sqr(a^2 + b^2)
tri2->v1->y= tri->v1->y + 2*a/sqr(a^2 + b^2)
tri2->v2->x= tri->v1->x
tri2->v2->y= tri->v1->y
gtriangle(tri)
gtriangle(tri2)
draw string (0,0),"fps: " & fps
frames+=1
if frames mod 100=0 then
dim as double tNow = timer()
fps=100/(tNow-tStart)
tStart=tNow
tri->v0->r=rnd*255 : tri->v0->g=rnd*255 : tri->v0->b=rnd*255
tri->v1->r=rnd*255 : tri->v1->g=rnd*255 : tri->v1->b=rnd*255
tri->v2->r=rnd*255 : tri->v2->g=rnd*255 : tri->v2->b=rnd*255
end if
'next
flip
sleep 400
wend
More demonstrative this way:
Code: Select all
type vertex
as single x,y,r,g,b
end type
type triangle
as vertex ptr v0,v1,v2
end type
type edge
as single x,e,r,g,b,dx,de,dr,dg,db
end type
type gfx_buffer
as integer w,h,b,p
as ulong ptr pixels
end type
dim shared as gfx_buffer ptr buffer
sub gtriangle(byval tri as triangle ptr)
dim as edge edge=any
dim as edge scan=any
dim as single d1=any,d2=any
dim as vertex ptr v0=tri->v0
dim as vertex ptr v1=tri->v1
dim as vertex ptr v2=tri->v2
if v1->y<v0->y then swap v1,v0
if v2->y<v0->y then swap v2,v0
if v2->y<v1->y then swap v2,v1
d1=1.0/(v2->y-v0->y)
edge.dx=(v2->x-v0->x)*d1
edge.dr=(v2->r-v0->r)*d1
edge.dg=(v2->g-v0->g)*d1
edge.db=(v2->b-v0->b)*d1
d1=v1->y-v0->y
edge.de=(v1->x-v0->x)/d1
d2=1.0 /(v1->x-(v0->x+d1*edge.dx))
scan.dr=(v1->r-(v0->r+d1*edge.dr))*d2
scan.dg=(v1->g-(v0->g+d1*edge.dg))*d2
scan.db=(v1->b-(v0->b+d1*edge.db))*d2
dim as single ptr xl=@edge.x,xr=@edge.e
if edge.dx>edge.de then swap xl,xr
dim as integer y_start=v0->y-0.4999
if y_start<0 then y_start=0
dim as integer y_end=v1->y-0.4999
if y_end>=buffer->h then y_end=buffer->h-1
dim as integer y_fin=v2->y-0.4999
if y_fin>=buffer->h then y_fin=buffer->h-1
d1=y_start-v0->y
edge.x=v0->x+edge.dx*d1
edge.e=v0->x+edge.de*d1
edge.r=v0->r+edge.dr*d1
edge.g=v0->g+edge.dg*d1
edge.b=v0->b+edge.db*d1
while (y_start<=y_fin)
while (y_start<=y_end)
dim as integer x_start=*xl-0.4999
if x_start<0 then x_start=0
dim as integer x_end =*xr-0.4999
if x_end>=buffer->w then x_end=buffer->w-1
d1=x_start-edge.x
dim as single r=edge.r+scan.dr*d1
dim as single g=edge.g+scan.dg*d1
dim as single b=edge.b+scan.db*d1
dim as ulong ptr p_start=buffer->pixels+x_start+y_start*buffer->p
dim as ulong ptr p_end =buffer->pixels+x_end +y_start*buffer->p
while (p_start<=p_end)
*p_start=(r shl 16) or (g shl 8) or b
r+=scan.dr
g+=scan.dg
b+=scan.db
p_start+=1
wend
edge.x+=edge.dx
edge.e+=edge.de
edge.r+=edge.dr
edge.g+=edge.dg
edge.b+=edge.db
y_start+=1
wend
if y_start<=y_fin then
y_end=y_fin
edge.de=(v2->x-v1->x)/(v2->y-v1->y)
d1=y_start-v2->y
edge.e=v2->x+edge.de*d1
end if
wend
end sub
screenres 800,600,32,2
screenset 1,0
buffer=new gfx_buffer
screeninfo _
buffer->w, _ ' width
buffer->h,, _ ' height
buffer->b, _ ' bytes
buffer->p ' pitch
buffer->pixels=screenptr()
' bytes to pixels
buffer->p shr=2
dim as triangle ptr tri= new triangle
dim as triangle ptr tri2= new triangle
tri->v0 = new vertex
tri->v1 = new vertex
tri->v2 = new vertex
tri2->v0 = new vertex
tri2->v1 = new vertex
tri2->v2 = new vertex
tri->v0->r=255 : tri->v0->g=155 : tri->v0->b=55
tri->v1->r=255 : tri->v1->g=155 : tri->v1->b=55
tri->v2->r=255 : tri->v2->g=155 : tri->v2->b=55
tri2->v0->r=255 : tri2->v0->g=105 : tri2->v0->b=55
tri2->v1->r=255 : tri2->v1->g=105 : tri2->v1->b=55
tri2->v2->r=255 : tri2->v2->g=105 : tri2->v2->b=55
randomize TIMER
dim as integer frames,fps
dim as double tStart=timer()
dim as integer radius = 200
dim as single angle = 100
while inkey<>chr(27)
angle += .0001
'for i as integer=0 to 9
line (0,0)-step(buffer->w-1,buffer->h-1),0,BF
tri->v0->x=buffer->w/2
tri->v0->y=buffer->h/2
tri->v1->x=tri->v0->x + radius*cos(angle)
tri->v1->y=tri->v0->y + radius*sin(angle)
dim as single a = tri->v1->x - tri->v0->x
dim as single b = tri->v1->y - tri->v0->y
tri->v2->x= tri->v0->x - 2*b/sqr(a^2 + b^2)
tri->v2->y= tri->v0->y + 2*a/sqr(a^2 + b^2)
tri2->v0->x= tri->v0->x - 2*b/sqr(a^2 + b^2)
tri2->v0->y= tri->v0->y + 2*a/sqr(a^2 + b^2)
tri2->v1->x= tri->v1->x - 2*b/sqr(a^2 + b^2)
tri2->v1->y= tri->v1->y + 2*a/sqr(a^2 + b^2)
tri2->v2->x= tri->v1->x
tri2->v2->y= tri->v1->y
gtriangle(tri)
gtriangle(tri2)
draw string (0,0),"fps: " & fps
frames+=1
if frames mod 100=0 then
dim as double tNow = timer()
fps=100/(tNow-tStart)
tStart=tNow
tri->v0->r=255 : tri->v0->g=55 : tri->v0->b=rnd*255
tri->v1->r=255 : tri->v1->g=55 : tri->v1->b=55
tri->v2->r=255 : tri->v2->g=55 : tri->v2->b=55
end if
'next
flip
wend