Help creating a grid of points

i have been trying to create a function that will create a grid of AnchorPoints in a part when you pass in the part, and the resolution.

Something like this:

This image was made manually by myself and only has points on the outer edges. I would like the function to have the option for outer edges only or fill the whole box. Because parts can have different sizes, it might be best for the resolution to not be based on studs, but QUANTITY of points in a given row so they would always end up spaced evenly no matter what the part dimensions may be.

Here is my failed attempt so far:


function module.GetPointGrid(size, resolution)

	local stepsX = (size.X / resolution) + 1
	local stepsY = (size.Y / resolution) + 1
	local stepsZ = (size.Z / resolution) + 1

	local pointsTable = {}
	for countX = 1, stepsX do
		for countY = 1, stepsY do
			for countZ = 1, stepsZ do
			
				local posX = (countX - 1) * resolution
				local posY = (countY - 1) * resolution
				local posZ = (countZ - 1) * resolution

				local point = Vector3.new(posX, posY, posZ)
				table.insert(pointsTable, point)

			end
		end
	end

	return pointsTable
end

This script creates the grid of points, but they are offset from the part because the way I am positioning them. It also does not allow for only having points on the outer surface.

Does anyone have a function that can do this?

1 Like

I’ve made a similar “solution”. Try reading through the thread and improvising it to your situation (which is just adding more points instead of just the 8 corners of a part):

Here's something that works well:

– Return a list of points evenly spaced in a right-angle grid in a unit cube (1x1x1)
– (resolution + 1) points will be generated along each axis, to divide the unit cube into
– (resolution) number of smaller cubes.
– resolution is a Vector3, where each component represents the resolution in the respective axis.
function makeUnitCubeVolumeGrid(resolution)
local points = {}

for posX = 0, 1, 1 / resolution.X do
	for posY = 0, 1, 1 / resolution.Y do
		for posZ = 0, 1, 1 / resolution.Z do
			table.insert(points, Vector3.new(posX, posY, posZ))
		end
	end
end

return points

end

– Return a list of points evenly spaced in a right-angle grid on the surface of a unit cube (1x1x1)
– (resolution + 1) points will be generated along each axis, to divide the unit cube into
– (resolution) number of smaller cubes.
– resolution is a Vector3, where each component represents the resolution in the respective axis.
function makeUnitCubeSurfaceGrid(resolution)
local points = {}

    --Not the most efficient algo, but probably not performance critical so worth it in dev time
for posX = 0, 1, 1 / resolution.X do
	for posY = 0, 1, 1 / resolution.Y do
		for posZ = 0, 1, 1 / resolution.Z do
			if posX == 0 or posX == 1 or posY == 0 or posY == 1 or posZ == 0 or posZ == 1 then 
				table.insert(points, Vector3.new(posX, posY, posZ))
			end
		end
	end
end

return points

end

–Given a point, return the point translated according to the position
– of a part and a given anchorpoint, and scaled and rotated according
– to the size and orientation of the part, respectively.
function transformPointToPartSpace(point, part, anchorPoint)
return part.CFrame:PointToWorldSpace(
(point + anchorPoint) * part.Size
)
end

– Given a list of values v1 … vn, a function f, and values …,
– return a list containing f(v1, …) … f(vn, …)
function map(list, f, …)
local result = {}
for _, v in pairs(list) do
table.insert(result, f(v, …))
end
return result
end

function makePartAttachmentGrid(part, gridResolution, isSurfaceGrid)
local attachments = {}

--gridResolution can be a Vector3 to have different resolutions on each axis,
--	or a number to have the same resolution on each axis.
local resolutionVector = typeof(gridResolution) == "Vector3"
	and gridResolution 
	or Vector3.new(1, 1, 1) * gridResolution

--Attachments can be spaced around the surface or the volume (default) of the part
local gridPoints = isSurfaceGrid 
	and makeUnitCubeSurfaceGrid(resolutionVector) 
	or makeUnitCubeVolumeGrid(resolutionVector)

local transformedPoints = map(gridPoints, transformPointToPartSpace, part, Vector3.new(-0.5, -0.5, -0.5))

for _, transformedPoint in ipairs(transformedPoints) do
	local attachment = Instance.new("Attachment")
	attachment.CFrame = CFrame.new(transformedPoint - game.Workspace.Part.Position)
	attachment.Parent = game.Workspace.Part
	table.insert(attachments, attachment)
end

return attachments

end

makePartAttachmentGrid(game.Workspace.Part, 8, true)


I modified some of my old code to work with the “surface” grid thing. Hope it helps! If you’ve any questions then ask away :slight_smile:

1 Like