• draw.Arc() Version 2.0
    22 replies, posted
It occurs to me that [URL="http://s3.scriptfodder.com/script_media/025db3e2f1609d1fb73744fb002ab952.png"]lots[/URL] [URL="http://s3.scriptfodder.com/script_banners/4e4b1bb86afd7210fbb51cb1ba9ca14e_full.png"]of[/URL] [URL="http://s3.scriptfodder.com/script_media/31a0fb0ccab97ba014c3a008f4273162.png"]people[/URL] use my drawarc.lua snippet. I've been painfully aware of the FPS drop it can cause for a while now, so I finally got around to improving it. The new version measures roughly twice as fast using FProfiler. It takes the same arguments so you can just fast-replace the old version in your code. [U]Changes:[/U] 1. Half as many polygons per arc 2. Only one loop for inner and outer points 3. Uses quads instead of triangles 4. Odd-degreed arcs aren't malformed 5. No longer needs roughness. Just put 1 in case of old version conflicts. 6. Microoptimizations [U]Download:[/U] Any old link I posted before will now download the new version. The old version can be found [URL="https://www.dropbox.com/s/msb2y7pi8sjuolj/drawarcv1.lua?dl=1"]here[/URL]. [url]https://www.dropbox.com/s/dh2nvua6gjmptmi/drawarc.lua?dl=1[/url] [U]Raw Code:[/U] [lua] -- VERSION 2.0 released 03/26/2017 -- Changes: -- 1. Half as many polygons per arc -- 2. Only one loop for inner and outer points -- 3. Uses quads instead of triangles -- 4. Odd-degreed arcs aren't malformed. -- 5. No longer needs roughness. Just put 1 in case of old version conflicts. -- 6. Microoptimizations. -- Enjoy! ~Bobbleheadbob -- Draws an arc on your screen. -- startang and endang are in degrees, -- radius is the total radius of the outside edge to the center. -- cx, cy are the x,y coordinates of the center of the arc. -- roughness is only used in old versions. Just put 1 to prevent conflicts local cos, sin, abs, max, rad1, log, pow = math.cos, math.sin, math.abs, math.max, math.rad, math.log, math.pow local surface = surface function draw.Arc(cx,cy,radius,thickness,startang,endang,roughness,color) surface.SetDrawColor(color) surface.DrawArc(surface.PrecacheArc(cx,cy,radius,thickness,startang,endang,roughness)) end function surface.DrawArc(arc) -- Draw a premade arc. for k,v in ipairs(arc) do surface.DrawPoly(v) end end function surface.PrecacheArc(cx,cy,radius,thickness,startang,endang,roughness) local quadarc = {} -- Correct start/end ang local startang,endang = startang or 0, endang or 0 -- Define step -- roughness = roughness or 1 local diff = abs(startang-endang) local smoothness = log(diff,2)/2 local step = diff / (pow(2,smoothness)) if startang > endang then step = abs(step) * -1 end -- Create the inner circle's points. local inner = {} local outer = {} local ct = 1 local r = radius - thickness for deg=startang, endang, step do local rad = rad1(deg) -- local rad = deg2rad * deg local cosrad, sinrad = cos(rad), sin(rad) --calculate sin,cos local ox, oy = cx+(cosrad*r), cy+(-sinrad*r) --apply to inner distance inner[ct] = { x=ox, y=oy, u=(ox-cx)/radius + .5, v=(oy-cy)/radius + .5, } local ox2, oy2 = cx+(cosrad*radius), cy+(-sinrad*radius) --apply to outer distance outer[ct] = { x=ox2, y=oy2, u=(ox2-cx)/radius + .5, v=(oy2-cy)/radius + .5, } ct = ct + 1 end -- QUAD the points. for tri=1,ct do local p1,p2,p3,p4 local t = tri+1 p1=outer[tri] p2=outer[t] p3=inner[t] p4=inner[tri] quadarc[tri] = {p1,p2,p3,p4} end -- Return a table of triangles to draw. return quadarc end [/lua]
:dance: I would rate you but... im kinda new ( ? ) Thanks bro! [IMG]http://i.imgur.com/jQokmJN.png[/IMG]
Looks awesome!
[QUOTE=B1ts;52013887]:dance: I would rate you but... im kinda new ( ? ) Thanks bro! [IMG]http://i.imgur.com/jQokmJN.png[/IMG][/QUOTE] Can't rate until 50 posts I think.
But what if I had just used my own draw.Arc?! Thanks for this, this won't fix multicore rendering issues, will it?
[QUOTE=Tenrys;52014928]But what if I had just used my own draw.Arc?! Thanks for this, this won't fix multicore rendering issues, will it?[/QUOTE] I doubt it, but the prerelease of the next GMod version claims to have multicore fixes.
Doesn't look like this is working, nothing draws anymore. The function does get called [IMG]https://i.tenrys.pw/2017/Mar/5dZw.png[/IMG]
[QUOTE=Tenrys;52015007]Doesn't look like this is working, nothing draws anymore. The function does get called [IMG]https://i.tenrys.pw/2017/Mar/5dZw.png[/IMG][/QUOTE] Show me some code and I'll try to replicate it.
[code] draw.Arc(X + 164 * 0.5, Y + 164 * 0.5, 164 * 0.5, 8, 0, math.ceil(360 * HP), 2, LerpColor(Color(192, 64, 64, 255), Color(64, 192, 64, 255), HP))[/code] This is the line for the health bar. Used to work fine before. X and Y are positions around the bottom left, HP is a number between 0 and 1, LerpColor is probably not the issue.
You are not resetting the texture to one that does not cull.
Works on my end. Are you doing draw.NoTexture() before calling draw.Arc()? EDIT: Here comes NinjaBoy cucking me out of my own user support. >:I
And now I'm having this odd error, not sure why it happens since the color does exist and I give it to the function, then when I try to print it inside of the function [code][ERROR] addons/silkyhud/lua/silkyhud/cl_arc.lua:20: bad argument #3 to 'SetDrawColor' (number expected, got no value) 1. SetDrawColor - [C]:-1 2. Arc - addons/silkyhud/lua/silkyhud/cl_arc.lua:20 3. v - addons/silkyhud/lua/silkyhud/cl_main.lua:414 4. unknown - lua/includes/modules/hook.lua:84 [/code] [editline]26th March 2017[/editline] Gonna do some more testing. draw.NoTexture() didn't seem to change much either
[QUOTE=Tenrys;52015059]And now I'm having this odd error, not sure why it happens since the color does exist and I give it to the function, then when I try to print it inside of the function [code][ERROR] addons/silkyhud/lua/silkyhud/cl_arc.lua:20: bad argument #3 to 'SetDrawColor' (number expected, got no value) 1. SetDrawColor - [C]:-1 2. Arc - addons/silkyhud/lua/silkyhud/cl_arc.lua:20 3. v - addons/silkyhud/lua/silkyhud/cl_main.lua:414 4. unknown - lua/includes/modules/hook.lua:84 [/code] [editline]26th March 2017[/editline] Gonna do some more testing. draw.NoTexture() didn't seem to change much either[/QUOTE] Weird shit. It says "bad argument #3" which implies it had 2 other arguments or that the first argument was a number and not a table or something.
Something might be fucking with my game at this point or something, this doesn't work either: [code] hook.Add("HUDPaint", "Test", function() draw.NoTexture() draw.Arc(500, 500, 10, 10, 10, 60, Color(255, 255, 255, 255)) end) [/code] [editline]26th March 2017[/editline] No addons on, neither legacy or workshop, verified cache, still same thing. [editline]26th March 2017[/editline] Nope, even without my own addon and using a simple file in lua/autorun/client the same error about SetDrawColor pops up, or nothing happens, even when trying the dev branch. [editline]26th March 2017[/editline] No more ideas.
I believe you need a texture with $nocull 1 for it to work, and draw.NoTexture doesn't have that.
Even then, there's a weird error like shown above which I don't understand. My script worked fine before even without using draw.NoTexture or anything.
You missed one argument in your test code. Nothing weird about that. [editline]26th March 2017[/editline] Also draw.NoTexture resets surface.SetMaterial, not render.SetMaterial. for some reason surface.DrawPoly requires render.SetMaterial [editline]26th March 2017[/editline] Also your function is kinda borked at 0 radius. [editline]26th March 2017[/editline] [code] local mat = Material( "vgui/white") hook.Add("HUDPaint", "ssssssssssss", function() render.SetMaterial( mat ) draw.Arc( 500, 500, 50 + math.sin( CurTime() ) * 25, // radius 15 + math.cos( CurTime() ) * 10, // thickness 180 + math.cos( CurTime() ) * 45, // start angle in deg 360 + math.cos( CurTime() ) * 45, // end angle in deg ( must be lower than start ang ) math.sin( CurTime() ) * 50, // roughness HSVToColor( (CurTime() * 100 ) % 360, 1, 1 ) ) end )[/code] Here's animated example [editline]26th March 2017[/editline] Also at higher roughness it sort of never reaches the end angle [editline]26th March 2017[/editline] [code] hook.Add("HUDPaint", "ssssssssssss", function() render.SetMaterial( mat ) draw.Arc( 500, 500, 50 + math.sin( CurTime() ) * 25, // radius 15 + math.cos( CurTime() ) * 10, // thickness 180 + math.cos( CurTime() ) * 45, // start angle in deg 360 + math.cos( CurTime() ) * 45, // end angle in deg ( must be lower than start ang ) 0, // roughness color_white ) draw.Arc( 500, 500, 50 + math.sin( CurTime() ) * 25, // radius 15 + math.cos( CurTime() ) * 10, // thickness 180 + math.cos( CurTime() ) * 45, // start angle in deg 360 + math.cos( CurTime() ) * 45, // end angle in deg ( must be lower than start ang ) math.sin( CurTime() ) * 50, // roughness HSVToColor( (CurTime() * 100 ) % 360, 1, 1 ) ) end )[/code] Here's code that highlights the last issue.
[QUOTE=Robotboy655;52015187]You missed one argument in your test code. Nothing weird about that. [editline]26th March 2017[/editline] Also draw.NoTexture resets surface.SetMaterial, not render.SetMaterial. for some reason surface.DrawPoly requires render.SetMaterial [editline]26th March 2017[/editline] Also your function is kinda borked at 0 radius. [editline]26th March 2017[/editline] [code] local mat = Material( "vgui/white") hook.Add("HUDPaint", "ssssssssssss", function() render.SetMaterial( mat ) draw.Arc( 500, 500, 50 + math.sin( CurTime() ) * 25, // radius 15 + math.cos( CurTime() ) * 10, // thickness 180 + math.cos( CurTime() ) * 45, // start angle in deg 360 + math.cos( CurTime() ) * 45, // end angle in deg ( must be lower than start ang ) math.sin( CurTime() ) * 50, // roughness HSVToColor( (CurTime() * 100 ) % 360, 1, 1 ) ) end )[/code] Here's animated example [editline]26th March 2017[/editline] Also at higher roughness it sort of never reaches the end angle [editline]26th March 2017[/editline] [code] hook.Add("HUDPaint", "ssssssssssss", function() render.SetMaterial( mat ) draw.Arc( 500, 500, 50 + math.sin( CurTime() ) * 25, // radius 15 + math.cos( CurTime() ) * 10, // thickness 180 + math.cos( CurTime() ) * 45, // start angle in deg 360 + math.cos( CurTime() ) * 45, // end angle in deg ( must be lower than start ang ) 0, // roughness color_white ) draw.Arc( 500, 500, 50 + math.sin( CurTime() ) * 25, // radius 15 + math.cos( CurTime() ) * 10, // thickness 180 + math.cos( CurTime() ) * 45, // start angle in deg 360 + math.cos( CurTime() ) * 45, // end angle in deg ( must be lower than start ang ) math.sin( CurTime() ) * 50, // roughness HSVToColor( (CurTime() * 100 ) % 360, 1, 1 ) ) end )[/code] Here's code that highlights the last issue.[/QUOTE] I can see why it doesn't reach the end angle at huge roughness like that. Roughness is just the step value in a for loop, so if it goes way over with the last step, it won't even come close to the endang. Roughness values above 5 aren't recommended if you're going for accuracy. I would make it force that last segment to draw but then it would be really malformed. Strange though that it uses render.SetMaterial(). I've used draw.NoTexture() this whole time and it's always worked fine for me. It's even fixed things when they were broken in the past.
You could just build your polys by subdivision. Anyway, something on your client must have set render.SetMaterial, some addon or whatever. Or that's the default function. Kinda need to make reder.SetMaterial and surface.SetMaterial do the same thing on the back end though. No reason to have them both.
I'm at a dilemma now. I just improved the code to work like you said, but now it takes a smoothness parameter instead of roughness. However, if I convert roughness to smoothness within the function to keep legacy functionality it's not a 1:1 inverse ratio. So either roughness becomes really esoteric and meaningless or I make negative values of roughness equal to smoothness. I think considering I made this a global function any script which uses it can have conflicts if it doesn't accept the exact same arguments so changing them is out of the question. I'll just make it do nothing in the new version. It's a lot faster now anyway and step doesn't affect the final segment anymore. I can calculate the best smoothness in the code. EDIT: Updated OP
[QUOTE=Robotboy655;52015158]I believe you need a texture with $nocull 1 for it to work, and draw.NoTexture doesn't have that.[/QUOTE] You've no idea how happy I am that I read the replies before posting. [editline]14th May 2017[/editline] I was having some sort of issue with the function earlier tonight; whenever I drew an arc, it'd look fine until it went past a radius of 20 or so. I'm off my PC for tonight so I haven't gotten a chance to try anything else but draw.NoTexture(), but I'll try in the morning if there isn't some other sort of fix. [editline]14th May 2017[/editline] [QUOTE=bobbleheadbob;52017435]... esoteric ...[/QUOTE] I only know what that means because of Gojira :v
Hey, sorry to bring up an old thread but this is very useful and Version 2.0 doesn't seem to work anymore. This is how I'm creating the arc: draw.Arc(x, y, 50, 10, 0, 362 * (defender / 100), 1, Color(255, 0, 0, 200)) defender is a number that goes down from 100 to 0 (I tested and this works). The issue is that the arc is invisible. I think it has to do with the last part of surface.PrecacheArc where it does: for tri = 1, ct do local p1, p2, p3, p4 local t = tri + 1 p1 = outer[tri] p2 = outer[t] p3 = inner[t] p4 = inner[tri] quadarc[tri] = {p1, p2, p3, p4} end The way I was able to fix it was to do: p1 = outer[t] p2 = outer[tri] p3 = inner[tri] p4 = inner[t] It comes out (sort of) fine. It has these weird white edges every 90 degrees. https://files.facepunch.com/forum/upload/265355/cacbfe2b-e72f-44a3-a122-f8246736d2f7/Untitled.png
Create a new thread for these problems and post the full code, also could be the background since it's not fully opaque.
Sorry, you need to Log In to post a reply to this thread.