Omnimaga

Calculator Community => HP Calculators => HP Prime => Topic started by: MacBernick on January 15, 2014, 09:18:39 am

Title: Fast filled circles routine
Post by: MacBernick on January 15, 2014, 09:18:39 am
After a discussion an another thread about filled circles, I made a little program using FILLPOLY_P to simulate a fillled circle. It was really slow because of the use of a FOR loop to make a list of coordinates to feed the FILLPOLY function. One day Han told me it would be more efficient to call MAKELIST for building lists, so I modified it a bit, and this is now REALLY faster :)

You can push the attached program in your calc or the simulator, run "circles" for a quick demo drawing random circles on screen at a nice speed, or use the EXPORTed FILLCIRCLE_P(centerX, centerY, radius, color) function in your program.

You can also copy/past the function in your program if you want to use it but don't want to rely on an external lib.

NB : these are not perfect circles, they are not suitable for mathematics purposes. Also, very small circle may look weird.

Enjoy
Title: Re: Fast filled circles routine
Post by: Han on January 15, 2014, 09:56:33 am
I have even gone as far as replacing loops with either a makelist or makemat (double loop) even if I'm not generating lists or matrices. Simply create a procedural function that returns garbage data and don't store the resulting list or matrix. Have the procedural function do what you would normally do in a loop.
Code: [Select]
mainprogram()
begin
  makemat(prg(I,J),25,25);
end;

prg(x,y)
begin
  // code that loops x from 1 to 25 and y from 1 to 25 goes here
  return(0);
end;

I don't remember if the speed difference is still significant ever since the most recent firmware (never retested).
Title: Re: Fast filled circles routine
Post by: bb010g on January 15, 2014, 10:00:23 am
If they just throw away the outputs as they go instead of making a list and throwing it away, then that's nice; we just got speedy effectual mapping.
Title: Re: Fast filled circles routine
Post by: MacBernick on January 15, 2014, 10:02:49 am
Yeah that's clever. FOR loops deprecated ? ^^
Title: Re: Fast filled circles routine
Post by: DJ Omnimaga on January 15, 2014, 06:56:08 pm
Very good work :D
Title: Re: Fast filled circles routine
Post by: bb010g on January 15, 2014, 09:43:17 pm
Actually, couldn't you just do
Code: [Select]
mainprogram()
begin
  makemat(
    // code that loops x from 1 to 25 and y from 1 to 25 goes here
    return(0);
  ,25,25);
end;
if the code was short enough?
Title: Re: Fast filled circles routine
Post by: MacBernick on January 15, 2014, 10:01:26 pm
I'm not sure MAKEMAT would support multiple statements. Did you try it ?

I replaced the two FOR loops in render routine in Trailblazer by a MAKEELIST, that's about 3 or 4 FPS earned.

If I got it right, only a Home variable can be used with MAKELIST ?
Title: Re: Fast filled circles routine
Post by: Han on January 15, 2014, 10:15:17 pm
Actually, couldn't you just do
Code: [Select]
mainprogram()
begin
  makemat(
    // code that loops x from 1 to 25 and y from 1 to 25 goes here
    return(0);
  ,25,25);
end;
if the code was short enough?

Not really. They only way it could be short enough is if it were a single "command" (i.e. built-in command or procedural function created either in the same source file or made available via export). If your code requires more than a single semicolon, then I am pretty sure it won't work (though I never tried myself) because the arguments of makelist or makemat must be comma-separated.
Title: Re: Fast filled circles routine
Post by: bb010g on January 15, 2014, 11:34:34 pm
Han: Confirmed; from Home 'MAKEMAT(PRINT(I); PRINT(J); RETURN 0,25,25)' fails syntax checking with the cursor positioned right before the first ";". Also, I've had problems with 'MAKELIST(MAKELIST(X,X,1,10),X,1,10)' passing the syntax check but presently failing with 'Error: Bad argument type'.
Title: Re: Fast filled circles routine
Post by: DJ Omnimaga on June 16, 2014, 12:23:35 am
Necrobump:

Thanks to this routine, we can actually do circle-based fade-in/out animations, like in Zelda, in addition to stuff like dark cavern/dungeon effects! :D

