- Home /
Set vertex positions aligned to a grid
I am creating a mesh and I need my vertices to line up exactly with the grid. How do I find the positions to place the vertices, including the "edge" vertices, so they intersect with any of the grid lines? I suppose there is a mathematical solution to this, but I don't even know where to start looking for an answer. Hope anyone can help.
Here is an explanation of what I have and what I am hoping for:
Image 1 I have the grid. The grid is actually just all the whole number positions, for example Vector2(1,1). I also have the position of the mesh corners (black dots).
Image 2 I want to build the mesh so that all the outer vertices is positioned where the green line intersects with the grid (pink dots). I also need to find all the inner vertices (black dots) and have them positioned according to the grid.
Thank you!
Answer by Ymrasu · Feb 18, 2019 at 05:33 AM
I made your pictures out of gizmos that update in real-time.
Just attach this script to an empty gameobject and hit play! Have fun moving the child and parent gameobjects around. Maybe the maths I used will help you out. This only works for 2 Dimensions!
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
public class MeshCreationHelper : MonoBehaviour
{
GameObject[] dots;
private void Start()
{
dots = new GameObject[4];
for (int i = 0; i < dots.Length; i++) {
dots[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
dots[i].transform.SetParent(transform);
}
dots[0].transform.position = new Vector3(2.5f, 0, 4.5f);
dots[1].transform.position = new Vector3(5.5f, 0, 14.5f);
dots[2].transform.position = new Vector3(12.5f, 0, 10.5f);
dots[3].transform.position = new Vector3(6.5f, 0, 2.5f);
}
private void OnDrawGizmos()
{
if (EditorApplication.isPlaying) {
List<Vector3> points = new List<Vector3>();
// lines
for (int i = 0; i < dots.Length; i++) {
Vector3 A = dots[i].transform.position;
Vector3 B = dots[(i + 1) % dots.Length].transform.position;
Gizmos.color = Color.cyan;
Gizmos.DrawLine(A, B);
var m = (B.z - A.z) / (B.x - A.x);
var b = A.z + (-m * A.x);
// X aligned points
int startX = (A.x < B.x) ? Mathf.CeilToInt(A.x) : Mathf.CeilToInt(B.x);
int finishX = (A.x < B.x) ? Mathf.FloorToInt(B.x) : Mathf.FloorToInt(A.x);
for (int x = startX; x <= finishX; x++) {
float z = (m * x) + b;
Gizmos.color = Color.red;
Gizmos.DrawSphere(new Vector3(x, 0, z), 0.1f);
points.Add(new Vector3(x, 0, z)); // add point for use with grid
}
// Z aligned points
int startZ = (A.z < B.z) ? Mathf.CeilToInt(A.z) : Mathf.CeilToInt(B.z);
int finishZ = (A.z < B.z) ? Mathf.FloorToInt(B.z) : Mathf.FloorToInt(A.z);
for (int z = startZ; z <= finishZ; z++) {
float x = (z - b) / m;
Gizmos.color = Color.red;
Gizmos.DrawSphere(new Vector3(x, 0, z), 0.1f);
}
}
// magic sort... sort vector3's by x pos then y pos
List<Vector3> gridPoints = points.OrderBy(v => v.x).ThenBy(v => v.z).ToList();
for (int i = 0; i < gridPoints.Count; i += 2) {
var x = gridPoints[i].x;
for (int z = Mathf.CeilToInt(gridPoints[i].z); z <= Mathf.FloorToInt(gridPoints[i + 1].z); z++) {
Gizmos.color = Color.black;
Gizmos.DrawSphere(new Vector3(x, 0, z), 0.1f);
}
}
}
}
}
Thank you so much for this! It truly helped me out a lot!
Answer by toddisarockstar · Feb 18, 2019 at 04:14 AM
here is the math you need. this gives the points along the x of your grid. just switch the x's and y's to get the points along the y.
obviosly you run this for every line in your shape
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class linedots : MonoBehaviour {
void Start (){
Vector2[] p = LinePoints (new Vector2 (-5.5f, 8f), new Vector2 (-11.5f, -15));
foreach (Vector2 pp in p) {
print("Point: "+pp);
}
print (p.Length);
}
public Vector2[] LinePoints(Vector2 a,Vector2 b){
float[] x = EvenNumbersBetween (a.x, b.x).ToArray();
float distx = Mathf.Abs (a.x - b.x);
float disty = Mathf.Abs (a.y - b.y);
print ("str" + disty);
Vector2[] r = new Vector2[x.Length];
int i = x.Length;
while(i>0){i--;
r[i].x = x[i];
r[i].y = x[i] - a.x;
Mathf.Abs(r[i].y = r[i].y/distx);
print ("per:"+r[i].y);
Mathf.Abs(r[i].y = disty * r[i].y);
print ("dis:"+r[i].y);
r[i].y += a.y;
}return r;}
public List<float> EvenNumbersBetween (float a, float b) {
float n=0;
if(a>b){n = a; a=b; b=n;}
List<float> r = new List<float> ();
if(n<0){ n = Mathf.Ceil (a);}else{n = Mathf.Floor (a);}
while (n<=b) {
r.Add(n);n++;}
return r;}
}
so to explain the logic behind this... first of all we kinda allready know what all the x coordnates should be in our final vector list. and how many results we should have. the x coordanates are all going to whole numbers. to get the length of our return we just find the amount of whole numbers between the x of point a and the x of point b.
once you have all your x coordinates in your vecors, to get the corresponding y cordinates its a bit tricky. you figure the percentage each new x coordinate is between point a's x and point b's x. then you take that percentage and use it to multiply to the distance between point a's y and point b'y.
in other words if your x coordinate is a quarter of the way between the two black points x's. then the y should also be a quarter of the way between the the black point's y's.
after you have all your lines, and you are looking to output the middle you would use a flood algorithm. if you are doing shapes with only 4 sides there is a shortcuted method you could use. if you have more than 4 sides then you would need another step to for setting up a full flood algo. but this is really another question.
Thank you for this explanation and example! I will use this and try to make my own solution! Great help!
Your answer
Follow this Question
Related Questions
Procedural Mesh Editing Performance 1 Answer
Getting mesh length (x,z) 1 Answer
How can I remove redundant vertices in custom mesh? 0 Answers
Holes in procedural mesh 0 Answers