How do I clamp a 3d rotation (a vector) within a cone about a (second) vector?
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
@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.