Recent

Author Topic: Animated Oscillating Lined Star  (Read 787 times)

Boleeman

  • Hero Member
  • *****
  • Posts: 924
Animated Oscillating Lined Star
« on: May 15, 2025, 03:06:18 pm »
An Animated Oscillating Lined Star


I could not get an anti-aliased line version to work at a nice smooth speed so I used non-float points.


Used Gamma correct for hue.

A bit Trippy at a fast speed.

Josh

  • Hero Member
  • *****
  • Posts: 1375
Re: Animated Oscillating Lined Star
« Reply #1 on: May 15, 2025, 05:37:19 pm »
Hi

just quicklook at code

var i is declared but not assigned.and used...

 0.55 * Sin(5);  should be pre-calculated
plus various others as its in a calc loop being run 100's of time

Code: Pascal  [Select][+][-]
  1. for j := 0 to num - 1 do
  2.   begin
  3.     x := j * 0.55 * Sin(5);
  4.     y := x * Sin(i + 2 * t + x / 2 + Pi / PhaseDivisor) / (numVertices - 2);
  5.     b := (j * (numVertices - 1)) * Pi / numVertices;
  6.  
  7.     _x := x * Cos(b) + y * Sin(i);
  8.     _y := x * Sin(b) + y * Cos(i);
  9.  
  10.     pathPoints[j] := Point(Round(cx + _x), Round(cy + _y));
  11.  
  12.     col := myHSLAtoBGRA(hueDot, 0.9, 0.7, 0.3);
  13.     bmp.FillEllipseAntialias(pathPoints[j].X, pathPoints[j].Y, 2, 2, col);
  14.   end;                                                            
« Last Edit: May 15, 2025, 05:51:20 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Nitorami

  • Hero Member
  • *****
  • Posts: 510
Re: Animated Oscillating Lined Star
« Reply #2 on: May 15, 2025, 05:57:07 pm »
And instead of separate sin and cos calls you may use math.sincos(). Factor 2 faster.

Boleeman

  • Hero Member
  • *****
  • Posts: 924
Re: Animated Oscillating Lined Star
« Reply #3 on: May 16, 2025, 12:41:10 am »
Thanks for the advice guys.

Josh, I realized later that i was not the needed variable, but instead t. Thanks..

Nitorami, I did not know about math.sincos() so I learnt something new. Thanks.

Now working reliably for other numbers of vertices.
« Last Edit: May 16, 2025, 06:41:35 am by Boleeman »

Josh

  • Hero Member
  • *****
  • Posts: 1375
Re: Animated Oscillating Lined Star
« Reply #4 on: May 16, 2025, 09:41:34 am »
hi

optimizing timer for performance,pre-calculating values.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   x, y, _x, _y, b,temp1,angle: Single;
  4.    j: Integer;
  5.   cx, cy: Integer;
  6.   col: TBGRAPixel;
  7.   pathPoints: array of TPoint;
  8.   numVertices, PhaseDivisor, theSpeed: Integer;
  9.   _t: Single;
  10.   hueDot, hueLine: Single;
  11.   invNumVert: Single;
  12.   sinT, cosT: Single;
  13.   invPhase: Single;
  14. begin
  15.   bmp.Fill(BGRA(12, 12, 12, seFillAlpha.Value));
  16.  
  17.   cx := bmp.Width div 2;
  18.   cy := bmp.Height div 2;
  19.   theSpeed := tbSpeed.Position;
  20.  
  21.   numVertices := seVertices.Value;
  22. //  CoEffofT := seCoEffofT.Value;
  23.   PhaseDivisor := sePhaseDivisor.Value;
  24.   _t := 1 / theSpeed;
  25.   SetLength(pathPoints, num);
  26.  
  27.   // Precompute smooth hue values
  28.   hueDot := Frac(u / 360);           // Dots hue
  29.   hueLine := Frac((u + 30) / 360);   // Offset for line hue
  30.  
  31.   // constants used  loop
  32.   col := myHSLAtoBGRAFast(hueDot, 0.9, 0.7, 0.3);
  33.   temp1:=0.55 * Sin(5);
  34.   invNumVert := 1 / (numVertices - 2);
  35.   invPhase := Pi / PhaseDivisor;
  36.   sinT := Sin(t);
  37.   cosT := Cos(t);
  38.  
  39.   for j := 0 to num - 1 do
  40.   begin
  41.     x := j * temp1;
  42.     angle := 3 * t + x * 0.5 + invPhase;
  43.     y := x * Sin(angle) * invNumVert;
  44.     b := (j * (numVertices - 1)) * Pi / numVertices;
  45.     _x := x * Cos(b) + y * sinT;
  46.     _y := x * Sin(b) + y * cosT;
  47.     pathPoints[j] := Point(Round(cx + _x), Round(cy + _y));
  48.     bmp.FillEllipseAntialias(pathPoints[j].X, pathPoints[j].Y, 2, 2, col);
  49.   end;
  50.  
  51.   // Draw path
  52.   col := myHSLAtoBGRAFast(hueLine, 0.6, 0.3, 0.1);
  53.   bmp.DrawPolyLineAntialias(pathPoints, col, False);
  54.  
  55.   // Animate parameters
  56.   t += _t;
  57.   u -= 0.5;
  58.   if u < 0 then u := u + 360;
  59.  
  60.   bmp.Draw(PaintBox1.Canvas, 0, 0, True);
  61. end;              

