A.D.A. Amiga Demoscene Archive

        Welcome guest!

  

  

  

log in with SceneID

  

Demos Amiga Demoscene Archive Forum / Coding / coding tutorial: general questions
 Page:  ««  1  2  3  4  5  6  7  8  »» 
Author Message
z5_
Member
#1 - Posted: 30 Jun 2007 23:14
Reply Quote
thanks for the explanation, Stingray. The mistake i made was thinking that mulu took 2 cycles on all processors. However, if you are targetting an 68060, then mulu would actually be as fast or faster than the 3 instructions replacing it, so it seems.
z5_
Member
#2 - Posted: 30 Jun 2007 23:21
Reply Quote
On to another question. I had a routine working (nearly finished what i was aiming for) but at some point it stopped working. Not finding the cause, i stripped it down again to this:

moveq #0,d0
lea screen,a0
lea screen+320*10,a1
moveq #2,d7
.next_pixel
add.w d0,a0
add.w d0,a1
move.b (a0),(a1)
addq.w #1,d0
dbra d7,.next_pixel

I thought that this would copy 3 pixels horizontal (chunky screen) to line 10. It does copy 2 pixels with one black in between.

Honestly, i don't see it... i really don't.
Kalms
Member
#3 - Posted: 30 Jun 2007 23:58
Reply Quote
z5:

What happens if you run this for 100 iterations?

On the first iteration, a0 & a1 will advance 0 bytes before copying a pixel.
On the second iteration, a0 & a1 will advance 1 bytes before copying a pixel.
On the third iteration, a0 & a1 will advance 2 bytes before copying a pixel.
On the fourth, ...

The code will gradually make larger and larger steps between each pixel-copy.

What you want is to have a0 & a1 always advance _1 byte_, *after* copying a pixel.

Either:
.next_pixel
move.b (a0,d0.l),(a1,d0.l)
addq.l #1,d0
dbra d7,.next_pixel


or:
.next_pixel
move.b (a0),(a1)
addq.l #1,a0
addq.l #1,a1
dbra.d7,.next_pixel


or just:
.next_pixel
move.b (a0)+,(a1)+
dbra d7,.next_pixel
z5_
Member
#4 - Posted: 1 Jul 2007 00:37
Reply Quote
At first, i had move.b (a0,d0.l),(a1,d1.l) (in the "effect", i'm manipulating d1 in relation to d0). When that stopped working, i stripped it down to the move.b (a0),(a1). However, my add.w error has always been there so i don't understand how it worked until some point.

I do get the error... it's sooo obvious...
z5_
Member
#5 - Posted: 4 Jul 2007 20:27 - Edited
Reply Quote
Suppose i've got a dot on screen at position x,y (starting from 0,0 in upper left corner).

I want to move this dot along a circle path. What is the best way to calculate the y-value for each x.

I still remember: r^2= x^2 + y^2, which means that y would be the square root of r^2 - x^2.

However, i associate square roots with floating point (after comma) numbers. Another way would probably be to calculate with sinus or cosinus (i should look up the formula for that though... it's been too long to remember). Again, sinus and cosinus are all associated with after comma numbers in my mind. So i'm not exactly sure how i could tackle this.
Kalms
Member
#6 - Posted: 4 Jul 2007 22:18
Reply Quote
If you want to draw exactly one dot per horizontal line, then:

[circle is specified as (x0, y0, r)]

for y = y0 - r to y0 + r
  sqr_dx = sqrt(r^2 - (y - y0)^2)
  left_x = x0 - sqr_dx
  right_x = x0 + sqr_dx
  putpixel(y, left_x)
  putpixel(y, right_x)


That code is easy to convert into one which draws a filled circle (you just replace the two putpixels with code that renders a horizontal line).


... but you probably want to draw a non-filled circle where the perimeter is contiguous. You have two better choices then:

1) plot a lot of pixels centered around (x0, y0) at distance (r), with varying angle. Use sin/cos to get the coordinates.

or

2) use bresenham's circle drawing algorithm.

Option 1 is less work but it will still either give gaps or ugly circles.

