getClosestEdgePointXZ.lua 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. local function isOutside(bounds, controlPoint)
  2. local relativePosition = bounds.CFrame:PointToObjectSpace(controlPoint)
  3. local xDist = math.abs(relativePosition.X)
  4. local yDist = math.abs(relativePosition.Y)
  5. local zDist = math.abs(relativePosition.Z)
  6. if xDist > bounds.Size.X/2 then
  7. return true
  8. elseif yDist > bounds.Size.Y/2 then
  9. return true
  10. elseif zDist > bounds.Size.Z/2 then
  11. return true
  12. end
  13. return false
  14. end
  15. local function clampPointToBounds(bounds, controlPoint)
  16. local relativePosition = bounds.CFrame:PointToObjectSpace(controlPoint)
  17. local clampedPosition = Vector3.new(
  18. math.clamp(relativePosition.X, -bounds.Size.X/2, bounds.Size.X/2),
  19. math.clamp(relativePosition.Y, -bounds.Size.Y/2, bounds.Size.Y/2),
  20. math.clamp(relativePosition.Z, -bounds.Size.Z/2, bounds.Size.Z/2)
  21. )
  22. return bounds.CFrame * CFrame.new(clampedPosition)
  23. end
  24. local function getClosestEdgePointXZ(board, controlPoint)
  25. local relativeControlPos = board.CFrame:PointToObjectSpace(controlPoint) * Vector3.new(1,0,1)
  26. local boardSize = board.Size
  27. local xzConstrained = (board.CFrame * CFrame.new(relativeControlPos)).Position
  28. if isOutside(board,xzConstrained) then
  29. return clampPointToBounds(board, xzConstrained) * CFrame.new(0,boardSize.Y/2,0)
  30. end
  31. -- get the positions on x axis of left and right edges
  32. local leftEdgePos = -(boardSize.X/2)
  33. local rightEdgePos = (boardSize.X/2)
  34. -- do the same for top and bottom but on z axis
  35. local frontEdgePos = -(boardSize.Z/2)
  36. local backEdgePos = (boardSize.Z/2)
  37. -- get all edge distances
  38. local leftDist = math.abs(leftEdgePos - relativeControlPos.X)
  39. local rightDist = math.abs(rightEdgePos - relativeControlPos.X)
  40. local frontDist = math.abs(frontEdgePos - relativeControlPos.Z)
  41. local backDist = math.abs(backEdgePos - relativeControlPos.Z)
  42. -- get distance to closest edge
  43. local xDist = leftDist < rightDist and leftDist or rightDist
  44. local zDist = frontDist < backDist and frontDist or backDist
  45. -- get local position of closest edge
  46. local closestXEdge = leftDist < rightDist and leftEdgePos or rightEdgePos
  47. local closestZEdge = frontDist < backDist and frontEdgePos or backEdgePos
  48. if xDist < zDist then
  49. -- x edge is closest
  50. return board.CFrame * CFrame.new(closestXEdge, boardSize.Y/2, relativeControlPos.Z)
  51. elseif zDist < xDist then
  52. -- z edge is closest
  53. return board.CFrame * CFrame.new(relativeControlPos.X, boardSize.Y/2, closestZEdge)
  54. elseif xDist == zDist then
  55. -- both equal distance, use corner
  56. return board.CFrame * CFrame.new(closestXEdge, boardSize.Y/2, closestZEdge)
  57. end
  58. end