Page 2 of 2
Posted: Sat May 02, 2009 2:51 am
by eVAPor8
Kaeru,
The purpose of the "SetOrigin()" I was referring to (from my old Beeb days) was a single-call function to change the location of (0 ,0) from top-left to centre screen (or anywhere else for that matter). All drawing functions thereafter "originate" from the set origin. If you see what mean, So no framework would be necessary.
Which I why I asked the question. The answer seems to be a resounding (and rather disappointing) "No".
It just seems nutty to me that a machine designed and built when a ZX81 or an Acorn Atom was considered affordable home computers had more flexibility than a modern PC with Gigs of RAM and more maths power in a low-end GFX card that NASA had to send man to moon with!
Obviously, as time's passed I've missed a lot!!!
Posted: Sat May 02, 2009 3:10 am
by Kaeru Gaman
The purpose of the "SetOrigin()" I was referring to (from my old Beeb days) was a single-call function to change the location of (0 ,0) from top-left to centre screen (or anywhere else for that matter). All drawing functions thereafter "originate" from the set origin. If you see what mean, So no framework would be necessary.
ermn... no.
the SetOrigin() was part of a "Framework", no matter whether natively implemented or extra loaded.
the Graphic Matrix was a straight Array in Memory.
using a Plot( x, y ) would result in SetPix ( x + y* width ) under the hood, within the "Framework".
SetOrigin( Ox, Oy ) was a single call, but it would just set internal values for later operations.
with that, a Plot( x, y ) will result in some SetPix( ( Ox + x ) + ( Oy - y ) * width ) under the hood.
the subtraction or addition will be there, because it
has to be there, no matter whether you see it or not.
... I did direct graphical access on the C64, wasn't that different from the Sinclair I think ...
Posted: Sat May 02, 2009 3:38 am
by idle
The best you can do is pre calculate as much as you can.
like for instance your points.
here I've pre calculated the ellipse and the cos and sin so all your left with it translation scale and rotation.
Code: Select all
Global Dim arCos.f(360)
Global Dim arSin.f(360)
Global Dim elipse.f(2,360)
Global ct1.i
Procedure drawElipse1(hdc,cx.f,cy.f,sfx.f,sfy.f,majoraxis,minoraxis,orient.i)
Protected dx.f,dy.f,px.i,py.i,cosOrient.f,sinOrient.f,dx1.f,dy1.f,color.i
color = RGB(Random(196)+59,Random(196)+59,Random(196)+59)
;draw elipse
For da = 1 To 500
dx = cx + (Sin(da) * majoraxis) * sfx
dy = cy + (Cos(da) * minoraxis) * sfy
px = cx + (((dx - cx) * Sin(orient))) - (((dy - cy) * Cos(orient)))
py = cy + (((dx - cx) * Cos(orient))) + (((dy - cy) * Sin(orient)))
ct1 + SetPixel_(hdc, px, py,color) & $1
Next
EndProcedure
Procedure drawElipse(hdc,ox.f,oy.f,sfx.f,sfy.f,orient.i)
Protected dx.f,dy.f,px.i,py.i,cosOrient.f,sinOrient.f,dx1.f,dy1.f,color.i
cosOrient = ArCos(orient%360)
sinOrient = ArSin(orient%360)
color = RGB(Random(196)+59,Random(196)+59,Random(196)+59)
;draw elipse
For alpha = 1 To 360
dx = ox + elipse(0,alpha) * sfx ; plot x
dy = oy + elipse(1,alpha) * sfy ; plot y
dx1 = dx - ox
dy1 = dy - oy
px = ox + (dx1 * sinOrient - dy1 * cosorient) ;rotate elipse
py = oy + (dx1 * cosOrient + dy1 * sinorient)
ct1 + SetPixel_(hdc, px, py,color) & $1
;count pixels in bounds
Next
EndProcedure
Procedure draw(*void)
hdc = StartDrawing(WindowOutput(0))
st = GetTickCount_()
For b = 1 To 200
ox = Sin(b/10) * 100 + 400
oy = Cos(b/10) * 100 + 300
For a = 1 To 90 Step 5
drawelipse(hdc,ox,oy,b/100,b/100,a)
Next
Next
et = GetTickCount_() - st
stRes.s = "time to draw " + Str(ct1) + " pixels " + Str(et) + " miliseconds"
ct1 = 0
SetWindowTitle(0,stRes)
SetWinBackgroundColor(WindowID(0),RGB(0,0,0))
st3 = GetTickCount_()
For b = 1 To 200
ox = Sin(b/10) * 100 + 400
oy = Cos(b/10) * 100 + 300
For a = 1 To 90 Step 5
drawelipse1(hdc,ox,oy,b/100,b/100,300,150,a)
Next
Next
et3 = GetTickCount_() - st3
stRes + " normal " + Str(et3)
SetWindowTitle(0,stRes)
st1 = GetTickCount_()
For a = 0 To ct1
ct2 + SetPixel_(hdc,400,300,0) & $1
Next
et1 = GetTickCount_() - st1
stRes + " to just setpixel = " + Str(et1) + " "
SetWindowTitle(0,stRes)
st2 = GetTickCount_()
For a = 0 To ct1
Plot(400,300,0)
ct2 + 1 & $1
Next
et2 = GetTickCount_() - st2
stRes.s + "vs plot " + Str(et2)
SetWindowTitle(0,stRes)
StopDrawing()
EndProcedure
OpenWindow(0,0,0,800,600,"")
SetWinBackgroundColor(WindowID(0),RGB(0,0,0))
;precalculate angles and elipse plots
For a = 0 To 360
ArCos(a)=Cos(a)
ArSin(a)=Sin(a)
elipse(0,a) = ArSin(a) * 300 ;major axis
elipse(1,a) = ArCos(a) * 150 ;minor axis
Next
CreateThread(@draw(),#Null)
Repeat
event = WaitWindowEvent()
Until event = #WM_CLOSE
Posted: Sat May 02, 2009 10:52 am
by eVAPor8
@Kaeru: Do you know I never realised that!!!

I always believed that the screen was simply mapped to that offset... Well, learn something new every day!!!
@idle: Yes, I see what you mean now. When you mentioned "look-up tables" I presumed you meant using linked lists. First Law : Never Assume!
Also the SetWinBackgroundColour throws errors. I think it's a WinSkin funtion only (I'm using 4.30) but commenting the lines gets the code to run.
One other question. Your function seems able to draw outside the window - this causes a RTE when using a Screen. Is this just difference between the two graphics methods?
Thanks again to both of you. It's much appreciated - right now I'm off to do some gardening so I'll check back later on
EDIT: Fixed typo
Posted: Sat May 02, 2009 1:44 pm
by idle
Yes the plot function needs to be checked if its in bounds where as GDI handles setpixel and returns some val if successful or 0 if false, hence why I was counting the ct1 + setpixel() & $1 otherwise the ellipse routines would appear to be faster than the straight iterative test as some of the pixels are off screen.
I guess if your using a screen then there are other things to consider, though I don't really have experience using the 2D / 3D stuff in PB, so don't really know what the best approach would be.
Though how to go about it would really depend upon if you wanted to plot single points as opposed to objects sprites.
Enjoy your Gardening, time for me to count sheep!
Posted: Mon May 04, 2009 7:56 pm
by dagcrack
Heh, it's funny how you guys sidetrack a lot into premature optimization without even realizing what the bottleneck really is...
In the first code posted said bottleneck lies in the SetPixel_() call. You went for a walk and you forgot your legs!.
After a quick (1 minute) profiling session I can tell you the following:
55% of the time was taken by WaitWindowEvent() (which we ignore in this case)
32% was taken by SetPixel
...the rest were the math lines each taking 3%...
So unless we're back in the 60s... All of the above optimizations were pretty much in vain. You were barking on the wrong tree.
Seriously you can preach all you want regarding what's fast and what isn't but you must make sure it applies or else it's just a bunch of big words trying to fit inside a small piece of paper.
Optimize only after you've achieved all of your goals and make sure you optimize the correct code by profiling beforehand.
Cheers.
Posted: Mon May 04, 2009 10:05 pm
by idle
> All of the above optimizations were pretty much in vain. You were barking on the wrong tree.
It's more like barking up the right tree in the wrong forrest!
What do you think your typical graphics lib does?
Cos and sin look ups probably don't achieve to much these days but display lists are used all the time.
So while the question was simply about setting an origin it was illustrative to go on and show the transforms that are required to plot a point.
Posted: Mon May 04, 2009 10:44 pm
by dagcrack
Well... You should focus your time and effort on important matters.
Optimizing what isn't causing you a slowdown seems rather pointless. Plus in this case you could get away with a quadratic curve approximation if you're serious into optimizing that specific portion of code. This will prevent any cache misses and will probably execute faster than your average LUT for that reason.
That said, I'm all for optimization. I just wanted to address the fact that some people fall into the premature optimization trap and they don't seem to snap out of it for some unknown reason... Well, perhaps it releases a few endorphins here and there but aside from that I can't imagine why would anyone want to start optimizing a) the wrong code b) without having a solid, proven base.