If you are to do any sin/cos style calculations, you utilize fixed point: you've pre-multiplied any decimal numbers with 65536 (or some other suitable factor), so you make sure that all the values which you add/sub to your pre-scaled numbers have the same pre-scaling, and just before you need a real pixel coordinate, you shift down to get rid of the fractional bits.
You'll need a table with sin/cos values. Generate it somehow, or find an existing one, and utilize that.
z5_
Member
#7 - Posted: 4 Jul 2007 22:43 - Edited
Reply Quote
Thanks kalms. The idea was actually to draw only one point that makes a circle movement. There used to be some scrollers doing that (i think in megademo 8 / kefrens and some others). Then i was to replace the moving dot with something else. So i was mainly interested in the coords for each x. I already have a bresenham circle routine so i will try to use this as a starting point.

But i don't think i will be able to avoid sinus tables forever :o)
winden
Member
#8 - Posted: 4 Jul 2007 23:06
Reply Quote
rom issue 1, article by touchstone/essence on circle drawing
Kalms
Member
#9 - Posted: 4 Jul 2007 23:37
Reply Quote
z5: oops. yes, if you just want to animate a single dot, and you want to move it with a constant speed, then your best bet is to go with sin/cos.
z5_
Member
#10 - Posted: 5 Jul 2007 21:05
Reply Quote
rom issue 1, article by touchstone/essence on circle drawing

Winden, there is no circle draw routine in rom 1. I checked. it's probably in another issue (those tutorials by touchstone do seem interesting though).

yes, if you just want to animate a single dot, and you want to move it with a constant speed, then your best bet is to go with sin/cos.


Seems i can't avoid sinus tables / calculations anymore... Does anyone have a sinus/cosinus table for download.

As a starting point, am i right in assuming that:
- sinus table = table with sinus values going from one angle to another (0 to 360 seems logical) but angle in radians for more precise (smaller) steps? All values probably multiplied by the same value to avoid comma numbers (seeing that sinus is between -1 and 1)
- sinus table = are the radians included in a sinus table? And do you have to interpolate + search?
- circle movement: achieved by going from 0 -> 360 ° (in radians for smaller steps) (so input = angle + radius) and calculation of both x and y using cos = x/r and sin = y/r in which case i should need a cos table aswell

Anyone know of a good tutorial?
noname
Member
#11 - Posted: 5 Jul 2007 23:18
Reply Quote
ASM-One has a built in create sinus table function. I can't remember how to use it but you can find it in the ASM-One docs.
Kalms
Member
#12 - Posted: 5 Jul 2007 23:54
Reply Quote
Radians is just an alternative scale instead of degrees.

When using the sinus table in code, you will probably want to have a sinus table with 256, 512 or 1024 values for one full period (one period = 360 degrees = 2PI radians). Let's say that you go with a table that has 1024 entries; the difference in angle between two consecutive entries in the table will then be (360/1024) degrees, or (2*PI/1024) radians.

Your sine table will contain values multiplied by a constant, indeed. If you have all values multiplied by 16384, then you can use 16/32-bit maths without having to fear overflow all the time.

If you are using pure integer calculations, you will probably represent your angles in something else than degrees. One useful unit would be: 1024 = one full period (since this is the resolution of your sine table). Another useful unit is: 65536 = one full period.

When you have an angle (a), the sine table is useful for calculating sin(a). Just lookup the entry at position (a) in the table, that's the sine value you are looking for. If your angle values have higher precision than your sine table (i.e. angles are measured in 1/65536ths, but your sine table has only 1024 entries), then you *can* interpolate between neighboring values in the sine table to get a more accurate value. You won't need that for your current demo-effects, though.

cos-table: either you have an extra cos-table, or you use the identity:
cos(a degrees) = sin(a + 90 degrees)
This can be accomplished by having a sine-table which contains 1.25 periods, and having the base-pointer for cosine lookups point 0.25 periods into the table.

For instance, for the 1024 entries case, the sine table should have 1280 words, and the cos-table begins 256 words into the sine table.

Before you do all this in code, you should look at a picture of a sine and a cosine wave. (get out your old maths book, or google a bit.) Familiarize yourself with what the contents of the tables should look like, roughly.
StingRay
Member
#13 - Posted: 7 Jul 2007 16:50
Reply Quote
ASM-One has a built in create sinus table function. I can't remember how to use it but you can find it in the ASM-One docs.

it's rather simple to use (and a pretty nifty Asm-One/Pro feature :D)
type "IS" (I.nsert S.inus) in the commandline and you will get some prompts:

