Rendering thick curved lines

Advanced game related topics
Antithesis
New User
New User
Posts: 5
Joined: Sat Aug 04, 2007 3:39 pm

Rendering thick curved lines

Post by Antithesis »

This isn't so much a game question as a graphics question. Could someone suggest an efficient method to produce geometry (I hope this can be done in terms of geometry and not pixels) for thick curved lines like Photoshop and Flash can draw?
My current approach is to create a triangle strip following the curve but at large thickness + quick direction changes, it produces very ugly artifacts as the vertex sets on either side of the curve overlap other nearby vertex sets.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I apologize for the sloppy coding, I just threw this together. It's taking 2.5 milliseconds on average here to render a curve 10 pixels wide on the 640*480 screen. If 2.5 ms is fast enough for your purposes, this should work:

Code: Select all

OpenLibrary(1, "msimg32.dll")

CreateImage(0, 640,480,32)

Macro ARGB(RGB=0,Transparency=255) ; by einander
    Blue(RGB)|Green(RGB)<<8|Red(RGB)<<16|Transparency<<24 
EndMacro 

Structure POINTF
  x.f
  y.f
EndStructure

Global Dim PointArray.POINTF(100)
For i=0 To 100
  PointArray(i)\x = 30*i+0.5*i
  pointArray(i)\y = 50+i*1.1*i
Next

Global *token, *surface, *redpen5

CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0
  Structure GdiplusStartupInput 
    GdiPlusVersion.l 
    *DebugEventCallback.Debug_Event
    SuppressBackgroundThread.l 
    SuppressExternalCodecs.l 
  EndStructure 
CompilerEndIf  

Procedure DrawCurve()
  hdc = StartDrawing(ImageOutput(0))
    Box(0,0,640,480,#Black)
    CallFunction(0, "GdipCreateFromHDC", hdc, @*surface)
    CallFunction(0, "GdipDrawCurve", *surface, *redpen5, PointArray(), 100)
    CallFunction(0, "GdipDeleteGraphics", *surface)    
  StopDrawing()
  dc = GetWindowDC_(#Null)
  imagedc = CreateCompatibleDC_(dc)
  SelectObject_(imagedc, ImageID(0))
  hdc = StartDrawing(ScreenOutput())
    CallFunction(1, "TransparentBlt", hdc, 0, 0, 640,480, imagedc, 0, 0, 640,480,0) 
  StopDrawing()
  ReleaseDC_(0, dc)
  DeleteDC_(imagedc)
EndProcedure

input.GdiplusStartupInput
input\GdiPlusVersion = 1

OpenLibrary(0, "gdiplus.dll")
CallFunction(0, "GdiplusStartup", @*token, @input, #Null)
CallFunction(0, "GdipCreatePen1", ARGB(#Red, 180), 10.0, 2, @*redpen5)

InitSprite()
OpenWindow(0,0,0,640,480,"gdiplus curves",$CA0001)
OpenWindowedScreen(WindowID(0), 0,0,640,480,0,0,0)

Repeat
  EventID = WindowEvent()
  ClearScreen(#Black)
  DrawCurve()
  FlipBuffers()
  Delay(1)
Until EventID = #WM_CLOSE

CallFunction(0, "GdipDeletePen", *redpen5)
CallFunction(0, "GdiplusShutdown", *token)
CloseLibrary(0)
CloseLibrary(1)
Last edited by netmaestro on Sat Aug 11, 2007 3:36 am, edited 2 times in total.
BERESHEIT
Antithesis
New User
New User
Posts: 5
Joined: Sat Aug 04, 2007 3:39 pm

Post by Antithesis »

Thank you for the suggestion, but unfortunately this is not fast or versatile enough for what I'm doing. I'm very inclined to do this by building geometry alone, as I will also be wanting to do textured/fakeAA lines.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I figured it might not do, I have no other ideas unfortunately, not being a game developer. I hope you find what you're looking for, best of luck to you.
BERESHEIT
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

I have no idea how "thick curved lines like Photoshop and Flash can draw" look,
but I would suggest using a circle to plot.

like this:

Code: Select all

InitSprite()
OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "Plot")
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

radius = 7

StartDrawing(ScreenOutput())
  For n=-radius To 639+radius
    x.f = n
    y.f = 240 + 200 * Sin(x/40)
    Circle(x,y,7,$F0A040)
  Next
StopDrawing()

Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
the rounded shape of the circle keeps the artifacts low.

[edit]
if you want some lightning-effekt, use a sprite.

take this one Image and save it as a BMP in the same directory you saved the demo-code.

Code: Select all

InitSprite()
OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "Plot")
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

TransparentSpriteColor(-1,0)
LoadSprite(0,"ball.bmp")

radius = 7

  For n=-radius To 639+radius
    x.f = n
    y.f = 240 + 200 * Sin(x/40)
    DisplayTransparentSprite(0,x-radius,y-radius)
  Next
FlipBuffers()

Repeat:Until WaitWindowEvent() = #PB_Event_CloseWindow
oh... and have a nice day.
Post Reply