1
\$\begingroup\$

In JMonkeyEngine, given any view direction Vector3f instance, I'd like to get a new vector facing the nearest x or z axis (positive or negative), with y set to 0.

For example

[-0.99915564, -0.036672898, -0.018518358]
// -> should return [-1, 0, 0]

[-0.01313778, 0.042407744, 0.99901414]
// -> should return [0, 0, 1]

Is there a nifty math trick for this or do I need to manually check x and z and then set y to 0?

Thanks.

Update

So far, what I do is this

dir.x = dir.x >= 0 ? Math.floor(dir.x + 0.5) : Math.ceil(dir.x - 0.5);
dir.y = 0;
dir.z = dir.z >= 0 ? Math.floor(dir.z + 0.5) : Math.ceil(dir.z - 0.5);

Which produce the desired output. I was wondering if this can be done in a more elegant fashion (i.e. through some nifty matrix operation).

\$\endgroup\$
1
\$\begingroup\$

There is (IMO) nothing wrong with your general approach. The function is nonlinear, so there's going to be some involvement of {if ?: abs sgn floor ceil} or the like somewhere.

Your code won't work quite right though. Won't (0.707, 0, 0.707) snap to (1,0,1)? Similarly, (0.44, 0.9, 0.0) would snap to (0,0,0).

There's four possible results, which can checked as:

if(abs(dir.x) > abs(dir.z)) 
{
    return dir.x < 0 ? Vector3f(-1,0,0) : Vector3f(+1,0,0);
}
else
{
    return dir.z < 0 ? Vector3f(0,0,-1) : Vector3f(0,0,+1);
} 

(pardon if the language syntax is wrong)

\$\endgroup\$
  • \$\begingroup\$ Further notes -- the above code does NOT require a normalized dir vector. The above code will choose arbitrary for ambiguous cases like 45 degrees along XZ plane, or straight up on Y. \$\endgroup\$ – david van brink Sep 14 '15 at 19:26
  • \$\begingroup\$ Good point about the (0,0,0) or (1,0,1), or (-1,0,-1) etc. vectors. I haven't thought about that case! \$\endgroup\$ – Yanick Rochon Sep 14 '15 at 19:52
  • 1
    \$\begingroup\$ For my game I was doing something similar. Given a 3x3 rotation matrix, find the closest of the 6 axes (or 24 orientations!) to it. The solution turns out to be the same: Look for the biggest (abs magnitude) element in each column of the matrix... \$\endgroup\$ – david van brink Sep 15 '15 at 16:09
0
\$\begingroup\$

I guess you could compare the dot product with each axis?

Something like..

Vector3f xDir(-1, 0, 0);
Vector3f zDir(0, 0, 1);

Vector3f getClosestViewDir(Vector3f myDir)
{

    if(myDir.dot(xDir) > myDir.dot(zDir))
    {
        return xDir;
    }

    return zDir;
}
\$\endgroup\$
  • \$\begingroup\$ But you're comparing only two vectors, I should've put 4 examples to be clearer, I guess? There are 2 axises, but 4 directions for 360° :) \$\endgroup\$ – Yanick Rochon Sep 14 '15 at 17:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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