- Home /
Snap a direction vector
I have a vector3 direction (target.position - transform.position) which I'd like to snap along the y-axis to 8 directions so that it can be any direction x and z, but be snapped to the nearest 45 degrees on the y.
I've tried many different things like converting the vector to a quaternion, then to a euler, and trying to snap those values and putting them back into a vector but getting half working results. Trying to snap the quaternion itself instead of converting it to euler angles, but getting strange results that snap correctly at certain angles and completely go off in a different direction on other angles.
I'm pretty bad at math so I'd like to at least know the correct way to do this, and if you're feeling generous, some pseudocode as well.
Here are the few things I've tried
Find the angle between the direction and down vector (0,-1,0)
Check if that angle is closer to 0 or 45 (angle % 45 == closer to 0 or 45) (this works correctly so far using two if statements)
Attempt to rotate the Vector3. "snappedDirection = Quaternion.AngleAxis(angle % 45, Vector3.up) * originalDirection;"
Attempt being the keyword here. This only half works, and I could probably get it working if I had some help understanding the correct way to use Quaternions to rotate vectors.
Convert direction to Quaternion using LookRotation, then convert to Euler.
Snap those Euler angles using same method.
Convert back to to Quaternion, then multiply by Vector3 axis used during LookRotation (up vector) This one works on one side, but not the other, and probably won't ever work the way I'm doing it since I lose data when compressing the Quaternion into a Euler or something like that.
I've been stuck on this for over two days and am in a rut, getting frustrated here. Any help at all would be greatly appreciated, thanks!
Edit: Here is code of the first attempt I described above. It doesn't work properly but should show what I'm trying to achieve.
float num = Vector3.Angle(oDirection, Vector3.up);
float snapAngle = 360 / angles;
if (num % snapAngle > 0 && num % snapAngle < snapAngle / 2)
{
newDirection = Quaternion.AngleAxis(num % snapAngle, Vector3.up) * oDirection;
}
else if (num % snapAngle < snapAngle && num % snapAngle > snapAngle / 2)
{
newDirection = Quaternion.AngleAxis(snapAngle - (num % snapAngle), Vector3.up) * oDirection;
}
Basically I have an "explosion" that sends force, but I want to limit that force vertically so that the objects would only receive force at an angle of 0/45/90/.../315 degrees. However the objects should still be pushed sideways at any angle. Please refer to my crude drawings.
I'll be glad to help if you can explain more about the problem. A drawing would help. When you say "snapped to the nearest45 degrees on the y" I visualized using the 'y' as an axis and snapping to angles on this axis. But further you say "find the angle between the direction and the down vector", which does not map very well to my understanding. So what world axis is the axis of rotation for the vector?
Yeah the question doesn't make much sense. Show some code of what you are doing now.
I apologize, I have added some of my actual code and an image to hopefully demonstrate my goal.
Answer by robertbu · Jul 15, 2013 at 01:29 AM
Here is a SnapTo() methods that snaps the vector to the specified angle. It works by generating the cross product between the direction and Vector3.up to create an axis for rotation. Then it does an AngleAxis rotation to snap the vector to the angle.
Vector3 SnapTo(Vector3 v3, float snapAngle) {
float angle = Vector3.Angle (v3, Vector3.up);
if (angle < snapAngle / 2.0f) // Cannot do cross product
return Vector3.up * v3.magnitude; // with angles 0 & 180
if (angle > 180.0f - snapAngle / 2.0f)
return Vector3.down * v3.magnitude;
float t = Mathf.Round(angle / snapAngle);
float deltaAngle = (t * snapAngle) - angle;
Vector3 axis = Vector3.Cross(Vector3.up, v3);
Quaternion q = Quaternion.AngleAxis (deltaAngle, axis);
return q * v3;
}
The cross product for the rotation axis! Oh my god I'm so dumb I can't believe I forgot that already. Looks like the maths units I did have completely gone to waste hahaha!
Hey Robert, could you take a look at this post? It's based on this answer but with a small tweak that I'm in need of to shift the snap angles.
https://answers.unity.com/questions/1629211/snap-direction-to-angles-shifting.html