Making a wireframe from multiple points

Hello,

I’ve been trying to make a mesh system and now I want to make the mesh be able to display the lines connecting the vertices. Basically like a wireframe render or for example like in Blender when viewing the lines of an mesh. Also, I want to connect the lines so that they form triangles so I can later on create the surfaces from those triangles. But I don’t know how I would go about doing that, for now I’ve just been comparing axes and creating lines to the vertices laying where the position is further than the original vertex. For better visualization of what I’m trying to do I attached two screenshots.


Module:

-- @ Mesh

-- // Variables

-- # Constants

local debris = game:GetService("Debris")

-- # Modules

local types = require(script:WaitForChild("Types"))

-- # Tables

local mesh = {}

local vertices = {}

local connections = {}

-- // Functions

mesh.__index = mesh

vertices.__index = vertices

connections.__index = connections

local function removeDuplicates(parts: {})
    for _, part in pairs(parts) do
        for _, comparePart in pairs(parts) do
            if part ~= comparePart and part.Position == comparePart.Position and part.Size == comparePart.Size then
                debris:AddItem(part, 0)
            end
        end
    end
end

function mesh.new(center: Vector3, vertices: {})
    local data = {}

    setmetatable(data, mesh)

    data.Vertices = {}

    for vertex, offset in pairs(vertices) do
        local vertexPosition = center + offset

        data.Vertices[vertex] = offset
    end

    return data
end

function mesh:connections()
    local data = {}

    setmetatable(data, connections)

    data.Parts = {}

    local vertices = self.Vertices

    local function newConnection(rootVertexPosition: Vector3, endVertexPosition: Vector3)
        local connection = Instance.new("Part", game.Workspace)

        -- | Customizing

        -- # Vectors

        connection.CFrame = CFrame.lookAt(rootVertexPosition:Lerp(endVertexPosition, 0.5), endVertexPosition)
        connection.Size = types.Connection.Size + Vector3.new(0, 0, (rootVertexPosition - endVertexPosition).Magnitude)

        -- # Colors

        connection.Material = types.Connection.Material

        -- # Enums

        connection.BrickColor = types.Connection.BrickColor

        -- # Booleans

        connection.Anchored = true

        -- | Organizing

        table.insert(data.Parts, connection)

        -- | Returning

        return connection
    end

    local function compareVerticesAxis(axis: string)
        for _, vertex in pairs(vertices) do
            for _, compareVertex in pairs(vertices) do
                if vertex ~= compareVertex and vertex[axis] > compareVertex[axis] then
                    newConnection(vertex, compareVertex)
                end
            end
        end
    end

    local function compareVerticesAxes(axis_A: string, axis_B: string)
        for _, vertex in pairs(vertices) do
            for _, compareVertex in pairs(vertices) do
                if vertex ~= compareVertex and vertex[axis_A] > compareVertex[axis_A] and vertex[axis_B] > compareVertex[axis_B] then
                    newConnection(vertex, compareVertex)
                end
            end
        end
    end

    local function removeConnectionsInShape(parts: {}, center: Vector3, size: Vector3)
        
    end

    -- | Connect all upper vertecies with the bottom vertices ( Compare X Values )

    compareVerticesAxis("X")

    -- | Connect all right vertices with the left vertices ( Compare Y Values )

    compareVerticesAxis("Y")

    -- | Connect all front vertices with the back vertices ( Compare Z Values )

    compareVerticesAxis("Z")

    -- | Cleanup ( Remove duplicates )

    removeDuplicates(data.Parts)

    -- | Connect all upper front vertices with the bottom back vertices ( Compare Y, Z Values )

    compareVerticesAxes("Y", "Z")

    -- | Connect all upper right vertices with the bottom left vertices ( Compare Y, X Values )

    compareVerticesAxes("Y", "X")

    -- | Connect all right front vertices with the left back vertices ( Compare X, Z Values )

    compareVerticesAxes("X", "Z")

    -- | Cleanup ( Remove lines inside mesh )

    return data
end

function mesh:vertices()
    local data = {}

    setmetatable(data, vertices)

    data.Parts = {}

    for _, vertexPosition in pairs(self.Vertices) do
        local vertex = Instance.new("Part", game.Workspace)

        -- | Customizing

        -- # Vectors

        vertex.Position = vertexPosition
        vertex.Size = types.Vertex.Size

        -- # Colors

        vertex.BrickColor = types.Vertex.BrickColor

        -- # Enums

        vertex.Material = types.Vertex.Material

        -- # Booleans

        vertex.Anchored = true

        -- | Organizing

        table.insert(data.Parts, vertex)
    end

    return data
