Grid snapping system not working for rotated rectangles

I am trying to make a grid snapping system that is similiar to Lumber Tycoon 2’s building system, but the issue is that the grid just doesn’t snap the models correctly when they are rotated at 90 degree angles, as you can see below:
image

This is what i expect it to look like:
image
As you can see in the expected result, all models are snapped to the 1-stud grid.

I have tried rounding the position of the model, however the model’s size is 2x4x1, which is what I think is causing this problem to happen. When I tried it with a 2x2x2 model, it worked perfectly fine.

I have also tried searching on the DevForum but I wasn’t able to find any solutions for this type of problem.

--[[
The getBoundingBox() function is for returning a bounding box with
no rotation (which is what :GetBoundingBox() can't do), I got it
from this topic:
https://devforum.roblox.com/t/216581/8
]]

function roundToMultiple(x, mult)
	return math.floor((x / mult) + 0.5) * mult
end

...

-- Placing the object:
		elseif input.KeyCode == Enum.KeyCode.E then
			Storage.PlaceBlueprint:FireServer(place_cf, is_placing)

...

-- Moving the preview:
			while is_placing do
				local dt = task.wait()
				
				local mouse = UserInputService:GetMouseLocation()
				local ray = camera:ViewportPointToRay(mouse.X, mouse.Y)
				
				local params = RaycastParams.new()
				params.FilterType = Enum.RaycastFilterType.Include
				params.FilterDescendantsInstances = {plot}
				
				local result = workspace:Raycast(ray.Origin, ray.Direction.Unit * 1024, params)
				if result then
					-- This 'bounds' model is basically a clone of the 'preview' variable but it is not shown, it is only for calculating the bounding box.
					bounds:PivotTo(orientation)
					
					local _, size = getBoundingBox(bounds:GetDescendants())
					local offset = size * result.Normal / 2
					
					local position = Vector3.new(roundToMultiple(result.Position.X, 1), roundToMultiple(result.Position.Y, 1), roundToMultiple(result.Position.Z, 1))
					position += offset
					
					local target = CFrame.new(position) * orientation
					place_cf = target
					
					local cf = pivot:Lerp(target, dt * 15)
					preview:PivotTo(cf)
					
					if (target.Position - cf.Position).Magnitude > 50 then
						cf = target
						preview:PivotTo(target)
					end
					
					pivot = cf
				end
			end

After a painful 5 hours of searching, I decided to just replace the code with this:

It may not be the best, but at least it works.

local function calculateGridCFrame(model:Model, position:Vector3, normal:Vector3)
	local plot = workspace.Plots:FindFirstChild(client:GetAttribute('plot'))
	local cf, size = getBoundingBox({plot:FindFirstChild('Base')})
	
	local bounds, m_size = getBoundingBox({model.PrimaryPart})
	
	local lpos = cf:PointToObjectSpace(position) + normal * m_size / 2
	local size2 = (size - m_size) / 2
	
	local x = math.clamp(lpos.X, -size2.X, size2.X)
	local y = math.clamp(lpos.Y, 0, cf.Y + 100) - 1
	local z = math.clamp(lpos.Z, -size2.Z, size2.Z)
	
	local abs_x, abs_y, abs_z = math.abs(x), math.abs(y), math.abs(z)
	local sign_x, sign_y, sign_z = math.sign(x), math.sign(y), math.sign(z)
	
	x = sign_x * (math.round(abs_x) + (size2.X % 1))
	y = sign_y * (math.round(abs_y) + (size2.Y % 1))
	z = sign_z * (math.round(abs_z) + (size2.Z % 1))
	
	return cf * CFrame.new(x, y, z) * orientation
end

...

			while is_placing do
				local dt = task.wait()
				
				local mouse = UserInputService:GetMouseLocation()
				local ray = camera:ViewportPointToRay(mouse.X, mouse.Y)
				
				local params = RaycastParams.new()
				params.FilterType = Enum.RaycastFilterType.Include
				params.FilterDescendantsInstances = {plot}
				
				local result = workspace:Raycast(ray.Origin, ray.Direction.Unit * 1024, params)
				if result then
					bounds:PivotTo(orientation)
					place_cf = calculateGridCFrame(bounds, result.Position, result.Normal)
					
					local cf = pivot:Lerp(place_cf, dt * 15)
					preview:PivotTo(cf)
					
					if (place_cf.Position - cf.Position).Magnitude > 50 then
						cf = place_cf
						preview:PivotTo(place_cf)
					end
					
					pivot = cf
				end
			end

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