Triangulated flooring system

Hi I am trying to make a flooring system that you can place multiple points and it will make the proper floor inbetween the placed points, I have tried multiple other systems that were previously mentioned but none seemed to work for a specific layout

image

Here is the code relevant to this…


function GetPointInFront(point, listOfPoints)
	if point == #listOfPoints then
		return listOfPoints[1]
	else
		return listOfPoints[point+1]
	end
end

function GetPointBehind(point, listOfPoints)
	if point == 1 then
		return listOfPoints[#listOfPoints]
	else
		return listOfPoints[point-1]
	end
end

function IsPointConvex(behind, point, infront, previousDirection)
	local v1 = point.Position - behind.Position
	local v2 = infront.Position - point.Position

	local crossproduct = v2:Cross(v1)
	local currentDirection

	if crossproduct.Y > 0 then
		currentDirection = 1
	else
		currentDirection = -1
	end
	return currentDirection ~= previousDirection
end

function GetAreaOfTriangle(A, B, C)
	local BA = A.Position - B.Position
	local CA = C.Position - B.Position

	return (BA:Cross(CA).magnitude/2)
end

function GetEarOfPolygon(parts, direction, folder)
	local i = 1
	local earFound = false
	local newTable
	while not earFound and i <= #parts do wait()
		local point = parts[i]
		local A, B, C = GetPointBehind(i, parts), point, GetPointInFront(i, parts)
		if IsPointConvex(A,B,C, direction) then
			local contained = false
			for x,v in pairs(parts) do
				if v ~= A and v ~= B and v ~= C then
					local a1,a2,a3 = GetAreaOfTriangle(A, B, v), GetAreaOfTriangle(A, C, v), GetAreaOfTriangle(B, C, v)

					if a1 + a2 + a3 == GetAreaOfTriangle(A, B, C) then
						contained = true
					end
				end
			end				
			
			if not contained then
				earFound = point
				drawTriangle(A.Position, B.Position, C.Position, folder)
				newTable = {}
				for x,v in pairs(parts) do
					if v ~= point then
						table.insert(newTable, v)
					end
				end
			end
		end
		i=i+1
	end
	return earFound, newTable
end

function TriangulatePolygon(points)
	local folder = workspace['TempParts']['TempFloor']
	folder:ClearAllChildren()
	local newTable = points
	local done = false
	while #newTable > 2 do
		done,newTable = GetEarOfPolygon(newTable, -1, folder)
		if newTable then
			table.sort(newTable, function(a,b) return tonumber(a.Name) < tonumber(b.Name) end)
		end
	end
end

function drawTriangle(a, b, c, parent)
	local edges = {
		{longest = (c - b), other = (a - b), position = b},
		{longest = (a - c), other = (b - c), position = c},
		{longest = (b - a), other = (c - a), position = a}
	} 
	table.sort(edges, function(a, b) return a.longest.magnitude > b.longest.magnitude end) 
	local edge = edges[1] 
	local theta = math.acos(edge.longest.unit:Dot(edge.other.unit))
	local s1 = Vector2.new(edge.other.magnitude * math.cos(theta), edge.other.magnitude * math.sin(theta)) 
	local s2 = Vector2.new(edge.longest.magnitude - s1.x, s1.y) 
	local p1 = edge.position + edge.other * 0.5
	local p2 = edge.position + edge.longest + (edge.other - edge.longest) * 0.5
	local right = edge.longest:Cross(edge.other).unit 
	local up = right:Cross(edge.longest).unit 
	local back = edge.longest.unit 

	local cf1 = CFrame.new(
		p1.x, p1.y, p1.z,
		-right.x, up.x, back.x,
		-right.y, up.y, back.y,
		-right.z, up.z, back.z
	) 
	local cf2 = CFrame.new(
		p2.x, p2.y, p2.z,
		right.x, up.x, -back.x,
		right.y, up.y, -back.y,
		right.z, up.z, -back.z
	)

	local w1 = wedge:Clone()
	local w2 = wedge:Clone()
	w1.Parent = parent
	w2.Parent = parent
	w1.Size = Vector3.new(0.25, s1.y + 0.05, s1.x + 0.05)
	w2.Size = Vector3.new(0.25, s2.y + 0.05, s2.x + 0.05)
	w1.CFrame = cf1
	w2.CFrame = cf2
end
2 Likes

I found this function to make triangles, it might be helpful. (a, b and c are Vector3 positions (each edge), parent is the parent of the wedges, w1 and w2 are the wedges used)

local function draw3dTriangle(a, b, c, parent, w1, w2)
    local ab, ac, bc = b - a, c - a, c - b;
    local abd, acd, bcd = ab:Dot(ab), ac:Dot(ac), bc:Dot(bc);
    
    if (abd > acd and abd > bcd) then
        c, a = a, c;
    elseif (acd > bcd and acd > abd) then
        a, b = b, a;
    end
    
    ab, ac, bc = b - a, c - a, c - b;
    
    local right = ac:Cross(ab).unit;
    local up = bc:Cross(right).unit;
    local back = bc.unit;
    
    local height = math.abs(ab:Dot(up));
    
    w1.Size = Vector3.new(0, height, math.abs(ab:Dot(back)));
    w1.CFrame = CFrame.fromMatrix((a + b)/2, right, up, back);
    w1.Parent = parent;
    
    w2.Size = Vector3.new(0, height, math.abs(ac:Dot(back)));
    w2.CFrame = CFrame.fromMatrix((a + c)/2, -right, up, -back);
    w2.Parent = parent;
    
    return w1, w2;
end