I have the following code which accepts a v1 vector and outputs two other vectors to construct an orthonormal base
void CoordinateSystem(const Vector &v1, Vector *v2, Vector *v3)
{
if (fabsf(v1.x) > fabsf(v1.y))
{
// x or y may be 1 so I can't zero-out it or I get invLen = +inf
// if x > y, x might be 1 so I'll zero-out the y
float invLen = 1.f / sqrtf(v1.x*v1.x + v1.z*v1.z);
*v2 = Vector(-v1.z * invLen, 0.f, v1.x * invLen);
}
else
{
// Zero-out the y
float invLen = 1.f / sqrtf(v1.y*v1.y + v1.z*v1.z);
*v2 = Vector(0.f, v1.z * invLen, -v1.y * invLen);
}
*v3 = Cross(v1, *v2);
}
I understand why the if-else clauses have been put there (the risk is to zero-out a coordinate which may be 1 and cause invLen = 1/sqrt(0) = inf) and I understand I need to swap the two non-zero coordinates to get v2 as a perpendicular vector to v1, but I don't understand why the v2 vector has one of the two signs changed (-v1.z*invLen in the first branch and -v1.y*invLen in the second branch)
Is that necessary?
Edit: it seems that leaving the sign unchanged it's totally the same.. I obtain another left-handed base perfectly valid. I think there's no reason in that..
Yes, the sign change is necessary. Two vectors are orthogonal when their dot product is zero. We have $(x,y,z)\cdot(-z,0,x)=-xz+0+zx=0$, but $(x,y,z)\cdot(z,0,x)=xz+0+zx=2xz$, which is not zero in general.