Help with CFrame maths

I have three functions which help the placement of a piece of furniture, the first two functions calculate the position, with the first one intending to “snap” the furniture to a grid, while the second function prevents the furniture from “clipping” into the walls and floor.

What I want to do is combine the first two functions so that it can both prevent the furniture from “clipping” into walls as well as adhere to the snap to grid function. However the math gets too disorientating for me, any help?

local function SnapFurniture()
	posX = math.floor(mouse.Hit.X / gridSize + 0.5) * gridSize 
	posY = math.floor(mouse.Hit.Y / gridSize + 0.5) * gridSize  
	posZ = math.floor(mouse.Hit.Z / gridSize + 0.5) * gridSize
end

local function CheckPlacement(FurnitureLocal)
	local rayOrigin = mouse.UnitRay.Origin
	local rayDirection = mouse.UnitRay.Direction.unit * 100

	local ignoreList = {FurnitureLocal, player.Character}
	local newRay = RaycastParams.new()

	newRay.FilterDescendantsInstances = {FurnitureLocal, player.Character}
	newRay.FilterType = Enum.RaycastFilterType.Blacklist
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection, newRay)
	if raycastResult then
		pos = raycastResult.Position
		norm = raycastResult.Normal
	end
end

local function ChangePos(pos, norm, FurnitureLocal, TurnNum)
	if FurnitureLocal ~= nil then
		local endPos = pos + (norm * (FurnitureLocal.PrimaryPart.Size*.5)) 
		local endAngle = CFrame.fromEulerAnglesXYZ(0, math.rad(TurnNum), 0)
		FurnitureLocal:SetPrimaryPartCFrame(CFrame.new(endPos) * endAngle)
	end
end

Huh never mind, the math wasn’t actually that hard.
For those curious, I applied this equation posX = math.floor(mouse.Hit.X / gridSize + 0.5) * gridSize to the raycast result’s position instead of the mouse position and from there created a new vector 3 using the new positions.

local function CheckPlacement(FurnitureLocal)
	local rayOrigin = mouse.UnitRay.Origin
	local rayDirection = mouse.UnitRay.Direction.unit * 100

	local ignoreList = {FurnitureLocal, player.Character}
	local newRay = RaycastParams.new()

	newRay.FilterDescendantsInstances = {FurnitureLocal, player.Character}
	newRay.FilterType = Enum.RaycastFilterType.Blacklist
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection, newRay)
	if raycastResult then
		posX = math.floor(raycastResult.Position.X / gridSize + 0.5) * gridSize 
		posY = math.floor(raycastResult.Position.Y / gridSize + 0.5) * gridSize  
		posZ = math.floor(raycastResult.Position.Z / gridSize + 0.5) * gridSize
		pos = Vector3.new(posX, posY, posZ)  -- Create new vector 3 using those positions
		norm = raycastResult.Normal
	end
end
1 Like