So I’m just getting into coding math related stuff (i absolutely suck at it) and I was just curious on what the purpose of math.clamp is. I understand what it does, but I cant really think of a practical way to use it.
This post claims constraining rotation on an axis is a useful application. Basically constraining a value to a specific range while using the max and min and everything inbetween.
It makes sure that a number given is between a min number and max number supplied eg. if you supply 10 to a math.clamp(10,1,20) it will return 10. If the value is less than 1 it will return 1 and if it’s more than 20 it will return 20. It’s a good way to make sure you are returned a number between the ranges you want
For a more practical use case I have used it in my CFrame turret module.
Code snippet:
--In some runservice loop or while loop.
--baseCFrame is the world CFrame of any part where the turret is mounted on and serves as the XYZ axis of the turret. Hence objectspace.
local lookAtWorld = CFrame.lookAt(turretPosition,lookAtPosition,baseCFrame.UpVector)--goal LookAt CFrame
if self.Constraints then
local turretRelativeCF = baseCFrame:ToObjectSpace(lookAtWorld)
local x , y , z = turretRelativeCF:ToOrientation()
--print(math.deg(x),math.deg(y),math.deg(z))
local constrainedX , constrainedY = self:EulerClampXY(x,y)
--Detect quadrant of lookAt position
local jointPosition = currentJointMotor6D.Part0.CFrame*originalC0Position
local quadrantLookAtFromJointPosition = CFrame.lookAt(jointPosition,lookAtPosition,baseCFrame.UpVector)
local baseRelative = baseCFrame:ToObjectSpace(quadrantLookAtFromJointPosition)
local _,y, _ = baseRelative:ToOrientation()
constrainedY = math.abs(constrainedY)*math.sign(y)--use the quadrants of the lookAtFromJoint
--print(math.deg(constrainedX),math.deg(constrainedY))
--print(math.deg(constrainedY))
goalCFrame = relativeToWorld*baseCFrame*CFrame.fromOrientation(constrainedX,constrainedY,z)*turretCFrameRotationOffset
else
--Euler clamp function
function TurretController:EulerClampXY(x,y)
local Constraints = self.Constraints
--there is an issue when y is between -179 to 180 degrees
local degY = math.deg(y)
local degX = math.deg(x)
local newY = math.clamp(degY,-Constraints.YawRight,Constraints.YawLeft)
local newX = math.clamp(degX,-Constraints.DepressionAngle, Constraints.ElevationAngle)
local hasBeenClamped = false
local yawEdgeClamped = false
local elevationEdgeClamped = false
if degY < -Constraints.YawRight or degY > Constraints.YawLeft then
hasBeenClamped = true
yawEdgeClamped = true
end
if degX < -Constraints.DepressionAngle or degX > Constraints.ElevationAngle then
hasBeenClamped = true
elevationEdgeClamped = true
end
self.YawEdgeClamped = yawEdgeClamped
self.ElevationEdgeClamped = elevationEdgeClamped
self.HasBeenClamped = hasBeenClamped
return math.rad(newX), math.rad(newY)
end