BEG> -your starting angle, e.g. 0
END> -end angle, e.g. 360
AMOUNT> -number of values for your table, e.g. 1024
AMPLITUDE> -max. height of your curve, e.g. 256
YOFFSET> -offset adder
SIZE (B/W/L)>choose between byte/word/longword sized values for your tab
MULTIPLIER> the multiplier, e.g. 1<<14
HALF CORRECTION> no idea, i guess it changes the rounding approach
ROUND CORRECTION> same as above, I always use y/y here :)

and that's all you need to create a sinetable in Asm1. :)
Blueberry
Member
#14 - Posted: 9 Jul 2007 01:20
Reply Quote
Another way to put it is that the i'th number in your table will get the value

MULTIPLIER * (YOFFSET + round(AMPLITUDE * sin(BEG + (i + HC) * (END - BEG) / AMOUNT)))

where HC is 0.5 if HALF CORRECTION is on and 0 otherwise, and round() rounds to nearest if ROUND CORRECTION is on and towards zero (bad) otherwise.

As you see, the MULTIPLIER is multiplied on the rounded result. This is useful whenever you are multiplying the value by some constant anyway, for instance for vertical screen offsets.

A different version of the command is CS (create sinus) which takes a destination address as first parameter and otherwise the same as IS. This is very conveniently used with the AUTO directive, so you simply write in your source:

auto cs\SinusTable\0\360\1024\256\0\b1\ny

There are no backslashes after the SIZE and CORRECTION parameters because these do not need you to press enter.

This way, the definition of your sinus takes up just the space declaration and the auto statement in your source. And you can change the parameters of your sinus just by changing the values in the auto statement.
StingRay
Member
#15 - Posted: 9 Jul 2007 17:44
Reply Quote
Thanks Blueberry, apparently HC/RC indeed do what I expected. :) And CS is indeed very useful, I often use it in exactly the way you described. :)
z5_
Member
#16 - Posted: 7 Aug 2007 20:34
Reply Quote
Damn, i don't dare starting on sine stuff... there goes my still young scene career...
korruptor
Member
#17 - Posted: 8 Aug 2007 14:44
Reply Quote
Sine's your friend man. You gotta play about with it, there're loads of fun bits you can do :D
z5_
Member
#18 - Posted: 8 Aug 2007 16:50
Reply Quote
Sine's your friend man. You gotta play about with it, there're loads of fun bits you can do :D

I remember you doing a sine scroller in the past, so you already got it behind you :o)

