Triangles

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Triangles

Post by Tourist Trap »

That's fast.
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: Triangles

Post by Tourist Trap »

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.
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 ;) )

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
(simply 2 triangles melted in 1 thin rectangle here)

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
Post Reply