- Home /
[Solved] Issues mapping procedurally generated cube without repeating vertices
Having an issue UV mapping a procedurally generated cube without duplicate vertices (Generated through rings and then top and bottom covers (not 6 quads lined up with each other)). Get the triangles where I'm reusing vertices all stretched. I'm assuming it's because the map is wrapping all the way back from where it currently is to the vertex it wants. Does anyone know a solution where I can keep my array without duplicating vertices and not get that image distortion?
//Creates vertices
protected void CreateVertices()
{
int cornerVertices = 8;
int edgeVertices = (gridSize + gridSize + gridSize - 3) * 4;
int faceVertices = (
(gridSize - 1) * (gridSize - 1) +
(gridSize - 1) * (gridSize - 1) +
(gridSize - 1) * (gridSize - 1)) * 2;
vertices = new Vector3[cornerVertices + edgeVertices + faceVertices];
normals = new Vector3[vertices.Length];
uvs = new Vector2[vertices.Length];
int v = 0;
for (int y = 0; y <= gridSize; y++)
{
for (int x = 0; x <= gridSize; x++)
{
SetVertex(v++, x, y, 0, FRONT);
}
for (int z = 1; z <= gridSize; z++)
{
SetVertex(v++, gridSize, y, z, RIGHT);
}
for (int x = gridSize - 1; x >= 0; x--)
{
SetVertex(v++, x, y, gridSize, BACK);
}
for (int z = gridSize - 1; z > 0; z--)
{
SetVertex(v++, 0, y, z, LEFT);
}
}
//Top face
for (int z = 1; z < gridSize; z++)
{
for (int x = 1; x < gridSize; x++)
{
SetVertex(v++, x, gridSize, z, TOP);
}
}
//Bottom face
for (int z = 1; z < gridSize; z++)
{
for (int x = 1; x < gridSize; x++)
{
SetVertex(v++, x, 0, z, BOTTOM);
}
}
mesh.vertices = vertices;
mesh.normals = normals;
mesh.uv = uvs;
}
//Function call to set Vertex and UV coords
protected void SetVertex(int i, int x, int y, int z, int face = 10)
{
Vector3 v = new Vector3(x, y, z) * 2f / gridSize - Vector3.one;
float x2 = v.x * v.x;
float y2 = v.y * v.y;
float z2 = v.z * v.z;
Vector3 s;
s.x = v.x * Mathf.Sqrt(1f - y2 / 2f - z2 / 2f + y2 * z2 / 3f);
s.y = v.y * Mathf.Sqrt(1f - x2 / 2f - z2 / 2f + x2 * z2 / 3f);
s.z = v.z * Mathf.Sqrt(1f - x2 / 2f - y2 / 2f + x2 * y2 / 3f);
normals[i] = s;
vertices[i] = v; //Map a cube
switch (face)
{
case 0:
uvs[i] = new Vector2(vertices[i].x, vertices[i].z);
break;
case 5:
uvs[i] = new Vector2(vertices[i].x , -vertices[i].z);
break;
case 1:
uvs[i] = new Vector2(vertices[i].x, vertices[i].y);
break;
case 3:
uvs[i] = new Vector2(-vertices[i].x, vertices[i].y);
break;
case 2:
uvs[i] = new Vector2(vertices[i].z, vertices[i].y);
break;
case 4:
uvs[i] = new Vector2(-vertices[i].z, vertices[i].y);
break;
default:
break;
}
vertices[i] = normals[i] * radius; //Make it a sphere now that it's mapped
}
If you set your texture to use point filtering (none) rather than bilinear or trilinear, do you still experience the same problem?
Yes I do. Just lower or higher quality. Clamping texture breaks it. I'm pretty sure it has to do with how I'm referencing the vertices, but no idea how to fix
Hmm... as a second possibility, then, it may be that your UVs are connected to each other around those cube face divisions. I can't guarantee anything where the texture seam appears between two faces with the same alignment (top and right of the visible three in the image), but if the uvs are connected, then it may be that the edges of the uvs are stretched across the entire uv map.
If that is the case, then this script should help make what you're seeing more obvious. With a view of the UVs, you'll be able to see whether everything looks organized and aligned or if some of the vertices:
// C#
// ViewUVs.cs
using UnityEngine;
using System.Collections;
[ExecuteInEdit$$anonymous$$ode]
public class ViewUVs : $$anonymous$$onoBehaviour
{
[SerializeField]
$$anonymous$$esh m;
[SerializeField]
int[] t;
[SerializeField]
Vector2[] uv;
public Vector3 position = new Vector3(0, 0, 0);
public float scale = 5.0f;
public float rotationAngle = 0;
public Vector3 rotationAxis = Vector3.up;
void Start()
{
if(gameObject.GetComponent<$$anonymous$$eshFilter>() == null)
{
Debug.LogError("$$anonymous$$eshFilter not found! Script not added to object.");
DestroyImmediate(this);
}
else
{
m = gameObject.GetComponent<$$anonymous$$eshFilter>().shared$$anonymous$$esh;
t = m.triangles;
uv = m.uv;
position = transform.position + (Vector3.up * 5);
}
}
void OnDrawGizmos()
{
Quaternion rotation = Quaternion.AngleAxis(rotationAngle, rotationAxis.normalized);
for(int i = 0; i < t.Length; i += 3)
{
Gizmos.DrawLine(position + (rotation * new Vector3(uv[t[i]].x, uv[t[i]].y, 0)) * scale, position + (rotation * new Vector3(uv[t[i + 1]].x, uv[t[i + 1]].y, 0)) * scale);
Gizmos.DrawLine(position + (rotation * new Vector3(uv[t[i + 1]].x, uv[t[i + 1]].y, 0)) * scale, position + (rotation * new Vector3(uv[t[i + 2]].x, uv[t[i + 2]].y, 0)) * scale);
Gizmos.DrawLine(position + (rotation * new Vector3(uv[t[i + 2]].x, uv[t[i + 2]].y, 0)) * scale, position + (rotation * new Vector3(uv[t[i]].x, uv[t[i]].y, 0)) * scale);
}
}
}
Just want to add that i've created such a script several times now ^^. Here's one of them:
http://answers.unity3d.com/answers/1078038/view.html
You can't create a sphere / cube without any duplicated vertices if you want to individually want to UV map each side. A UV seam requires it's own unique vertices.
The script i've made creates an arbitrary large sphere mesh which is split in at least 6 seperate meshes (or even more if needed) to overcome Unity's vertex limit per mesh.
If you want to fix your code you might want to reduce your GridSize drastically for debugging (to lets say 2 or 3). That way it should be more clear which triangle references which vertices.
Your for loops look suspicious as some go to gridsize and some to (gridsize-1). And the z loop only down to 1 and not 0.
It's hard to tell where it went wrong especially you haven't included the triangle generation.
Yea that solution is way better than finding a solution to this problem. I could explain why I went about it the way I did but since the UV can't be created for it, no point. This also sets things so that I can separate mesh into chunks. Thank you for the insight and putting an end to my search.