Animated Vector Graphics Scene Graph

Share your advanced PureBasic knowledge/code with the community.
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

v 0.2.9a

added AVGAddPathPolygonBezier()
It's not quite right yet and color is fixed for demo

I cobbled this together from acreis post
viewtopic.php?p=646962#p646962

left click on the points and change. The plan is to add shape morphing as animation
and enable shapes to be drawn point and click , see previous post in thread
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

0.2.9b fixed AVGAddPathPolygonBezier
There's still a problem with curve joins on star points and still haven't worked out how to fill it :?:
Mesa
Enthusiast
Enthusiast
Posts: 455
Joined: Fri Feb 24, 2012 10:19 am

Re: Animated Vector Graphics Scene Graph

Post by Mesa »

There's still a problem with curve joins on star points and still haven't worked out how to fill it :?:

Code: Select all

Line 3114: AVGStrokePath(*scene,poly,3,#PB_Path_RoundEnd ): Works for me.
M.
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

Mesa wrote: Fri Oct 24, 2025 8:35 am
There's still a problem with curve joins on star points and still haven't worked out how to fill it :?:

Code: Select all

Line 3114: AVGStrokePath(*scene,poly,3,#PB_Path_RoundEnd ): Works for me.
M.
Thanks, it would help if I read the manual. :D
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

I'm adding AvgAnimatePath, It took a fair few hours of thought, though slotting it in wasn't difficult but it might seem a bit strange at first. You create a bezier path object which might be visible or hidden and then add AvgAnimatePath() to it, next you create a child object that you want to follow the path which can also have their own animations or children.
I still need to look at the finer details but it it appears to be the zen path as in the least path of resistance.

will post update when I've finished debugging the additions

Code: Select all

Global tri = AVGCreateObject(*scene,160,300,"Triangle")
  
  AVGSetOnMouseLeftDown(*scene,tri, @OnleftDown())
  AVGSetOnMouseLeftUp(*scene, tri, @OnleftUp())
  AVGSetOnMouseMove(*scene,tri,@OnMouseMove()) 
  AVGAddPathPolygonBezier(*scene,tri,0,0,3,90,90,90)
  AVGVectorSourceColor(*scene, tri, RGBA(255, 0, 255, 255),RGBA(255, 255, 0, 255))
  AVGStrokePath(*scene,tri,8) 
  AVGAnimatePath(*scene,tri,0,80, 3.0,#Ease_Linear, #True, #False)
  Global marker =  AVGCreateObject(*scene,0,0,"marker",tri) 
  AVGAddPathCircle(*scene,marker,0,0,10) 
  AVGVectorSourceColor(*scene, marker, RGBA(0, 255, 0, 255))
  AVGFillPath(*scene,marker) 
  AVGAnimateScale(*scene, marker, 1.0, 1.0, 2.0, 2.0, 1.0, #Ease_InOutQuad, #True, #True)


See video
https://Atomicwebserver.com/avgscenegraph.mp4
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

updated v0.3a
Added AvgAnimatePath object on path currently rotates orientation, I will make that optional
Fixed zoom and pan

There are still issues with Bezier paths, picking them is difficult and still can't fill the area.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 426
Joined: Thu Jul 09, 2015 9:07 am

Re: Animated Vector Graphics Scene Graph

Post by pf shadoko »

We will now need to adapt NanoSVG to PB to get the most out of SVG animations.

Any candidates?
User avatar
Skipper
User
User
Posts: 62
Joined: Thu Dec 19, 2024 1:26 pm
Location: Europe

Re: Animated Vector Graphics Scene Graph

Post by Skipper »

pf shadoko wrote: Mon Oct 27, 2025 10:25 am We will now need to adapt NanoSVG to PB to get the most out of SVG animations.

Any candidates?
Exactly my thinking as well, as this is more and more moving towards OpenVG functionality.
<< Win-11 (x64: XEON + i5) / Mint linux (x64: i3) / MacOS Monterey (Intel x64) >>
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

Nanosvg doesn't do fonts we will be better off adding to the pb svg module which Ive already fixed to handle fonts properly and its what got me started on this in the first place. After looking at a few c libs it became very clear that none of them considered how to do svg animation.

Before I get on to that though I need to fix the problem with filling closed bezier paths
It might be gdi+ issue. I'm trying other gdi+ curve functions if I get power back today. Lightning strike
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 426
Joined: Thu Jul 09, 2015 9:07 am

Re: Animated Vector Graphics Scene Graph

Post by pf shadoko »

wait a moment, I code you a sample
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

pf shadoko wrote: Mon Oct 27, 2025 9:30 pm wait a moment, I code you a sample
Thanks and see if you can apply it to the bezier polygon function.
I could do it by path segments and may have to resort to that but the reason I don't want to use path strings is that it's not efficient.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 426
Joined: Thu Jul 09, 2015 9:07 am

Re: Animated Vector Graphics Scene Graph

Post by pf shadoko »

Check out the AddPathCurve documentation.
Bezier curves are defined by four points.
The first point is the cursor position.
The other three are defined in AddPathCurve.
If you want the curves to be connected, just chain the AddPathCurve calls together
and end with the first point (or with closepath()).

(if you want the entire curve to have no sharp points, the first point of AddPathCurve must be aligned with the previous two
(points 1 and 2 define the tangents at the ends (see diagram in the documentation)

Note: if we adapt nanoVG in PB and can retrieve the list of points defining the letters of a font, I know how to display full text (this is a very interesting geometric problem that I have already solved).

Code: Select all

OpenWindow(0, 0, 0, 500, 500, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 500, 500)

RandomSeed(9)
Dim x(12)
Dim y(12)
For i=0 To 12
  x(i)=Random(400)+50
  y(i)=Random(400)+50
Next

StartVectorDrawing(CanvasVectorOutput(0))

Macro rnd:(Random(400)+50):EndMacro
MovePathCursor(x(n), y(n)):n+1
For i=0 To 3
  AddPathCurve(x(n), y(n), x(n+1), y(n+1), x(n+2), y(n+2)):n+3
Next

ClosePath()
VectorSourceColor($ff0000ff)
FillPath(#PB_Path_Preserve)
VectorSourceColor($ffff0000)
StrokePath(2)

For i=0 To 12 Step 3
  AddPathCircle(x(i),y(i),5)
Next
VectorSourceColor($ff008800)
StrokePath(2)

StopVectorDrawing()

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

Yes but look at avgpolygonbezier it's chained together and closed but a fill doesn't work as expected.
Generally you can't do circles with beziers they're not comutive, to do it you need to chain them reusing the control point.

Gdi+ has a second bezier function that takes an array of points so you can do a spline and close it
Or cardinal curves probably a cubic hermite so it fits better to your point along a path.

Why I want splines is so it's possible to animate them like morph between two curves and deform shapes with easing functions.
User avatar
pf shadoko
Enthusiast
Enthusiast
Posts: 426
Joined: Thu Jul 09, 2015 9:07 am

Re: Animated Vector Graphics Scene Graph

Post by pf shadoko »

svg (canvas) creates circles from Bézier curves
I'll try to make the splines for you tomorrow (it's late here in France)

Code: Select all

CreateImage(0,400,400,32,0)
StartVectorDrawing(ImageVectorOutput(0))
AddPathCircle(200,200,100)
Debug PathSegments()
StopVectorDrawing()
User avatar
idle
Always Here
Always Here
Posts: 6075
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Animated Vector Graphics Scene Graph

Post by idle »

pf shadoko wrote: Mon Oct 27, 2025 11:38 pm svg (canvas) creates circles from Bézier curves
I'll try to make the splines for you tomorrow (it's late here in France)

Code: Select all

CreateImage(0,400,400,32,0)
StartVectorDrawing(ImageVectorOutput(0))
AddPathCircle(200,200,100)
Debug PathSegments()
StopVectorDrawing()
you can make circles from quarters or halfs, usually you'd use cubic hermite for them

this is how I'm doing the polygons ignore the mod that's just my quick fix but I was toying with it to do multiple iterations so wanted to keep wrapping it around

Code: Select all

Structure avgpoint
  x.f
  y.f
EndStructure  

Procedure _AVGRefit_Bezier(*p0.avgpoint,*p1.avgpoint,*p2.avgpoint,*p3.avgpoint,*t0.avgpoint,*t1.avgpoint)
  
  Protected d1.f, d2.f, d3.f
  Protected a.f, b.f, c.f, d.f
  Protected tx1.f,ty1.f,tx2.f,ty2.f
  
  d1 = Sqr((*p1\x-*p0\x)*(*p1\x-*p0\x) + (*p1\y-*p0\y)*(*p1\y-*p0\y))*0.5
  d2 = Sqr((*p2\x-*p1\x)*(*p2\x-*p1\x) + (*p2\y-*p1\y)*(*p2\y-*p1\y))*0.5 
  d3 = Sqr((*p3\x-*p2\x)*(*p3\x-*p2\x) + (*p3\y-*p2\y)*(*p3\y-*p2\y))*0.5 
  
  a = d1 * d1
  b = d2 * d2
  c = (2 * d1 * d1) + (3 * d1 * d2) + (d2 * d2)
  d = 1.0 / (3 * d1 * (d1 + d2))
  
  *t0\x = (a * *p2\x - b * *p0\x + c * *p1\x) * d
  *t0\y = (a * *p2\y - b * *p0\y + c * *p1\y) * d
  
  a = d3 * d3
  b = d2 * d2
  c = (2 * d3 * d3) + (3 * d3 * d2) + (d2 * d2)
  d = 1.0 / (3 * d3 * (d3 + d2))
  
  *t1\x = (a * *p1\x - b * *p3\x + c * *p2\x) * d
  *t1\y = (a * *p1\y - b * *p3\y + c * *p2\y) * d
  
EndProcedure

Procedure AVGAddPathPolygonBezier(*scene.AVGScene, objectID,x,y,sides.i,majoraxis.i,minoraxis.i=0,orient.i=0,Stars=1)
    
  Protected xx, yy, px, py, inc.f, ang.f, fin.f
  Protected ndx.f,ndy.f,dy.f,dx.f,dx1,dy1,cosOrient.f,SinOrient.f
  Protected start.i,finish.i,dz.f,i.i
  Protected t0.avgpoint,t1.avgpoint  
  
  start = 0 
  If stars 
    sides*2 
  EndIf   
  
  Dim pt.avgpoint(sides) 
  
  dz=1.0
  finish = sides 
  If finish < 3 : finish = 3 : EndIf
  If finish > 64 : finish = 64 : EndIf
  inc = Radian(360 / finish)
  finish = start + 360
  
  ang = Radian(start)
  fin = Radian(finish)
  cosOrient = Sin(Radian(orient-180)) 
  sinOrient = Cos(Radian(orient-180))  
  dx = x + (Cos(ang) * majoraxis * dz) 
  dy = y + (Sin(ang) * minoraxis * dz) 
  dx1 = dx - x 
  dy1 = dy - y
  px = x + (dx1 * sinOrient - dy1 * cosOrient) ;rotate coordinates
  py = y + (dx1 * cosOrient + dy1 * sinOrient) 
  If stars 
    dz = 0.5 
  EndIf   
  
  Protected first=0  
  i=0
  Repeat 
    
    ang + inc  
    If ang > fin : ang = fin : EndIf
    dx = x + (Cos(ang) * majoraxis * dz) 
    dy = y + (Sin(ang) * minoraxis * dz) 
    dx1 = dx - x 
    dy1 = dy - y
    ndx = x + (dx1 * sinOrient - dy1 * cosorient) 
    ndy = y + (dx1 * cosOrient + dy1 * sinorient)
    
    pt(i)\x = ndx 
    pt(i)\y = ndy 
    i+1
    
    px = ndx
    py = ndy
    
    If stars 
      If dz = 0.5 
        dz = 1.0 
      Else 
        dz = 0.5 
      EndIf   
    EndIf 
  Until ang = fin
  
  sides = ArraySize(pt())
  For i = 0 To sides
    
    _AVGRefit_Bezier(pt(i%sides),pt((i+1)%sides),pt((i+2)%sides),pt((i+3)%sides),t0,t1) 
    
    AVGMovePathCursor(*scene,objectID,pt((i+1)%sides)\x,pt((i+1)%sides)\y)
    
    AVGAddPathCurve(*scene,objectID,t0\x,t0\y,t1\x,t1\y,pt((i+2)%sides)\x,pt((i+2)%sides)\y,first)
        
    first=1
    
  Next
  
  ;AVGClosePath(*scene,objectid)
  
EndProcedure

And the servers back up.

Also if I get stuck I can resort to AddpathSegments, but it makes it slower to process but I can always replace the string in place so that might be the simplest.
and I will also be caching images and later adding a spatialtrie to do caching culling collision resolution for physics module which will on binary keys.
and it should also be possible to add opengl target for immediate mode as well without changing the commands.
Post Reply