/// <summary> /// Returns the position of the nearest vertex. /// </summary> /// <returns> /// Grid position of the nearest vertex. /// </returns> /// /// <param name="grid"> /// The rectangular grid instance. /// </param> /// <param name="point"> /// Point in world space. /// </param> /// <param name="system"> /// Coordinate system to use. /// </param> /// /// <remarks> /// Returns the position of the nearest vertex from a given point in /// either grid- or world space. /// </remarks> public static Vector3 NearestVertex(this RectGrid grid, Vector3 point, CSystem system) { var gridPoint = grid.WorldToGrid(point); var roundedPoint = RoundVector3(gridPoint); return(system == CSystem.Grid ? roundedPoint : grid.GridToWorld(roundedPoint)); }
/// <summary> /// Aligns a <c>Transform</c> onto the grid. /// </summary> /// <param name="grid"> /// The grid instance to extend. /// </param> /// <param name="transform"> /// The <c>Transform</c> to align. /// </param> /// <remarks> /// <para> /// The exact position depends on the scale of the /// <c>Transform</c>, i.e. whether it's an even or odd multiple of /// the grid's spacing. /// </para> /// </remarks> public static void AlignTransform(this RectGrid grid, Transform transform) { var position = transform.position; var scale = transform.lossyScale; transform.position = AlignVector3(grid, position, scale); }
/// <summary> /// Returns the grid position of the nearest box. /// </summary> /// <returns> /// Grid position of the nearest box. /// </returns> /// <param name="grid"> /// The rectangular grid instance. /// </param> /// <param name="point"> /// Point in world space. /// </param> /// <param name="system"> /// Coordinate system to use. /// </param> /// <remarks> /// <para> /// returns the coordinates of a cell in the grid. Since cell lies /// between vertices all three values will always have +0.5 /// compared to vertex coordinates. /// </para> /// </remarks> /// <example> /// <code> /// GFRectGrid myGrid; /// Vector3 worldPoint; /// // something like (2.5, -1.5, 3.5) /// Vector3 box = myGrid.NearestBoxG(worldPoint); /// </code> /// </example> public static Vector3 NearestCell(this RectGrid grid, Vector3 point, CSystem system) { var shift = .5f * Vector3.one; var gridPoint = grid.WorldToGrid(point); var shifted = gridPoint - shift; var rounded = RoundVector3(shifted); var gridCell = rounded + shift; return(system == CSystem.Grid ? gridCell : grid.GridToWorld(gridCell)); }
/// <summary> /// Scales a size-vector to fit inside the grid. /// </summary> /// <returns> /// The re-scaled vector. /// </returns> /// <param name="grid"> /// The instance of the grid to extend. /// </param> /// <param name="vector"> /// The vector to scale. /// </param> /// <remarks> /// <para> /// Scales a size to the nearest multiple of the grid’s spacing. /// This ignores the grid's shearing and the result might look /// wrong if shearing is used, depending on what you want to /// achieve. /// </para> /// </remarks> public static Vector3 ScaleVector3(this RectGrid grid, Vector3 vector) { var spacing = grid.Spacing; for (int i = 0; i < 3; ++i) { vector[i] = Mathf.Round(vector[i] / spacing[i]) * spacing[i]; // If the vector has been rounded down to zero. vector[i] = Mathf.Max(vector[i], spacing[i]); } return(vector); }
/// <summary> /// Scales a <c>Transform</c> to fit inside the grid. /// </summary> /// <param name="grid"> /// The instance of the grid to extend. /// </param> /// <param name="transform"> /// The <c>Transform</c> to scale. /// </param> /// <remarks> /// <para> /// This method scales the <c>Transform</c> globally, which will /// work without issues if the <c>Transform</c> is not a child or a /// child but not rotated. However, if it is a rotated child of /// another <c>Transform</c> all the caveats of /// <c>Transform.lossyScale</c> apply. /// </para> /// </remarks> public static void ScaleTransform(this RectGrid grid, Transform transform) { var scale = ScaleVector3(grid, transform.lossyScale); var parent = transform.parent; if (!parent) { transform.localScale = scale; return; } var localScale = transform.localScale; for (int i = 0; i < 3; ++i) { localScale[i] = scale[i] / parent.localScale[i]; } transform.localScale = localScale; }
/// <summary> /// Aligns a position vector onto the grid. /// </summary> /// <param name="grid"> /// The grid instance to extend. /// </param> /// <param name="vector"> /// The position in world-coordinates. /// </param> /// <param name="scale"> /// Used to determine whether to align to a cell or an edge, see /// remarks. /// </param> /// <returns> /// Position of the nearest face. /// </returns> /// <remarks> /// <para> /// The position will be interpreted to be the position of an /// object that has the size <c>scale</c>. If the scale in an odd /// multiple of the grid's spacing the position will be aligned to /// an edge, otherwise to a cell. /// </para> /// </remarks> public static Vector3 AlignVector3(this RectGrid grid, Vector3 vector, Vector3 scale) { const CoordinateSystem system = CoordinateSystem.Grid; var vertex = grid.NearestVertex(vector, system); var cell = grid.NearestCell(vector, system); var spacing = grid.Spacing; var aligned = new Vector3(); for (var i = 0; i < 3; ++i) { var fraction = Mathf.Max(scale[i] / spacing[i], 1f); var even = Mathf.RoundToInt(fraction) % 2 == 0; aligned[i] = even ? vertex[i] : cell[i]; } return(grid.GridToWorld(aligned)); }
/// <summary> /// Aligns a position vector onto the nearest face of the grid. /// </summary> /// <param name="grid"> /// The grid instance to extend. /// </param> /// <param name="vector"> /// The position in world-coordinates. /// </param> /// <returns> /// Position of the nearest face. /// </returns> /// <remarks> /// <para> /// The position will be interpreted to be the position of an /// object that happens to fit exactly into a grid cell. /// </para> /// </remarks> public static Vector3 AlignVector3(this RectGrid grid, Vector3 vector) { var scale = Vector3.one; return(AlignVector3(grid, vector, scale)); }