- Home /
Get the signed angle between 2 two Vector3
Hi everybody,
currently i'm working on an IK-Solver based on the FABRIK Algorithm (described in here).
As for the rotation-limits i need to compare angles between Vectors - for the case where the target is not reachable everything is working:
void axis_limit()
{
for (int i = 0; i < (bones.Length - 1); i++)
{
axis_lambda = distances[i] / Vector3.Distance(axis_target.position, bones[i].position);
axis_newVec = ((1 - axis_lambda) * bones[i].position + axis_lambda * axis_target.position);
if (!useRotationLimits )
{
bones[i + 1].position = axis_newVec;
continue;
}
if (bones[i].GetComponent<rotationLimitAxis>())
{
rotationLimitAxis rotationScript = bones[i].GetComponent<rotationLimitAxis>();
// returns Vector3.up, right or forward depending on the rotations limit axis
cur_direction = getDirectionFromAxis(bones[i], rotationScript.axisX, rotationScript.axisY, rotationScript.axisZ);
if (SignedVectorAngle(axis_newVec.normalized, rotationScript.angleVec.normalized, cur_direction, bones[i].position) <= 0)
{
bones[i + 1].position = rotationScript.angleVec;
continue;
}
if (SignedVectorAngle(axis_newVec.normalized, rotationScript.limitVec.normalized, cur_direction, bones[i].position) >= 0)
{
bones[i + 1].position = rotationScript.limitVec;
continue;
}
}
bones[i + 1].position = axis_newVec;
}
}
And the SignedVectorAngle function:
//From Math3D - http://wiki.unity3d.com/index.php/3d_Math_functions
public static float SignedVectorAngle(Vector3 referenceVector, Vector3 otherVector, Vector3 normal)
{
Vector3 perpVector;
float angle;
//Use the geometry object normal and one of the input vectors to calculate the perpendicular vector
perpVector = Vector3.Cross(normal, referenceVector);
//Now calculate the dot product between the perpendicular vector (perpVector) and the other input vector
angle = Vector3.Angle(referenceVector, otherVector);
angle *= Mathf.Sign(Vector3.Dot(perpVector, otherVector));
return angle;
}
The backwards-reaching function is basicaly the same as the axis_limit with only those differences:
axis_lambda = distances[i] / Vector3.Distance(bones[i].position, bones[i + 1].position);
axis_newVec = ((1 - axis_lambda) * bones[i].position + lambda * bones[i+1].position);
If i try to get the angle in the forward and backward reaching loop SignedVectorAngle won't return the correct angle between both Vectors.
As far as i understand it and according to a few other posts about Vector angles, the SignedVectorAngle function seems to be the right approach to retrive the angle i need.
Am i totally wrong with my approach or just to blind to find the solution? Does someone solved sth. like this and can give me a hint how to find the right angle?
Here are some pictures to maybe visualize my problem:
black = angle limits
green = angle limits normalized
red = target vector
The axis_limit limited to a certain angle (magnitude is wrong - but doesn't matter right now)
forward-backward reaching
there seems to be a problem with the normalized angle-vectors or something but i can't find the solution. I hope someone can punch me in the right direction to understand what's going on here and how to solve this.
Thank you for your time
Martin
Answer by Das_M · Sep 11, 2014 at 11:15 AM
A bit of sleep and distance by doing other stuff made me finally find the soultion.
The problem was created by the angle-limitations Vector e.g. "rotationScript.angleVec". This Vector is constructed by the transforms position owning the limitiation-script (blue cone).
So if i'm right - to calculate the correct angle between two Vectors they need to have the same origin. This just simply means i have to substract the transforms position from the rotationScript.angleVec.
Right now this is working for me and i hope i'm right and not writing nonsense here ; -)
Here's the complete code for the backwards reaching (forward reaching is working with negated limit vectors)
void axis_backward()
{
for (int i = 0; i < bones.Length - 1; i++)
{
axis_lambda = distances[i] / Vector3.Distance(bones[i].position, bones[i + 1].position);
axis_newVec = (1 - axis_lambda) * bones[i].position + axis_lambda * bones[i + 1].position;
if (!useRotationLimits)
{
bones[i + 1].position = axis_newVec;
continue;
}
if (bones[i].GetComponent<rotationLimitAxis>())
{
rotationLimitAxis rotationScript = bones[i].GetComponent<rotationLimitAxis>();
cur_direction = getDirectionFromAxis(bones[i], rotationScript.axisX, rotationScript.axisY, rotationScript.axisZ);
Vector3 normedAxis_newVec = axis_newVec - bones[i].position;
Vector3 normedAngleVec = rotationScript.angleVec - bones[i].position;
Vector3 normedLimitVec = rotationScript.limitVec - bones[i].position;
if (SignedVectorAngle(normedAxis_newVec.normalized, normedAngleVec.normalized, cur_direction) < 0)
{
bones[i + 1].position = bones[i].position + (rotationScript.angleVec - bones[i].position).normalized * distances[i];
continue;
}
if (SignedVectorAngle(normedAxis_newVec.normalized, normedLimitVec.normalized, cur_direction) > 0)
{
bones[i + 1].position = bones[i].position + (rotationScript.limitVec - bones[i].position).normalized * distances[i];
continue;
}
}
bones[i + 1].position = axis_newVec;
}
}
Your answer

Follow this Question
Related Questions
Angle between player and rocket targetting player. 1 Answer
Global Rotation of a Vector Around an Object 0 Answers
Angle Of Ray 2 Answers
Vector3.Angle() Never Reaching 0 1 Answer
Angle between vectors - calculation 2 Answers