I have created a procedural low poly rock mesh and now I would like to apply textures on it.
I have the 3D-coordinates of every vertex of the mesh but that's about it. How would I automatically generate a UV map for this mesh, since this list of vertices will change every time I generate a rock? How do I get all these faces correctly mapped in a (1,1) square?
I am working in Unity3D if that helps.
Thanks,
Alex
EDIT: Preserving the face shapes/sizes is priority! I don't want distortion at all. The texture will be generally just the same color with some darker/lighter spots so every edge could be used as a seam. Faces can overlap! I just want all the faces in one 2D box (1,1), with the correct dimensions.
EDIT 2:
I have this code:
Vector3[] verts = mesh.vertices;
Vector2[] uvs = new Vector2[verts.Length];
for (int i = 0; i < uvs.Length; i++)
{
uvs[i] = new Vector2(Mathf.Abs(verts[i].x), Mathf.Abs(verts[i].z));
}
Which gives me the following UV map: [![enter image description here][2]][2]
EDIT 3:
float scaleFactor = 0.5f;
int[] tris = mesh.triangles;
Vector3[] verts = mesh.vertices;
Vector2[] uvs = new Vector2[verts.Length];
// Iterate over each face (here assuming triangles)
for(int index = 0; index < tris.Length; index += 3)
{
// Get the three vertices bounding this triangle.
Vector3 v1 = verts[tris[index]];
Vector3 v2 = verts[tris[index + 1]];
Vector3 v3 = verts[tris[index + 2]];
// Compute a vector perpendicular to the face.
Vector3 normal = Vector3.Cross(v3 - v1, v2 - v1);
Debug.Log("surface " + index/3 + " : " + (normal*0.5f).magnitude);
// Form a rotation that points the z+ axis in this perpendicular direction.
// Multiplying by the inverse will flatten the triangle into an xy plane.
Quaternion rotation = Quaternion.Inverse(Quaternion.LookRotation(normal));
// Assign the uvs, applying a scale factor to control the texture tiling.
uvs[tris[index]] = (Vector2)(rotation * v1) * scaleFactor;
uvs[tris[index + 1]] = (Vector2)(rotation * v2) * scaleFactor;
uvs[tris[index + 2]] = (Vector2)(rotation * v3) * scaleFactor;
}
The red triangle on the left and the dark blue one on the right should be the same shape/size:
EDIT 4:
Mesh mesh = new Mesh();
mesh.name = "RockMesh";
List<int> Triangles = new List<int>();
var vertices = Vertices.Select(x => new Vertex(x)).ToList();
var result = MIConvexHull.ConvexHull.Create(vertices);
mesh.vertices = result.Points.Select(x => x.ToVec()).ToArray();
var xxx = result.Points.ToList();
foreach(var face in result.Faces)
{
Triangles.Add(xxx.IndexOf(face.Vertices[0]));
Triangles.Add(xxx.IndexOf(face.Vertices[1]));
Triangles.Add(xxx.IndexOf(face.Vertices[2]));
}
mesh.triangles = Triangles.ToArray();
EDIT 5:
I had to move the code a bit but it finally works now! Like you guys predicted, the seems are not optimal, but I'm happy how it is now. Thanks!