Created an optimized myHSLAtoBGRA (named myHSLAtoBGRAFast), speed tweeks and removal of power,linear gamma correction, colors generated should be visually fine, a lot faster, couldbe  optimized further.

Code: Pascal  [Select][+][-]
  1. function myHSLAtoBGRAFast(H, S, L, A: Single): TBGRAPixel;
  2. var
  3.   C, X, m: Single;
  4.   R_, G_, B_: Single;
  5.   Hdeg: Single;
  6.   R, G, B, Alpha: Byte;
  7. begin
  8.   Hdeg := Frac(H) * 360;
  9.   C := (1 - Abs(2 * L - 1)) * S;
  10.   X := C * (1 - Abs(Frac(Hdeg / 60) * 2 - 1));
  11.   m := L - C / 2;
  12.  
  13.   if Hdeg < 60 then
  14.   begin
  15.     R_ := C; G_ := X; B_ := 0;
  16.   end else if Hdeg < 120 then
  17.   begin
  18.     R_ := X; G_ := C; B_ := 0;
  19.   end else if Hdeg < 180 then
  20.   begin
  21.     R_ := 0; G_ := C; B_ := X;
  22.   end else if Hdeg < 240 then
  23.   begin
  24.     R_ := 0; G_ := X; B_ := C;
  25.   end else if Hdeg < 300 then
  26.   begin
  27.     R_ := X; G_ := 0; B_ := C;
  28.   end else
  29.   begin
  30.     R_ := C; G_ := 0; B_ := X;
  31.   end;
  32.  
  33.   // Skip gamma correction: faster linear mapping
  34.   R := Round((R_ + m) * 255);
  35.   G := Round((G_ + m) * 255);
  36.   B := Round((B_ + m) * 255);
  37.   Alpha := Round(A * 255);
  38.  
  39.   Result := BGRA(R, G, B, Alpha);
  40. end;        

« Last Edit: May 16, 2025, 09:44:16 am by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Dzandaa

  • Sr. Member
  • ****
  • Posts: 452
  • From C# to Lazarus
Re: Animated Oscillating Lined Star
« Reply #5 on: May 16, 2025, 11:31:11 am »
Hi
@Boleeman:

You can also try this:

Code: Pascal  [Select][+][-]
  1. function GetRgb(r, g, b: Double): TBGRAPixel;
  2. var
  3.  ret: TBGRAPixel;
  4. begin
  5.  ret.red := byte(Round(r * 255.0));
  6.  ret.green := byte(Round(g * 255.0));
  7.  ret.blue := byte(Round(b * 255.0));
  8.  exit(ret);
  9. end;
  10.  
  11. function HsvToRgb(h, s, v: Double): TBGRAPixel;
  12. var
  13.  hi: Integer;
  14.  f, p, q, t: Double;
  15.  ret: TBGRAPixel;
  16. begin
  17.  hi := Round((Floor(h / 60.0) mod 6));
  18.  f := (h / 60.0) - Floor(h / 60.0);
  19.  
  20.  p := v * (1.0 - s);
  21.  q := v * (1.0 - (f * s));
  22.  t := v * (1.0 - ((1.0 - f) * s));
  23.  
  24.  ret := GetRgb(0.0, 0.0, 0.0);
  25.  case (hi) of
  26.   0:
  27.    ret := GetRgb(v, t, p);
  28.   1:
  29.    ret := GetRgb(q, v, p);
  30.   2:
  31.    ret := GetRgb(p, v, t);
  32.   3:
  33.    ret := GetRgb(p, q, v);
  34.   4:
  35.    ret := GetRgb(t, p, v);
  36.   5:
  37.    ret := GetRgb(v, p, q);
  38.  end;
  39.  
  40.  exit(ret);
  41. end;    
  42.                                      
  43.  

This is the code I use.

You just have to add Alpha channel and change Double to Single.

B->
Regards,
Dzandaa

Boleeman

  • Hero Member
  • *****
  • Posts: 924
Re: Animated Oscillating Lined Star
« Reply #6 on: May 16, 2025, 01:34:10 pm »
Thanks Josh and DZandaa for your codes and replies.

I wondered if there is a way to use Canvas2D and set the anti-aliased line width to 0.5 pixels (I tried but it was too slow)


I worked out a way to always get tentacles by adjusting the wavelength/WaveStretch (found it works reliably).

Code: Pascal  [Select][+][-]
  1.  // Precompute constant expressions
  2.   piDivPhase := Pi / PhaseDivisor;
  3.   angleStep := (numVertices - 1) * Pi / numVertices;
  4.   invDiv := 1 / (numVertices - 2);
  5.   SinCos(t, sinT, cosT);
  6.  
  7.   for j := 0 to num - 1 do
  8.   begin
  9.     x := j * X_SCALE;
  10.     phase := 2 * t + x / WaveStretch + piDivPhase;
  11.     y := x * Sin(phase) * invDiv;
  12.     b := j * angleStep;
  13.  
  14.     SinCos(b, sinB, cosB);
  15.  
  16.     _x := x * cosB + y * sinT;
  17.     _y := x * sinB + y * cosT;  


I also used sincos() and precalc.

I will need to look at Josh's code more closely but thought I would just upload what I have at the moment.
« Last Edit: May 16, 2025, 02:02:37 pm by Boleeman »

 

TinyPortal © 2005-2018