# Clamp view direction vector to nearest axis

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).

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)

• 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. Commented Sep 14, 2015 at 19:26
• Good point about the (0,0,0) or (1,0,1), or (-1,0,-1) etc. vectors. I haven't thought about that case! Commented Sep 14, 2015 at 19:52
• 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... Commented Sep 15, 2015 at 16:09

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;
}

• 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° :) Commented Sep 14, 2015 at 17:37