Clamp a 3d Rotation

How do I clamp a 3d rotation (a vector) within a cone about a (second) vector?

2 Likes

Vector within a cone of another vector? I believe I’ve done something similar with my CCDIK module here is how it went by measuring the angles for a ball socket constraint. Is this what you were looking for?

local centerAxis = axisAttachment.WorldAxis
	local currentCenterAxis = jointAttachment.WorldAxis 
	local angleDifference = VectorUtil.AngleBetween(currentCenterAxis,centerAxis)

	local constraintUpperAngle = math.rad(jointConstraintInfo.UpperAngle) or math.rad(45)

	--out of bounds constrain it to world axis of the socket
	if angleDifference > constraintUpperAngle then
		local axis = currentCenterAxis:Cross(centerAxis)
		local angleDifference = angleDifference-constraintUpperAngle
		local newCenterAxisWithinBounds = rotateVectorAround( currentCenterAxis, angleDifference, axis )
		self.rotateJointFromTo(motor6d,currentCenterAxis,newCenterAxisWithinBounds,part0CF.RightVector)
	end

Rotating vectors is like doing spherical linear interpolation (slerp) of the endpoints of the vectors. We’ll need to compute the angle between the vectors:

function angleBetweenVectors(p0, p1)
    return local angle = math.acos( p0.Unit:Dot(p1.Unit) ) --Angle between the vectors (O to p0) and (O to p1)
end

Here’s the slerp function

function slerp(p0, p1, t)
    local angle = angleBetweenVectors(p0, p1)
    local sinOfAngle = math.sin(angle)
    return p0 * sin((1-t) * angle) / sinOfAngle  + p1 * sin(t * angle) / sinOfAngle 
end

And here’s a function that, given a vector and a cone, returns the vector but clamped inside the cone.

function constrainVectorInsideCone(toConstrain, coneDirection, coneAngle)
    local currentAngle = angleBetweenVectors(toConstrain, coneCenter)
    if currentAngle > coneAngle then --If not already inside cone
        local angleProportionToEdgeOfCone = coneAngle / currentAngle
        coneDirection = coneDirection.Unit * toConstraint.Magnitude --Clamping shouldn't change the length of the vector, so slerp from a cone direction that has the same length as the original vector
        toConstrain = slerp(coneDirection, toConstrain, angleProportionToEdgeOfCone)
    end
    return toConstrain
end

Hope this helps, let me know if it doesn’t work as expected or if you have questions :slight_smile:

1 Like

@ThanksRoBama worked exactly as expected, ty.

@dthecoolest, is rotateVectorAround a means to hinge around a cross product between two vectors in your module? This CCDIK looks very nice and I would tip you a coffee for it if you have patreon.

I will additionally be trying out specifying an x and y dim angle to constrain a vector to an oval cone.

1 Like