Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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;
share|improve this question
    
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. –  teodron Sep 20 '12 at 15:11

1 Answer 1

up vote 3 down vote accepted

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
}
share|improve this answer
    
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. –  Heisenbug Sep 20 '12 at 15:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.