end

return mesh

I appreciate any help!

2 Likes

This sounds like an interesting problem! I’ll definitely check it out and see what I can do. Have you found a way to connect 2 points with a line?

1 Like

Ta-da!
image


local function connectPoints(point1, point2)
	local distance = (point1.Position - point2.Position).Magnitude
	local midPos = (point1.Position + point2.Position) / 2

	local connectPart = Instance.new("Part")
	connectPart.CanCollide = false
	connectPart.Anchored = true
	connectPart.Parent = game:GetService("Workspace").Connections
	connectPart.BrickColor = BrickColor.new("Electric blue")
	
	connectPart.Size = Vector3.new(1, 1, distance)
	connectPart.CFrame = CFrame.lookAt(midPos, point2.Position, Vector3.new(0, 1, 0))
end

local points = game:GetService("Workspace").Points:GetChildren()

for i , v in points do
	for k = 1, #points - 1 do 
		if points[k + 1] then
			connectPoints(v, points[k + 1])
		end
	end
end
1 Like

If we don’t want the internal diagonals, we can destroy it if it lies in the middle of the points.


local function connectPoints(point1, point2)
	local distance = (point1.Position - point2.Position).Magnitude
	local midPos = (point1.Position + point2.Position) / 2

	local connectPart = Instance.new("Part")
	connectPart.CanCollide = false
	connectPart.Anchored = true
	connectPart.Parent = game:GetService("Workspace").Connections
	connectPart.BrickColor = BrickColor.new("Electric blue")
	
	connectPart.Size = Vector3.new(1, 1, distance)
	connectPart.CFrame = CFrame.lookAt(midPos, point2.Position, Vector3.new(0, 1, 0))
end

function GetCenter(partList)
	local min = nil
	local max = nil
	for _,i in partList do
		if not min then
			min = i.Position
		else
			if i.Position.X < min.X then min = Vector3.new(i.Position.X,min.Y,min.Z) end  
			if i.Position.Y < min.Y then min = Vector3.new(min.X, i.Position.Y,min.Z) end  
			if i.Position.Z < min.Z then min = Vector3.new(min.X,min.Y,i.Position.Z) end  
		end
		if not max then
			max = i.Position
		else
			if i.Position.X > max.X then max = Vector3.new(i.Position.X,max.Y,max.Z) end
			if i.Position.Y > max.Y then max = Vector3.new(max.X, i.Position.Y,max.Z) end
			if i.Position.Z > max.Z then max = Vector3.new(max.X,max.Y,i.Position.Z) end
		end	
	end

	local center = ((max-min)/2)+min
	return center
end

local points = game:GetService("Workspace").Points:GetChildren()
local centre = GetCenter(points)

for i , v in points do
	for k = 1, #points - 1 do 
		if points[k + 1] then
			connectPoints(v, points[k + 1])
		end
	end
end

local connections = game:GetService("Workspace").Connections:GetChildren()

for i, v in connections do
	if v.Position == centre then
		v:Destroy()
	end
end

Result:
image
P.S. stole the GetCenter() function from: How do I get the middle of multiple parts? - #20 by SelDraken

2 Likes

Hello,

Although It’s not what I’m exactly looking for, I really do appreciate you trying to help. I only want the diagonals on a face one time and removing the center connections will only work when all lines are parralel. For example, would I move the right bottom vertices one stud back, some of the lines going through the center wouldn’t be detected.

I may have thought of an idea that could work so I’ll be testing that for now.

1 Like

With regards to this, you are completely right in the thing internal diagonals. A better way is to index through them and remove the 4 longest lines since the internal diagonals are mathematically the longest lines in the whole shape.

Hello,

Luckily my idea worked and everything is working correctly. For every face I got the four most distant vertices in the direction of the face. For example when I want the front face, I get the four vertices with the highest values on the “Z” axis. Then I choose one vertex to be the root vertex, typically the first vertex from the face vertices and I connect every other vertex to it. Then I connect the two most close vertices to the last vertex of the face vertices, to the last vertex. I again thank you for all your effort trying to help me and I appreciate it.

Have a nice day!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.