(http://img.ourl.ca/circlefadeout.gif)


The edited code by MacBernick looks like this:

Code: [Select]
FILLCIRCLE_P(cx, cy, r, color);

EXPORT circles()
BEGIN
DIMGROB_P(G1,320,240);
DIMGROB_P(G2,320,240);
DIMGROB_P(G3,320,240);
BLIT_P(G1,G0);
FOR A FROM 220 DOWNTO 0 DO
      RECT_P(G2,#000000);
      FILLCIRCLE_P(160, 120, A, #FF00FF);
BLIT_P(G3,G1);
BLIT_P(G3,0,0,320,240,G2,0,0,320,240,#FF00FF);
BLIT_P(G3);
END;
END;



EXPORT FILLCIRCLE_P(cx, cy, r, color)
BEGIN
   LOCAL s, cl := {}, angle := HAngle;
   HAngle := 1;

   LOCAL cl :=
      MAKELIST({EVAL(r * COS(S) + cx), EVAL(r * SIN(S) + cy)},
         S, 0, 359, 10);

   HAngle := angle;
   FILLPOLY_P(G2,cl, #FF00FF,255);
END;


You need multiple GROBs or at least a GROB large enough for each frame, because it involves transparency.
Title: Re: Fast filled circles routine
Post by: bb010g on June 16, 2014, 01:22:35 am
Necrobump:

Thanks to this routine, we can actually do circle-based fade-in/out animations, like in Zelda, in addition to stuff like dark cavern/dungeon effects! :D

(http://img.ourl.ca/circlefadeout.gif)


The edited code by MacBernick looks like this:

Code: [Select]
FILLCIRCLE_P(cx, cy, r, color);

EXPORT circles()
BEGIN
DIMGROB_P(G1,320,240);
DIMGROB_P(G2,320,240);
DIMGROB_P(G3,320,240);
BLIT_P(G1,G0);
FOR A FROM 220 DOWNTO 0 DO
      RECT_P(G2,#000000);
      FILLCIRCLE_P(160, 120, A, #FF00FF);
BLIT_P(G3,G1);
BLIT_P(G3,0,0,320,240,G2,0,0,320,240,#FF00FF);
BLIT_P(G3);
END;
END;



EXPORT FILLCIRCLE_P(cx, cy, r, color)
BEGIN
   LOCAL s, cl := {}, angle := HAngle;
   HAngle := 1;

   LOCAL cl :=
      MAKELIST({EVAL(r * COS(S) + cx), EVAL(r * SIN(S) + cy)},
         S, 0, 359, 10);

   HAngle := angle;
   FILLPOLY_P(G2,cl, #FF00FF,255);
END;


You need multiple GROBs or at least a GROB large enough for each frame, because it involves transparency.
Why the EVALs? Also, angle should be a pragma.
Title: Re: Fast filled circles routine
Post by: DJ Omnimaga on June 16, 2014, 11:22:29 am
Not sure what the evals do and about the Angle, nor why it prompts me for which program to run at startup. I just took MacBernick code at http://www.omnimaga.org/hp-prime/fast-filled-circles-routine/?action=post;quote=373410;last_msg=386862 and replaced both colors and the FILLCIRCLE arguments so that the circle is always centered. Then I added DIMGROB/BLIT commands for the effect.
Title: Re: Fast filled circles routine
Post by: pimathbrainiac on June 16, 2014, 11:23:33 am
Every time I see cool stuff for the prime, it makes me wish my parents let me buy one...

Nice job!
Title: Re: Fast filled circles routine
Post by: DJ Omnimaga on June 16, 2014, 03:12:21 pm
By the way, the S, 0, 359, 10 part can be changed to stuff like S, 0, 359, 20 for faster, but lower quality circle. Don't set the last number too high, else it looks weird. Lower results in higher quality, but slower circles and possible glitches when the circle becomes smaller.
Title: Re: Fast filled circles routine
Post by: Princetonlion.tibd on June 16, 2014, 03:14:41 pm
Now I wish I got a HP Prime instead of a V200
:P

It looks like it would be useful for games with circles.

Spoiler For my opinion:
Looks awesome!
Title: Re: Fast filled circles routine
Post by: Streetwalrus on June 16, 2014, 03:23:33 pm
Yeah that's great. I'm not exactly sure how much we'll be blown by native code on this platform.
Title: Re: Fast filled circles routine
Post by: cyrille on June 24, 2014, 02:02:16 am
Hello,


[quoteJBy the way, the S, 0, 359, 10 part can be changed to stuff like S, 0, 359, 20 for faster, but lower quality circle. Don't set the last number too high, else it looks weird.

the 20 should be based on the radius... the larger the radius, the more segments you need to draw...




Also, in the case of your circle fade out, instead of using multiple graphics and blits, you could try creating one single polygon of the type:
0,0,   319,0,   319, 239  160, 239,    190, bottom of circle,    circle....   190, bottom of circle,    160, 239    0, 239
This would allow you do to the animation without any extra graphics...


If this does not work well (unpainted pixels), try spliting it in 2 halfs. the right and left half of the screen... might work better..



The reason why in your program it asks you which function to run is because you have multiple EXPORTED functions in your program (FILLPOLY in this case)... remove the EXPORT in front of FILLPOLY and it will not ask you again.


Cyrille
Title: Re: Fast filled circles routine
Post by: DJ Omnimaga on June 24, 2014, 02:42:24 am
Ok thanks for the info :)


EDIT: Ok I removed the EVAL commands now and yes they weren't needed after all.