Still hope we will see some release coming from you btw, korruptor :o)
korruptor
Member
#19 - Posted: 9 Aug 2007 14:39
Reply Quote
Christ, I'd love to do something but I've hit a wall where I've got sod all time to battle through things. Really annoying, as I was just getting to grips with stuff thanks to everyone's help and pointers... :(

I've started on a simple game to force myself to have some proper structure to my code and write things with an eye to reusing them but there's not much to show atm :(
z5_
Member
#20 - Posted: 9 Aug 2007 23:05
Reply Quote
A game... doh, Korruptor :o)

Fuck multimedia, make more demos (as quoted from the nice Synergy/Sector 7 demo)

In any case, hoping for a bit more free time for you and maybe, just maybe, someday an actual release. I was under the impression that you were making good progress.
michael phipps
Member
#21 - Posted: 22 Aug 2007 18:04
Reply Quote
Here is the code on how to clear the screen in Asm-One using the CPU:-

Lea screen,a0+(40*256)*6,a0 ;40 bytes across screen * 256 scanlines down
;* 6 bitplanes!!! For decending clear!
Movem.l screen_mem(pc),d0-a6/a1-a4 ;clear all d0-a4 registers!
Moveq.l #6-1,d7 ;number of bitplanes -1 for counter!
Clear_loop:
Rept 256 ;number of scanlines down.
Movem.l d0-d6/a1-a4,-(a0) ;clear 40 bytes
Endr
Dbf,d7,clear_loop
Rts

Screen_mem ds.l 10 ;10 dc.l's!!!
Screen ds.b (40*256)*6 ;no.bytes across*no.scanlines * no.bitplanes


Here is how to clear the screen using the BLITTER! (My favourite chip hehehe..)

Lea screen,a0
Lea $dff000,a6 ;Points Amiga's Hardware registers!

Moveq.l #6-1,d7 ;number of bitplanes * 6
Clear_loop:
Move.w #$0100,bltcon0(a6) ;blt control0
Move.w #$0000,bltcon1(a6) ;blt control1
Move.w #$ffff,bltfwm(a6)
Move.w #$ffff,bltlwm(a6)
Move.w #20*256+40,bltsize(a6) ;clear screen width in words * scanlines + no.bytes
Dbf,clear_loop
Rts
michael phipps
Member
#22 - Posted: 22 Aug 2007 19:19
Reply Quote
Oooops...good job i checked but forgot to add this instruction inside Blitter Clear Routine insert it after clear loop hehehe...

move.l a0,bltapt(a6)
korruptor
Member
#23 - Posted: 24 Aug 2007 12:09
Reply Quote
Which is better on a stock A500? Clearing with Blitter or CPU? I'm guessing blitter?

I'm trying to write my little game for the A500, but with a load of bobs flying about I'm worried that I'm limiting how much I'll get on screen if I just use blitter clears?
z5_
Member
#24 - Posted: 24 Aug 2007 18:07
Reply Quote
Which is better on a stock A500? Clearing with Blitter or CPU? I'm guessing blitter?

@korruptor: i seem to remember (vaguely) somebody writing on this forum about clearing part of the screen with the blitter while clearing the other part with the cpu, both possible at the same time? Don't ask me more because i don't know. Somebody with more knowledge will hopefully shed more light on this.
z5_
Member
#25 - Posted: 24 Aug 2007 18:19 - Edited
Reply Quote
In the meantime, i have another question in between korruptor's.

So far, i have never managed to get smooth movement, even from the simplest of cases. Imagine that i draw a rectangle at the screen and move it in horizontal direction. The way i do it:
- clear my rectangular area
- add 1 to my x coord
- draw a new rectangle
-...

Something along the lines of this (chunky 320*200 screen), rectangle 12x12, starting at line 100:

lea screen+320*100,a0
add.w pa4_1_x(pc),a0

moveq #12-1,d7
.pa4_1_clr_line
rept 12
move.b #0,(a0)+
endr
add.w #320-12,a0
dbra d7,.pa4_1_clr_line

addq.w #1,pa4_1_x
lea screen+320*100,a0
add.w pa4_1_x(pc),a0

moveq #12-1,d7
.pa4_1_draw_line
rept 12
move.b #6,(a0)+
endr
add.w #320-12,a0
dbra d7,.pa4_1_draw_line
rts

(again, please don't mind the code... it is a fast written example).

In the mainloop, i clear a vbi_counter and wait until it's value is 2 (the vbi counter is augmented in my vbi routine). If 2, then i execute my routine, clear my vbi counter,...

When i look at my rectangle going from left to right, sometimes it is as part of the rectangle is one pixel behind. It's as if "lagging behind".

What could be the reasone for this. And what exactly makes the eye see a smooth movement?

One possible reason i just thought about: that i am changing the contents of my screen while it is already in the process of being drawn on screen at that point. However, from the little i know about double buffering, that should not be possible (and wickedos uses double or even triple buffering).
Kalms
Member
#26 - Posted: 25 Aug 2007 21:10
Reply Quote
z5,

if you are observing how one portion (either upper or lower) sometimes is lagging behind, that is caused by one out of two things:

1) the display hardware is switching which buffer it is displaying data from mid-frame. (That means, someone's writing to BPLxPT registers when the screen has just been displayed halfway.) This is not very likely to be happening in your case.
2) someone is rendering to the buffer that is currently being displayed.

So, this is probably due to some interaction between the demosystem's double/triple buffering and the C2P. Put up a complete example program (including demosystem) that exhibits this behaviour and we'll give it a look.


Regarding "smooth movement" in general: if you are doing 2D animation, you will need to be double-buffering. If you are double buffering, and your code takes roughly the same amount of time (say, 35 milliseconds), then every rendered frame will be displayed for the same number of 50Hz frames.
If you would choose to do triple buffering, each rendered frame would instead be displayed for (say, 2-2-2-1-2-2-2-1-... 50Hz frames). This will make the animation jittery.

The biggest problem with double buffering is that it is really obvious when the rendering code temporarily taking an extra frame (then the framerate drops from 50 -> 25 > 16.7 -> 12.5fps etc). One way around this is to time the worst-case scenario on the target machine, and artificially lock your frame rate to the lowest framerate.

Triple buffering makes framerate transitions much less noticeable. It is useful for 3D scenes. We always do plain double buffering in our demos though.
Toffeeman
Member
#27 - Posted: 26 Aug 2007 10:48
Reply Quote
@korruptor:

Z5 is correct clearing half the screen with the CPU and half with the Blitter is the quickest way.

If I'm not using the Blitter for much else then I setup a triple buffer one each for the Blitter, display hardware and the CPU. Then you can switch off Blitter priority and you get your screen cleared almost for free :0) Basically update the Blitter pointers and hit go.

As you are using the Blitter to draw your bobs you have to wait for the Blitter to finish clearing the screen first so if the CPU is sitting there just waiting for the Blitter to finish you might as well get it to help out clearing the screen. For the absolute best performance you might want to get the Blitter to clear more memory than the CPU but you would need to test which work load is the most optimal.
michael phipps
Member
#28 - Posted: 27 Aug 2007 11:47
Reply Quote
Hiya Guy's!!!

Sorryz for having a little break on here as i've had some personal business to take care of but i'm back in full effect now hehehe... btw i will answer all your questions regarding CPU vs BLITTER to korruptor, z5_, & kalms!!! Let me just have my breakfast first then i 'll write a nice little article on here for ya, how about that?! See ya l8r!!!
z5_
Member
#29 - Posted: 27 Aug 2007 12:14
Reply Quote
btw i will answer all your questions regarding CPU vs BLITTER to korruptor, z5_, & kalms!!!

@michael:
I'd like to see you answering questions from kalms (he hasn't asked any anyway)... i think you'll have to be in good shape for that :o) (you know... kalms... coder of starstruck, silkcut, ocean machine and tons of splendid top of the range demos...)

