Im using tiny ptc and I wondered if anyone knew how to plot filled circles / ovals, using the FeedPixel(x,y,col) method with different heights and widths. Ive been racking my brain cell all day.
Cheers and many thanks,
Clyde.
There is a piece of code on the BR code archieves which plots a circle/eclipse using integer math. It should be fairly easy to convert to FB, there are both a bmx and bb version on the following link:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1477
Hmm seems the site is down. And Thanks man, I'll take a look whens its back online.
Cheers,
Clyde.
The site isn't down, but apparently it doesn't work to link directly to it, so here is the bb version (btw. the code is public domain so free to use/convert)
;Midpoint ellipse algorithm
Graphics 640,480,0,2
Local xCenter% = 320
Local yCenter% = 240
Local Rx%, Ry%
Local p%, px%, py%, x%, y%
Local Rx2%, Ry2%, twoRx2%, twoRy2%
Local pFloat#
Repeat
Cls
WaitEvent()
If MouseDown(1)
xCenter = MouseX()
yCenter = MouseY()
EndIf
Rx = Abs(xCenter - MouseX())
Ry = Abs(yCenter - MouseY())
Rx2 = Rx * Rx
Ry2 = Ry * Ry
twoRx2 = Rx2 Shl 1
twoRy2 = Ry2 Shl 1
msStart = MilliSecs()
;Region 1
x = 0
y = Ry
Plot xCenter + x, yCenter + y
Plot xCenter - x, yCenter + y
Plot xCenter + x, yCenter - y
Plot xCenter - x, yCenter - y
pFloat = (Ry2 - (Rx2 * Ry)) + (0.25 * Rx2)
p = Int(pFloat)
If pFloat Mod 1.0 >= 0.5 Then p = p + 1
px = 0
py = twoRx2 * y
While px < py
x = x + 1
px = px + twoRy2
If p >= 0
y = y - 1
py = py - twoRx2
EndIf
If p < 0 Then p = p + Ry2 + px Else p = p + Ry2 + px - py
Plot xCenter + x, yCenter + y
Plot xCenter - x, yCenter + y
Plot xCenter + x, yCenter - y
Plot xCenter - x, yCenter - y
Wend
;Region 2
pFloat = (Ry2 * (x + 0.5) * (x + 0.5)) + (Rx2 * (y - 1.0) * (y - 1.0)) - (Rx2 * (Float(Ry2)))
p = Int(pFloat)
If pFloat Mod 1.0 >= 0.5 Then p = p + 1
While y > 0
y = y - 1
py = py - twoRx2
If p <= 0
x = x +1
px = px + twoRy2
EndIf
If p > 0 Then p = p + Rx2 - py Else p = p + Rx2 - py + px
Plot xCenter + x, yCenter + y
Plot xCenter - x, yCenter + y
Plot xCenter + x, yCenter - y
Plot xCenter - x, yCenter - y
Wend
timeToDraw = MilliSecs() - msStart
Text 20, 20, Rx + " x " + Ry
Text 20, 30, "Draw time " + timeToDraw + " ms"
Flip(False)
Until KeyHit(1)
Filled circles are a bit harder, this does the trick and would probably be ok for you, it's basically my metaball generation code but I'm sure you can pull out the bits you need.
#Include Once "tinyptc.bi"
option dynamic
If( ptc_open( "METABLOBS", 640, 480 ) = 0 ) Then
End -1
End If
Dim Shared As Integer Buffer( 640 * 480 )
dim as double angle,bangle
DO
radius=99
for z=1 to 99
bangle=360
clv=z
if clv>255 then clv=255
clv=rgb(clv,clv,clv)
for a=1 to 360
x1=(100+(radius*sin(angle*3.1415926535897932/180)))
y1=(100+(radius*cos(angle*3.1415926535897932/180)))
x2=(100+(radius*sin(bangle*3.1415926535897932/180)))
angle=angle+.5
bangle=bangle-.5
for l=x2 to x1
buffer((640*y1)+l)=clv
next
next
radius=radius-1
next
ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""
Basically the Y sinus sorts out the Y co-ordinate
The two X sinus create the points to loop between to fill the circle.
I was feeling mean just posting that snippet...
Here.. I converted it for you..
Slow code; :P
#Include Once "tinyptc.bi"
option dynamic
option explicit
If( ptc_open( "METABLOBS", 640, 480 ) = 0 ) Then
End -1
End If
declare sub dcircle(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
Dim Shared As Integer Buffer( 640 * 480 )
DO
dcircle (320,240,239,&hffffff)
ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""
SUB dCIRCLE(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
DIM as integer a,z,x1,y1,x2,l
dim as double angle,bangle
bangle=360
for a=1 to 1440
x1=(cx+(r*sin(angle*3.1415926535897932/180)))
y1=(cy+(r*cos(angle*3.1415926535897932/180)))
x2=(cx+(r*sin(bangle*3.1415926535897932/180)))
angle=angle+.125
bangle=bangle-.125
for l=x2 to x1
buffer((640*y1)+l)=CLR
next
next
END SUB
Thanks kindly to both of you.
Cheers,
Clyde.
A nice simple Blitz filled circle.
Graphics 640,480,0,2
Repeat
Color Rand(255),Rand(255),Rand(255)
fillcircle(Rand(640),Rand(480),Rand(100))
Until KeyDown(1)
End
Function fillcircle(x%,y%,r%)
r2%=r*r
For h% = -r To r
w% = Sqr(r2-h*h)
Line x-w,y+h , x+w,y+h
Next
End Function
Jim
Thanks,
Clyde.
It would be easy to generate a much faster circle algo than mine in freebasic using Jims code :)
Here, I did it.
All it needs now is a little asm to flat fill the scan lines :)
' Coded By Jim Shaw and Shockwave.
'
' Usage..
' DCIRCLE ( XP , YP , RADIUS , COLOUR )
#Include Once "tinyptc.bi"
option dynamic
option explicit
If( ptc_open( "CIRCLES", 640, 480 ) = 0 ) Then
End -1
End If
declare sub dcircle(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
Dim Shared As Integer Buffer( 640 * 480 )
dim rrx,rry,rrr,rrc
DO
rrx=rnd*(640)
rry=rnd*(480)
rrr=rnd*(250)
rrc=rnd*(255)
dcircle (rrx,rry,rrr,rgb(rrc,rrc,rrc))
ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""
SUB dCIRCLE(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
DIM as integer r2,cc,loopy,ww,l
r2=r*r
cc=-r
for loopy = cc to r
ww = Sqr(r2-loopy*loopy)
for l = CX-ww to CX+ww
if l>0 and l<640 and loopy+CY>0 and loopy+CY<480 then
buffer((640*(loopy+CY))+l)=CLR
end if
next
next
END SUB
Here's a quick hack to show how easy it would be to use this for generating your own bobs :)
' Fast Filled Circle Algo Using Tinyptc.
' Coded By Jim Shaw and Shockwave.
'
' Usage..
' DCIRCLE ( XP , YP , RADIUS , COLOUR )
'
' All it needs now is a little asm tweak to flat shade the scanline for
' ultimate speed.
'
' www.dbfinteractive.com
'
' A Quick hack to show shaded circles..
#define ptc_win
#Include Once "tinyptc.bi"
option static
option explicit
If( ptc_open( "CIRCLES", 640, 480 ) = 0 ) Then
End -1
End If
declare sub dcircle(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
Dim Shared As Integer Buffer( 640 * 480 )
dim rrx,rry,rrr,rrrc,rrgc,rrbc ,zz,rrt,rgt,rbt
DO
rrx=rnd*(640)
rry=rnd*(480)
rrr=20+rnd*(50)
rrrc=rnd*(255)
rrgc=rnd*(255)
rrbc=rnd*(255)
rrt=0
rgt=0
rbt=0
for zz= rrr to 1 step -1
dcircle (rrx,rry,zz,rgb(rrt ,rgt ,rbt))
if rrt<rrrc then rrt=rrt+1
if rgt<rrgc then rgt=rgt+1
if rbt<rrbc then rbt=rbt+1
next
ptc_update @buffer(0)
LOOP UNTIL INKEY$<>""
SUB dCIRCLE(BYVAL CX AS INTEGER , BYVAL CY AS INTEGER , BYVAL R AS INTEGER, BYVAL CLR AS INTEGER)
DIM as integer r2,cc,loopy,ww,l
r2=r*r
cc=-r
for loopy = cc to r
ww = Sqr(r2-loopy*loopy)
for l = CX-ww to CX+ww
if l>0 and l<640 and loopy+CY>0 and loopy+CY<480 then
buffer((640*(loopy+CY))+l)=CLR
end if
next
next
END SUB
Nice stuff Shockwave, if speed is a concern (particularly if you're considering using asm) then it'd be an idea to take the screen bounds checking outside the loops instead of for every pixel.
Cheers fellas.
Quote from: Stonemonkey on July 05, 2006
Nice stuff Shockwave, if speed is a concern (particularly if you're considering using asm) then it'd be an idea to take the screen bounds checking outside the loops instead of for every pixel.
And if in that row, not all the pixels are on the screen, then what? ???
You'd have to calculate how many pixels you're going be drawing in the row, see if it goes out of bounds, if so, at what pixel, then use the for loop below to draw to that last pixel, but I agree, it cuts down the amount of IFs from a couple hundred per line to 1 per line
Thrawn
Hmmmm sorry, I didn't word that quite right. Take the x clipping out of the x loop and take the y clipping out of the y loop.
something like:
y=cy-radius
y_end=cy+radius
if y<0 then y=0
if y_end>screenheight then y_end=screenheight
while y<y_end
Ã, Ã, halfwidth=sqr(radius^2-(cy-y)^2)
Ã, Ã, x=cx-halfwidth
Ã, Ã, x_end=cx+halfwidth
Ã, Ã, if x<0 then x=0
Ã, Ã, if x_end>screenwidth then x_end=screenwidth
Ã, Ã, while x<x_end
Ã, Ã, Ã, Ã, plot(x,y,colour)
Ã, Ã, Ã, Ã, x+=1
Ã, Ã, wend
Ã, Ã, y+=1
wend
although I'd take it a bit further and use pointers to write into memory instead of using plot.
Cool :) I've had some common sense whacked into me! :)
Stonemonkey > :whack: < Shocky
Why stop there and write the whole thing in ASM, you? lol just kidding ;-)
Common sense whacked into you? Hmm looks like it was more like a long, rather deformed, green,...stick that was wacked into you to me....;-)
EDIT:
In hindsight, that should have probally have been left unsaid :o
All I can say is lol. :)
Anyway, what did you want this for Clyde? :) Anything interesting brewing mate?
Yeah, I wanted it for hiding a few messy pixels for an effect that's going to feature in the next Gravity prod.
Thanks to all for their cool as ever advice and help.
Cheers,
Clyde.
Hope it hides 'em adequately, if it's just for masking then you could just pre-calculate it.