Optimizing is usually a sacrifice of readability / portability for speed that in this case isn't worth it. As I mentioned the bottleneck lies in the pixel access. A properly designed bitmap library could easily deal with this in both a transparent and convenient way.
As a side note I think that programmers ought to adapt without too many complaints when it comes to this or that. You can mimic anything but you must always make sure that it is the right way to go. So, within reason you could mimic any system you "miss" but remember: nostalgia is only good for rainy days and 40 year old virgins looking to score in a Battlestar Galactica convention.
Seriously don't ever limit yourself to "what you know", there is always something better to learn and apply.
PS: About the adapting part, also keep in mind that some issues should only take so much of your time -- Prioritize and you shall accomplish your goals!
Posted: Tue May 05, 2009 1:32 am
by eVAPor8
Dagcrack,
No offence or anything but wind your neck in,eh?
You are correct in the topic was not originally about optimisation, it was about readability and yes it got side-tracked... by a lot of useful code and explanation that I for one appreciate and could well help many others browsing the forum. And it's fairly obvious that lovely, readable code is useless if it's too slow to get the job done, so compromises must be made.
As for "optimising the wrong code", it's fairly evident to me at least that replacing the Sin Cos calcs per star per loop is not only more efficient, but also more readable. Oh and since the code has yet to be written, I think your Tardis must be very well maintained.
Just sitting back and bleating "I could do better, 'cos I'm, like, leet
man!" contributes nothing to the subject at hand, throws the thread wildly off-topic and simply paints you as a trolling egotistist.
As for nostalgia (since that seemed to me to be personal slight) I apologise for having a life history...
1. I've just entered my 40's.
You assumed. You were correct.
2. Actually I luuurved Battlestar Galactica.
You assumed. You were correct - Hell, I even designed and build space-fighters out of lego based on the designs. Then I learnt how to plot wireframes from RTFM and photocopied magazines.
3. As far as my sex-life goes... come out with me a pint sometime and I'll teach
YOU a lesson or two, matey, beleive me.
You assumed. You fucked up.
NEVER ASSUME. (See my earlier post on the matter). You just end up making blinding mistakes and looking like an idiot.
I know Fred's going to be pissed at me for flaming back, but I'm not the sort of person to take insults lying down. When the insults are also aimed at people that are trying to help out, teach, and have earned a lot of my respect... It's Both-Barrels time!