@kalms:
So, this is probably due to some interaction between the demosystem's double/triple buffering and the C2P. Put up a complete example program (including demosystem) that exhibits this behaviour and we'll give it a look.

As i don't want to waist your time, i'll wait until i have something which might lead to an actual release (which is not at all certain at this point). Until then, i'll accept it as is but there is definately something going on that i don't understand. Thanks for the offer!
michael phipps
Member
#30 - Posted: 27 Aug 2007 19:37
Reply Quote
@z5_

Sorry for not writing sooner as I was busy on E-Bay & managed to win a cool A1200 for £20.00!!! Not bad eh?! Right let's get down to business! In response to your question about me being in good shape, what do you mean? did you check out my GET-TOUGH! Demo you sent me yet??? & after this, you still doubt my capabilities... lol!!! Okey then here's more evidence for you to check out my article on CPU vs BLITTER!

@korruptor

In my view, if you have just a standard A500 machine, then the BLITTER is the best weapon at clearing the screen in real-time without using too much raster-time being that the BLITTER Chip is approx twice as fast as the CPU. In regards to the A1200 though I think they made it about the same speed as the CPU, not sure. If you want to know how to clear the screen using the blitter&CPU for four bitplanes, here is my example for you:-

• CPU part

Moveq #0,d0
Move.l d0,d1
Move.l d0,d2
Move.l d0,d3
Move.l d0,d4
Move.l d0,d5
Move.l d0,d6
Move.l d0,a1
Move.l d0,a2
Move.l d0,a3
Move.l d0,a4
Move.l d0,a5
Move.l d0,a6
Lea screen(pc),a0
Lea 40*256*2(a0),a0 ;point to bottom of first two bitplanes for descending clear
Moveq #2-1,d7 ;clear first two bitplanes –1 for counter!
Cpu_clear_loop
Rept 256
Movem.l d0-d6/a1-a4,-(a0)
Endr
Dbf d7,cpu_clear_loop

Lea screen(pc),a0
Lea 40*256*2(a0),a0 ;point to next two bitplanes!!!
Lea $dff000,a6

* The Blitter part

move #2-1,d7 d7 ;clear next two bitplanes –1 for counter!
blit_clear_loop:
move.l a0,apt(a6)
move.l a0,dpt(a6)
move.w #$0100,bltcon0(a6)
move.w #$0000,bltcon1(a6)
move.w #$ffff,bltfwm(a6)
move.w #$ffff,bltlwm(a6)
move.w #20*256+40,bltsize(a6)
lea 40*256(a0),a0 ;point to next screen bitplane!!!
dbf d7,blit_clear_loop
rts

By the way this code is only useful you are trying to create several Bobs on the screen using the Blitter & things like glenz vectors that demand line-drawing and filling, routines etc... hope this helps!
 Page:  ««  1  2  3  4  5  6  7  8  »» 

  Please log in to comment

  

  

  

 

A.D.A. Amiga Demoscene Archive, Version 3.0