local module = {}

local function form_triangle(pa,pb,p1,p2,p3,s2)
	local s1 = pa.Size.X
	s2 = s2 or s1*0.5
	local p12 = p2-p1
	local p23 = p3-p2
	local p13 = p3-p1
	local p12l = p12.Magnitude
	local p23l = p23.Magnitude
	local p13l = p13.Magnitude
	local bottom
	local bot_len
	local totop
	local root
	local tip
	local far
	if p12l > p23l and p12l > p13l then -- TRUE: p12 largest FALSE: p12 smaller than p23l or p13l
		tip = p3
		root = p1
		far = p2
		bottom = p12
		bot_len = p12l
		totop = p13
		s2 = -s2
	elseif p23l > p13l then -- TRUE: p23 must be largest FALSE: p13 largest
		tip = p1
		root = p2
		far = p3
		bottom = p23
		bot_len = p23l
		totop = -p12
		s2 = -s2
	else -- p13 largest
		tip = p2
		root = p1
		far = p3
		bottom = p13
		bot_len = p13l
		totop = p12
	end
	bottom = bottom.Unit
	local coeff = totop:Dot(bottom)
	local mid = root+coeff*bottom
	local cross = totop:Cross(bottom).Unit
	local top = (mid-tip)
	pa.Size = Vector3.new(s1,top.Magnitude,coeff)
	pb.Size = Vector3.new(s1,top.Magnitude,bot_len - coeff)
	top = top.Unit
	pa.CFrame = CFrame.fromMatrix(s2*cross+(root+tip)*0.5,cross,-top,bottom)
	pb.CFrame = CFrame.fromMatrix(s2*cross+(tip+far)*0.5,-cross,-top,-bottom)
end
local function form_normal(p,n)
	local part = Instance.new("Part")
	part.Anchored = true
	part.Size = Vector3.new(1,1,10)
	part.Parent = game.Workspace
	part.CFrame = CFrame.lookAlong(p,n) * CFrame.new(0,0,-5)
end
local w = 8
local grass = script.Grass
local ter = workspace.Terrain
function module.make_wedges(_,p)
	local part = grass:Clone()
	for _,item in pairs(part:GetChildren()) do
		for k,v in pairs(p) do
			item[k] = v
		end
	end
	return {
		make_quad = function(p1,p2,p3,p4,s,n1,n2,n3,n4,parent)
			local g = part:Clone()
			g.Parent = parent
			form_triangle(g.a,g.b,p1,p2,p3,s*(-w/2))
			form_triangle(g.c,g.d,p1,p4,p3,s*(w/2))
			--[[form_normal(p1,n1)
			form_normal(p2,n2)
			form_normal(p3,n3)
			form_normal(p4,n4)]]
			return g		
		end,
		flush = function() end,
	}
end

local assets = game:GetService("AssetService") 
local s = 1
function module.make_mesh(_root,p)
	local mesh = assets:CreateEditableMesh()
	local empty = true
	local root = _root or Vector3.zero
	local mesh = mesh
	local topleft = mesh:AddUV(Vector2.new(0,0))
	local topright = mesh:AddUV(Vector2.new(s,0))
	local bottomright = mesh:AddUV(Vector2.new(s,s))
	local bottomleft = mesh:AddUV(Vector2.new(0,s))
	return {
		make_quad = function(p1,p2,p3,p4,s,n1,n2,n3,n4)
			empty = false
			n1 = mesh:AddNormal(n1)
			n2 = mesh:AddNormal(n2)
			n3 = mesh:AddNormal(n3)
			n4 = mesh:AddNormal(n4)
			p1 = mesh:AddVertex(p1 - root)
			p2 = mesh:AddVertex(p2 - root)
			p3 = mesh:AddVertex(p3 - root)
			p4 = mesh:AddVertex(p4 - root)
			local tri1,tri2
			if s > 0 then
				tri1 = mesh:AddTriangle(p1,p2,p3)
				tri2 = mesh:AddTriangle(p3,p4,p1)
				mesh:SetFaceNormals(tri1,{n1,n2,n3})
				mesh:SetFaceNormals(tri2,{n3,n4,n1})
				mesh:SetFaceUVs(tri1,{topleft,topright,bottomright})
				mesh:SetFaceUVs(tri2,{bottomright,bottomleft,topleft})
			else
				tri1 = mesh:AddTriangle(p3,p2,p1)
				tri2 = mesh:AddTriangle(p1,p4,p3)
				mesh:SetFaceNormals(tri1,{n3,n2,n1})
				mesh:SetFaceNormals(tri2,{n1,n4,n3})
				mesh:SetFaceUVs(tri1,{bottomright,topright,topleft})
				mesh:SetFaceUVs(tri2,{topleft,bottomleft,bottomright})
			end
		end,
		flush = function()
			if not empty then
				local part = assets:CreateMeshPartAsync(Content.fromObject(mesh),
					{
						CollisionFidelity = Enum.CollisionFidelity.PreciseConvexDecomposition,
						RenderFidelity = Enum.RenderFidelity.Performance
					})
				for index,item in pairs(p) do
					part[index] = item
				end
				part.Parent = workspace.Terrain
				part.Position = root
				part.Anchored = true
			end
			root = nil
			mesh = nil
		end,
	}
end

return module
