• Stencil Wrapper Module - CSG!
    3 replies, posted
[img]https://dl.dropboxusercontent.com/u/104427432/Scripts/csg/subtract.jpg[/img] [b]Description:[/b] [URL="http://en.wikipedia.org/wiki/Constructive_solid_geometry"]Constructive Solid Geometry[/URL], or CSG, is a form of rendering which uses three operators to create complex shapes from simple primitives. Using stencils, I've made a wrapper module which allows for one-dimensional CSG's to be created with a few easy steps. Should work on both 3D and 2D drawing, though 3D is untested. In true CSG models, "trees" can be built using multiple CSG operations. This module, unfortunately, can't do that because stencils use global variables which screw everything up. The library is written so that if I figure out how to make that work, your code should remain unmodified. [B]Download:[/B] [url]https://www.dropbox.com/sh/wbzhawgi0suve7i/AADUcTMekb-jF21XUJKtsq_Da?dl=1[/url] Merge into your root lua folder. [B]How to use:[/B] 1. Define two draw functions. 2. Call csg.Start() 3. Call csg.Add, csg.Subtract, or csg.Union using the draw functions as arguments. 4. If using Add or Union, use a third draw function to paint over the newly created shape. 5. Call the returned function given by your CSG operation. 6. Call csg.End() [B]Examples (Included in the files as comments):[/B] [lua] local Box = function() --Red surface.SetDrawColor(255,0,0,100) surface.DrawRect(100,100,200,200) end local Triangle = function() --Green local PolyData = {{x=200,y=150},{x=150,y=200},{x=250,y=200}} surface.SetDrawColor(0,255,0,100) surface.DrawPoly(PolyData) end local Circle = function(ox,oy) --Blue local PolyData = {} local originx = ox or 300 local originy = oy or 300 local radius = 50 for deg=0, 359 do local x,y = math.cos(math.rad(deg)*math.pi)*radius+originx, math.sin(math.rad(deg)*math.pi)*radius+originy PolyData[deg] = {x=x,y=y} end surface.SetDrawColor(0,0,255,100) surface.DrawPoly(PolyData) end local ScreenQuad = function()--Yellow, with transparency. surface.SetDrawColor(255,255,0,255/2) surface.DrawRect(0,0,ScrW(),ScrH()) end local ScreenQuadBold = function()--Black, without transparency. surface.SetDrawColor(0,0,0,255) surface.DrawRect(0,0,ScrW(),ScrH()) end hook.Add("HUDPaint","CSG 2D Test", function() //Uncomment to test: -- Box() -- Triangle() -- Circle() csg.StartTree() //Uncomment to test: -- csg.Add(Box,Circle,ScreenQuad)() --Paint over each item with solid transparent white. -- csg.Subtract(Box,Triangle)() --Cut the triangle out of the box. -- csg.Union(Box,Circle,ScreenQuad)() --Only paint the parts covered by both the circle and the box with transparent white. //Can't csg a csg yet. If you figure out how to do this, message bobbleheadbob on facepunch. //This is because the stencil buffer uses global variables which are modified every time a csg is processed. -- local add = csg.Add(Box,Circle,ScreenQuad) -- csg.Subtract(add,Triangle)() --Trees of cgi within cgi can be made like so. (same effect in this case as subtracting circle from box.) local sub = csg.Subtract(Box,Triangle) csg.Subtract(sub,Circle)() csg.EndTree() end) concommand.Add("testcsg",function() local testframe = vgui.Create("DFrame") testframe:SetSize(ScrW()/2,ScrH()/2) testframe:Center() testframe:MakePopup() testframe:SetTitle("Test CSG Subtract") local oldpaint = testframe.Paint function testframe:Paint(w,h) local x,y = self:GetPos() csg.Start() -- local p = csg.Subtract( function() oldpaint(self,w,h) end, function() Circle(800-x,600-y) end) local p = csg.Subtract( function() oldpaint(self,w,h) end, function() draw.RoundedBox(8,400-x,400-y,100,100,Color(255,255,255)) end) p() csg.End() end end) [/lua] [t]https://dl.dropboxusercontent.com/u/104427432/Scripts/csg/add.jpg[/t] (subtract output is at top of post) [t]https://dl.dropboxusercontent.com/u/104427432/Scripts/csg/union.jpg[/t]
[lua]local a = render.SetStencilCompareFunction function render.SetStencilCompareFunction(arg) a(arg) function render.GetStencilCompareFunction() return arg end end local b = render.SetStencilEnable function render.SetStencilEnable(arg) b(arg) function render.GetStencilEnable() return arg end end local c = render.SetStencilFailOperation function render.SetStencilFailOperation(arg) c(arg) function render.GetStencilFailOperation() return arg end end local d = render.SetStencilPassOperation function render.SetStencilPassOperation(arg) d(arg) function render.GetStencilPassOperation() return arg end end local e = render.SetStencilReferenceValue function render.SetStencilReferenceValue(arg) e(arg) function render.GetStencilReferenceValue() return arg end end local f = render.SetStencilTestMask function render.SetStencilTestMask(arg) f(arg) function render.GetStencilTestMask() return arg end end local g = render.SetStencilWriteMask function render.SetStencilWriteMask(arg) g(arg) function render.GetStencilWriteMask() return arg end end local h = render.SetStencilZFailOperation function render.SetStencilZFailOperation(arg) h(arg) function render.GetStencilZFailOperation() return arg end end[/lua] for functions that are called multiple times per frame, this is a very inefficient way to go about about adding accessors
Very interesting. From your OP: [lua]//Can't csg a csg yet. If you figure out how to do this, message bobbleheadbob on facepunch. //This is because the stencil buffer uses global variables which are modified every time a csg is processed. --local add = csg.Add(Box,Circle,ScreenQuadBold) -- csg.Subtract(add,Triangle)() --Trees of cgi within cgi can be made like so. (same effect in this case as subtracting circle from box.)[/lua] CSG a CSG. Isn't that what those last two lines are doing? Are you saying that those examples won't work, or?
[QUOTE=bitches;46877503]Very interesting. From your OP: [lua]//Can't csg a csg yet. If you figure out how to do this, message bobbleheadbob on facepunch. //This is because the stencil buffer uses global variables which are modified every time a csg is processed. --local add = csg.Add(Box,Circle,ScreenQuadBold) -- csg.Subtract(add,Triangle)() --Trees of cgi within cgi can be made like so. (same effect in this case as subtracting circle from box.)[/lua] CSG a CSG. Isn't that what those last two lines are doing? Are you saying that those examples won't work, or?[/QUOTE] That's how they WILL work if I can figure out how to stack stencils. As of now those examples don't work. And I know those accessors are hideous. Gonna comment all that stuff because it didn't work the way I hoped.
Sorry, you need to Log In to post a reply to this thread.