1
\$\begingroup\$

I read this post explaining a method to understand if the angle between 2 given vectors and the normal to the plane described by them, is clockwise or anticlockwise:

public static AngleDir GetAngleDirection(Vector3 beginDir, Vector3 endDir, Vector3 upDir)
{
    Vector3 cross = Vector3.Cross(beginDir, endDir);

    float dot = Vector3.Dot(cross, upDir);

    if (dot > 0.0f)
        return AngleDir.CLOCK;
    else if (dot < 0.0f)
        return AngleDir.ANTICLOCK;
    return AngleDir.PARALLEL;
}

After having used it a little bit, I think it's wrong. If I supply the same vector as input (beginDir equal to endDir), the cross product is zero, but the dot product is a little bit more than zero.

I think that to fix that I can simply check if the cross product is zero, means that the 2 vectors are parallel, but my code doesn't work.

I tried the following solution:

Vector3 cross = Vector3.Cross(beginDir, endDir);
if (cross == Vector.zero)
    return AngleDir.PARALLEL;

And it doesn't work because comparison between Vector.zero and cross is always different from zero (even if cross is actually [0.0f, 0.0f, 0.0f]).

I tried also this:

Vector3 cross = Vector3.Cross(beginDir, endDir);
if (cross.magnitude == 0.0f)
    return AngleDir.PARALLEL;

it also fails because magnitude is slightly more than zero.

So my question is: given 2 Vector3 in Unity, how to compare them?

I need the elegant equivalent version of this:

if (beginDir.x == endDir.x && beginDir.y == endDir.y && beginDir.z == endDir.z) 
    return true;
\$\endgroup\$
1
  • \$\begingroup\$ Hmm, this doesn't deserve an answer in the sense that you almost stumbled upon the idea yourself. Due to rounding and numerical stability reasons, the "correct" approach resumes to doing something similar to your own magnitude comparison: if (cross.magnitude < epsilon) return AngleDir.PARALLEL where epsiloncan be 1e-5 or some other reasonably small positive floating point value. Or perhaps faster: if (dot(cross, cross) < epsilon*epsilon since no sqrts are involved. \$\endgroup\$
    – teodron
    Sep 20, 2012 at 15:11

1 Answer 1

3
\$\begingroup\$

When working with floating point values it's usually not a good idea to use the comparison operator, as even slight inaccuracies will result in inequality. That's why a comparison of floats usually incorporates some sort of "epsilon".. a margin of error.

Example:

if(Math.abs(floatA - floatB) <= epsilon){
    // equal
}

Epsilon is the desired accuracy.. it's usually a really small number (1E-5 in C++ I believe).

So your check for equality could look like this:

if(Mathf.abs(cross.magnitude) <= Mathf.Epsilon){
    // equal
}
\$\endgroup\$
1
  • \$\begingroup\$ Yes, you are right. I know about float precision. Unfortunately mono wasn't showing the right value while debuggin. Positioning the mouse cursor over the variable, shows cross as [0,0,0]. If I open the panel to inspect it shows the accurate values, that are different from zero. \$\endgroup\$
    – Heisenbug
    Sep 20, 2012 at 15:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .