- Home /
Round a Vector3 to a grid position?
I need to round a Vector3 so each value is rounded to place it on a point in a 2x2 grid.
I figure I can do it by Mathf.RoundToInt on x\y\z and then use %, but that seems bulky.
Answer by Bunny83 · Mar 18, 2011 at 03:34 AM
What grid size do you use? You talk about gird intersections but can you tell us the grid step size and min max values? Because there's always a problem if you want +- values. Around "0" the rounding direction will change. It's mirrored at the origin.
In most cases it's enough to devide your value be a grid unit, add 0.5 and truncate the value (just cast it to int). If it's rounded you have grid coordinates which you multiply again with the grid unit size.
examples(grid size 2.5):
start: 12.2 | 5.1 | 24.1
step1: 4.88 | 2.04 | 9.64 // devided by 2.5
step2: 5.38 | 2.54 | 10.14 // + 0.5
step3: 5 | 2 | 10 // truncated: x = (int)x; // C#
step4: 12.5 | 5 | 25 // multiplied by 2.5
In C# it could look like:
float GridSize = 2.5f; float V = 12.2f;
V = (int)(V/GridSize + 0.5f); V *= GridSize;
In JS it would be:
var GridSize = 2.5;
var V = 12.2;
V = parseInt(V/GridSize + 0.5f);
V *= GridSize;
ps. haven't tested those two snippets, they can contain syntax errors but they should be ok.
edit
Just tried it and that's my little test class I end up with:
public class GridSnap : MonoBehaviour { public float offset = 1.0f; public float gridSize = 4.0f; private Plane plane;
void Start ()
{
plane = new Plane(new Vector3(0,0,5),new Vector3(1,0,5),new Vector3(0,1,5));
}
void Update ()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float hit = 0.0f;
if (plane.Raycast(ray, out hit))
{
Vector3 V = ray.GetPoint(hit);
V -= Vector3.one * offset;
V /= gridSize;
V = new Vector3(Mathf.Round(V.x), Mathf.Round(V.y), Mathf.Round(V.z));
V *= gridSize;
V += Vector3.one * offset;
transform.position = V;
}
}
}
In this example i use the same grid size and the same offset for each axis. With the current settings (grid 4 offset 1) i'll get values like: -3 | 1 | 5 | 9 | 13.
Mathf.Round works correct around 0 and it rounds exactly between two grid lines.
3.001 becomes 5
2.999 becomes 1
But if you have a working solution and you're happy with the result, keep it ;)
I'll give this a try. $$anonymous$$y current grid size is 4x4.
It works but I'm still having a hard time figuring out how to offset the grid.
This worked: int x = $$anonymous$$athf.CeilToInt(hit.point.x/GRID_SIZE); int y = $$anonymous$$athf.CeilToInt(hit.point.y/GRID_SIZE); int z = $$anonymous$$athf.CeilToInt(hit.point.z/GRID_SIZE);
marker.transform.position = new Vector3(x*GRID_SIZE-GRID_SIZE/2, hit.point.y+1, z*GRID_SIZE-GRID_SIZE/2);
marker.renderer.enabled = true;
markerBase.transform.position = new Vector3(x*GRID_SIZE-GRID_SIZE/2, hit.point.y, z*GRID_SIZE-GRID_SIZE/2);
markerBase.renderer.enabled = true;
Any offsets should be subtracted before the clamping and added again after the calculation. If you have a gridsize of 4 but the first value should be 1 and not 0: subtract 1 then do the calculation and after that add it again.
Cool. Tweaked a bit to fit my code, but your second function works great. Thanks.
Answer by DaveA · Mar 18, 2011 at 02:03 AM
You shouldn't have to RoundToInt, % takes care of that (I'm told)
I think that I need to round so that it snaps to the nearest point on the grid, not the least point. 23.5%2 = 1.5, 23.5-1.5 = 22. $$anonymous$$athf.RoundToInt(23.5) = 24, 24-24%2=24.
$$anonymous$$y problem now is that this snaps it to the intersections on the grid, when I really want to place the gameObject in the middle of the grid square.