Mark's circles wtf

Started by meems, February 13, 2018, 10:22:10

Previous topic - Next topic

meems

so i always thought Mark Sibly was a great programmer. But even the best make a few errors.
I couldn't understand how he had such a slow circle oval draw function in blitz. So I went his blitzplus github page. And by golly, what a monster function. wtf was he thinking? Most of his functions are concise, but this one, he really went into an unnecessary myriad of protracted thinking and ideas just to draw a circle.

No wonder blitzers wrote their own circle and oval functions. I'm no high tier programmer, but I got my own blitzplus circle function running at 70~100 times faster than Mark's, using just 8 lines of simple code, w/o using writepixelfast.
If anyone gets a chance to talk to him, ask him about his circles wtf.


void BBGrDriver2D::oval( int x1,int y1,int w,int h,bool solid ){

BBRect dest(x1,y1,x1+w,y1+h);
if( !clipRect().clip( &dest ) ) return;

float xr=w*.5f,yr=h*.5f,ar=(float)w/(float)h;
float cx=x1+xr+.5f,cy=y1+yr-.5f,rsq=yr*yr,y;

if( solid ){
y=dest.top-cy;
for( int t=dest.top;t<dest.bottom;++y,++t ){
float x=(float)sqrt( rsq-y*y )*ar;
int xa=(int)floor( cx-x ),xb=(int)floor( cx+x );
rect( xa,t,xb-xa,1,true );
}
return;
}

int l,r,p_xa,p_xb,t,hh=(int)floor(cy);

p_xa=p_xb=(int)cx;
t=dest.top;y=t-cy;
if( dest.top>y1 ){ --t;--y; }
for( ;t<=hh;++y,++t ){
float x=(float)sqrt( rsq-y*y )*ar;
int xa=(int)floor( cx-x ),xb=(int)floor( cx+x );

l=xa;r=p_xa;if(r<=l)r=l+1;
rect( l,t,r-l,1,true );
l=p_xb;r=xb;if(l>=r)l=r-1;
rect( l,t,r-l,1,true );

p_xa=xa;p_xb=xb;
}

p_xa=p_xb=(int)cx;
t=dest.bottom-1;y=t-cy;
if( dest.bottom<y1+h ){ ++t;++y; }
for( ;t>hh;--y,--t ){
float x=(float)sqrt( rsq-y*y )*ar;
int xa=(int)floor( cx-x ),xb=(int)floor( cx+x );

l=xa;r=p_xa;if(r<=l)r=l+1;
rect( l,t,r-l,1,true );
l=p_xb;r=xb;if(l>=r)l=r-1;
rect( l,t,r-l,1,true );

p_xa=xa;p_xb=xb;
}
}

meems

>just 8 lines of simple code
And on re-examine I see it can be 7 lines of simple code :)

ENAY

I don't think Mark has ever been a man of Math. Besides who uses oval in their games anyway? :)

TomToad

Don't have the time to look real close, but it appears that most of that code is dealing with ovals at the edge of the screen.  You can't just simply shrink the bounding rectangle to the clipping plane or else your ovals will be squashed. 
------------------------------------------------
8 rabbits equals 1 rabbyte.

meems

#4
@TomToad my circle code can draw over the edge of screen, writepixel implicitly handles attempts to draw out-of-bounds.

>Besides who uses oval in their games anyway?
I like the mario4 , looneytoons style of screen flip, which was circles-to-black in and out, so I had them in my games. Circles are also useful for games with bubbles, like underwater games.

Derron

I assume "write pixel" is slower than "drawrect" (dozen of plots versus a single fill operation instruction).

Without having a deeper look at the code (or yours) using less draw calls is to prefer. Dunno if "draw line" was possible there too - but usage of "rect()" alone seems to say that there was some kind of optimization done. "rect" is a untextured quad, a line surely a connection of plots.


@ Faster
What did you measure? FPS or "function execution time" ? Depending on your GPU/driver-stack the work is done on "flip" rather than "draw".

bye
Ron



meems

>seems to say that there was some kind of optimization done.
>some kind of optimization

Yes, a shit one.

I measured mine against Mark's in function execution time. For screenbuffer flip, Flip 0 was used.

Derron


Steve Elliott

Mark has written several computer languages - including one with a built-in 3D Engine.  Yet you sneer at one routine he wrote and say you can do better, but didn't post your version.

Hmm.  How many Computer Languages/3D Engines have you written then?  And of course they all contain perfect code.
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

Derron

@ Steve
Meems already started his thread with praise - and he wonders how it comes that such a mind as MS wrote this function. One could express this in a nicer way but the core is: if there are more efficient variants around there, why has MS written it the way it is now.




bye
Ron

Steve Elliott

#10
Fair point Derron, I was more reacting to the "Yes, a shit one." regards optimisation.  The tone is one of I can do much better.

But in a large project, anybody can let some unefficient code slip through.
Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

meems

#11
Quote from: Derron on February 14, 2018, 13:26:40
So where is yours?
I'm so glad you asked!  :D
Behold, a modest genius's finely crafted exhibit!


Function my_circle(x,y,r,col=222+(222 Shl 8)+(222 Shl 16))

x2#=r
y2#=0
n=r*6.29  ; if gaps in circle then increase this number, but should be ok

For i=0 To n
WritePixel x+x2,y+y2,col
x2=x2-y2/r
y2=y2+x2/r
Next

End Function


Actually, back in the blitzforum days, I saw others write their own circle and oval functions. We never got to the point of testing against each other to see whose was the fastest and most versatile. But some of us noobs were surprised we could beat Mark, and it made us feel like leet programmers for a moment.

Steve Elliott

Win11 64Gb 12th Gen Intel i9 12900K 3.2Ghz Nvidia RTX 3070Ti 8Gb
Win11 16Gb 12th Gen Intel i5 12450H 2Ghz Nvidia RTX 2050 8Gb
Win11  Pro 8Gb Celeron Intel UHD Graphics 600
Win10/Linux Mint 16Gb 4th Gen Intel i5 4570 3.2GHz, Nvidia GeForce GTX 1050 2Gb
macOS 32Gb Apple M2Max
pi5 8Gb
Spectrum Next 2Mb

Derron

Hmm, somehow I cannot use your function to do a solid circle - or even a non-solid oval?




bye
Ron

meems

#14
it doesn't do solids. try a loop like


function solid_circle(x,y,r)

for i=1 to r
my_circle(x,y,i)
next

end function

interesting to see if this is faster than Mark's