Posted: Tue May 05, 2009 2:47 am
by Kaeru Gaman
LOLZ 
I want MOAR!
... btw... I just entered my 40ies, too...
... and I mentioned the bottleneck of display pages ago...
nevermind...
I forgot to link the examples for lookup tables...
this is the newer version by dell_jockey
http://www.purebasic.fr/english/viewtopic.php?t=31272
and this is the root
http://www.purebasic.fr/german/viewtopic.php?t=5884
this with adoption to 4.0
http://www.purebasic.fr/german/viewtopi ... 905#143905
and no matter wich type of bottleneck one choses...
it's always a good idea to but sinuses in lookup-tables when needed frequently...
Posted: Tue May 05, 2009 3:06 am
by idle
I wouldn't worry about DagCracks comments, besides I think they where aimed at me.
I guess I should have responded holy cow Batman (DagCrack) thank you for enlightening us with your powers of deduction.
Just to illustrate a point, math optimizations do matter.
Code: Select all
Global Dim arCos.f(360)
Global Dim arSin.f(360)
Global Dim elipse.f(2,360)
Global ct1.i,ct2.i
Procedure drawElipse1(hdc,ox.f,oy.f,sfx.f,sfy.f,majoraxis,minoraxis,orient.i)
Protected dx.f,dy.f,px.i,py.i,cosOrient.f,sinOrient.f,dx1.f,dy1.f,color.i,alpha.i,theta.i,*px.long
color = RGB(Random(196)+59,Random(196)+59,Random(196)+59)
Pitch = DrawingBufferPitch()
;calculate elipse 10000 plots no short cuts
For alpha = 1 To 10000
theta = alpha % 360
dx = ox + (Sin(theta) * majoraxis) * sfx
dy = oy + (Cos(theta) * minoraxis) * sfy
px = ox + (((dx - ox) * Sin(orient) - ((dy - oy) * Cos(orient)))) ;rotate elipse
py = oy + (((dx - ox) * Cos(orient) + ((dy - oy) * Sin(orient))))
If px >= 0 And py >= 0 And px < 800 And py < 600
*px = hdc + ((px*4 + (py * pitch)))
*px\l = color
ct2+1
EndIf
Next
EndProcedure
Procedure drawElipse(hdc,ox.f,oy.f,sfx.f,sfy.f,orient.i)
Protected dx.f,dy.f,px.i,py.i,cosOrient.f,sinOrient.f,dx1.f,dy1.f,color.i,alpha.i,theta.i, *px.long
cosOrient = ArCos(orient)
sinOrient = ArSin(orient)
color = RGB(Random(196)+59,Random(196)+59,Random(196)+59)
Pitch = DrawingBufferPitch()
;calculates elipse 10000 plots With short cuts
For alpha = 1 To 10000
theta = alpha % 360
dx = ox + elipse(0,theta) * sfx ; plot of x / y from cords 0,0 * scale
dy = oy + elipse(1,theta) * sfy ;
dx1 = dx - ox ; combine distance to origion
dy1 = dy - oy
px = ox + (dx1 * sinOrient - dy1 * cosorient) ;translate and rotate plot x,y
py = oy + (dx1 * cosOrient + dy1 * sinorient)
If px >= 0 And py >= 0 And px < 800 And py < 600
*px = hdc + ((px*4 + (py * pitch)))
*px\l = color
ct1+1 ;count the pixels set
EndIf
Next
EndProcedure
Procedure draw(*void)
;-------------------precalculated elipse--------------------
st = GetTickCount_()
For b = 1 To 200
StartDrawing(ScreenOutput())
hdc= DrawingBuffer()
ox = ArSin(b) * 100 + 400
oy = ArCos(b) * 100 + 300
For a = 1 To 90 Step 5
drawelipse(hdc,ox,oy,b/100,b/100,a)
Next
StopDrawing()
FlipBuffers()
Next
et = GetTickCount_() - st
stRes.s = "time to draw " + Str(ct1) + " pixels " + Str(et) + " miliseconds"
SetWindowTitle(0,stRes)
;============================================================
;-----------------normal parametric elipse-------------------
st3 = GetTickCount_()
For b = 1 To 200
StartDrawing(ScreenOutput())
hdc= DrawingBuffer()
ox = Sin(b) * 100 + 400
oy = Cos(b) * 100 + 300
For a = 1 To 90 Step 5
drawelipse1(hdc,ox,oy,b/100,b/100,300,150,a)
Next
StopDrawing()
FlipBuffers()
Next
et3 = GetTickCount_() - st3
stRes + " normal " + Str(ct2) + " " + Str(et3)
SetWindowTitle(0,stRes)
EndProcedure
tt.TIMECAPS
timeGetDevCaps_(@tt, SizeOf(TIMECAPS))
timeBeginPeriod_(tt\wPeriodMin)
InitSprite()
OpenWindow(0,0,0,800,600,"")
OpenWindowedScreen(WindowID(0),0,0,800,600,0,0,0)
SetWinBackgroundColor(WindowID(0),RGB(0,0,0))
;precalculate angles and elipse plots
For a = 0 To 360
ArCos(a)=Cos(a+1)
ArSin(a)=Sin(a+1)
elipse(0,a) = ArSin(a) * 300 ;major axis
elipse(1,a) = ArCos(a) * 150 ;minor axis
Next
CreateThread(@draw(),#Null)
Repeat
event = WaitWindowEvent()
Until event = #WM_CLOSE
[/code]
Posted: Tue May 05, 2009 10:40 am
by eVAPor8
Thanks for the much-needed injection of good humour guys!
New rule: Never post when dog tired and during a major Sense-Of-Humour Failure!

Posted: Tue May 05, 2009 4:52 pm
by dagcrack
Sigh, Would you read my words 10 times and at least try to comprehend once please?
I gave you a solution if you were so fed up into speeding the trig functions. However, I also gave you a lot of good info and never ever insulted anyone of you at least not in this thread, not now.
For the record I don't play leet, that's just what you perceive and I ought to thank you for that. But the fact that you're always seeing yourself as something inferior can't be good on the long run.
I can assume whatever I want because this is a forum. Anyone can give their opinions and if you don't like them, ignore them. But don't try and force your view on others. I merely pointed out a fact and explained the why.
And yes, I do share code It just happens to be somewhere else where I don't have to cope with make-believe programmers such as you. And since it now became personal I invite you to PM me about it and stop flaming on the forums. Thanks.
@Kaeru Gaman@: Perhaps you're used to filtering through all the noise that lies on each thread in this forum. I'm clearly not since I only pitch in once or twice every few months. Still that doesn't change the fact that you're all focusing on the wrong side of the book and most of the times it just side-tracks to nowhere.
Cheers.
PD: eVAPor8 you still fail to see the point, the bottleneck lies in the pixel access. Lovely readable code is still achievable if you just obtain the bits and map them to an rgb quad structure. But you can only see so much without using a ladder.
Posted: Tue May 05, 2009 5:21 pm
by Kaeru Gaman
why are you keen on playing the big-balls-guy when you did not even read the whole thread?
on Caturday, Kaeru Gaman wrote:the way to display makes the edge between performance and slideshow.
on Windows, Plotting with colorvalue uses DSA.
when not mixing it up with other Draw commands, it's fastest to plot.
but at the end, using tiny Sprite3D stars would be even faster.
and furthermore, every acess of a 2D-Matrix is not very fast since we have 3D Hardware nowadays...
(oh, whoops, already said that on Caturday, too)
for access to a DrawingBuffer you'll need StartDrawing, this alone is already a bottleneck.
when you quote all these out, the sole difference between Plot via DSA and an RGB-structured Pointer is just marginal...
if the latter was faster at all, because it would mean acessing VidMem thru the BUS,
and then a Pointer is not that fast like it would be acessing MainMem.
and hey, making a performance test without proper rewriting and telling the folks that 55% goes into WaitWindowEvent is a lame joke.
kthxbai
Posted: Tue May 05, 2009 6:15 pm
by eVAPor8
Kaeru Gaman wrote:why are you keen on playing the big-balls-guy when you did not even read the whole thread?
BWAHAHAHAHAAA!!!!
ButtCrack wrote:I don't play leet, that's just what you perceive and I ought to thank you for that. But the fact that you're always seeing yourself as something inferior can't be good on the long run.
Shall we add "egotistical rampant hypocrite" to the description for accuracy's sake, Mr "I'm-not_leet-I'm-just-better-than-you-scum"?
The WHOLE POINT of the OP was about easily readable and hackable code. Yes, we got sidetracked (when people are conversing
it happens :roll:)
As Kaeru said, read the entire thread before casting aspersions. The original question was answered and explained so anything after that is some cool code in the public domain for others to learn from.
There been some great code, examples and explanations in this thread -
none of which offered by yourself. I've seen some of your work, and it's pretty outstanding and you're obviously a talented programmer, but just sitting there slating others and saying "I could do better" is lame. Let's see YOUR ideas and explanation.
Basically:
Put up or shut up.
Oh and as for inferior? Well, TBH mateyboy, I tend to find that people who need to become Interweb Keyboard Warriors to feel good about themselves are in dire need of help.