- Home /
Automatic UV Mapping for a Cube in C#
I'm currently working on creating a cube as a first step for a mild project. The cube renders perfectly fine and there are no colliding issues. However, I am having an issue with setting the UV map without hard-coding every coordinate. I'd like it to generate it within the script. What's an easy way of going about this?
void Start() {
//Make sure the requirements are set. Otherwise, don't run
if(!grassTexture) {
Debug.Log("Failed to start. Update the textures.");
return;
}
//Set the the GameObject so it has the required mesh materials and settings
gameObject.AddComponent("MeshFilter");
gameObject.AddComponent("MeshRenderer");
Mesh mesh = GetComponent<MeshFilter>().mesh;
mesh.Clear();
//Create the vertices for the cube.
mesh.vertices = new Vector3[] {
//front
new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0),
new Vector3(1, 1, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 0),
//back
new Vector3(0, 0, 1), new Vector3(1, 1, 1), new Vector3(0, 1, 1),
new Vector3(1, 1, 1), new Vector3(0, 0, 1), new Vector3(1, 0, 1),
//right
new Vector3(1, 0, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 1),
new Vector3(1, 1, 1), new Vector3(1, 0, 1), new Vector3(1, 1, 0),
//left
new Vector3(0, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 1, 0),
new Vector3(0, 1, 1), new Vector3(0, 1, 0), new Vector3(0, 0, 1),
//top
new Vector3(0, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 0),
new Vector3(1, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 1),
//bottom
new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1),
new Vector3(1, 0, 0), new Vector3(1, 0, 1), new Vector3(0, 0, 1)
};
//Create the uv for the cube
Vector2[] uvs = new Vector2[mesh.vertices.Length];
for(int i = 0; i < uvs.Length; i++) {
uvs[i] = new Vector2(mesh.vertices[i].x, mesh.vertices[i].y);
}
mesh.uv = uvs;
//Add the triangles to render the cube
int[] triangleNumbers = new int[mesh.vertices.Length];
for(int i = 0; i < mesh.vertices.Length; i++)
triangleNumbers[i] = i;
mesh.triangles = triangleNumbers;
//Set the cube's texture and add a collider
renderer.material = grassTexture;
gameObject.AddComponent("MeshCollider");
}
Extra Info: I have tried Unwrapping.GeneratePerTriangleUV()
and Unwrapping.GenerateSecondaryUVSet()
already.
The following combinations properly UV Maps the corresponding sides:
new Vector2(mesh.vertices[i].x, mesh.vertices[i].y)
for front/back
new Vector2(mesh.vertices[i].y, mesh.vertices[i].z)
for left/right
new Vector2(mesh.vertices[i].x, mesh.vertices[i].z)
for top/bottom
The solution shouldn't only work for a cubed shape since I plan on having the shape change in realtime.
Answer by QuaintShanty · Jun 28, 2014 at 07:04 PM
I seem to have found the solution and came up with a theory on how to understand it in multiple instances (such as spheres, triangles, and other shapes).
This is the chunk of code that was changed. The mesh.vertices
was not changed except for the commenting. The mesh.uv
was changed in terms of both logics and commenting. I'd like to post this here for anyone in the future who may come across the same issue as I have.
void Start() {
//...
//Create the vertices for the cube.
mesh.vertices = new Vector3[] {
//front - z (looking at it from the side, this is the coord
//that lets you see how thin the triangle is. Remember this for
//UV mapping. It makes the logic easier.)
new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0),
new Vector3(1, 1, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 0),
//back - z
new Vector3(0, 0, 1), new Vector3(1, 1, 1), new Vector3(0, 1, 1),
new Vector3(1, 1, 1), new Vector3(0, 0, 1), new Vector3(1, 0, 1),
//right - x
new Vector3(1, 0, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 1),
new Vector3(1, 1, 1), new Vector3(1, 0, 1), new Vector3(1, 1, 0),
//left - x
new Vector3(0, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 1, 0),
new Vector3(0, 1, 1), new Vector3(0, 1, 0), new Vector3(0, 0, 1),
//top - y
new Vector3(0, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 0),
new Vector3(1, 1, 0), new Vector3(0, 1, 1), new Vector3(1, 1, 1),
//bottom - y
new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 0, 1),
new Vector3(1, 0, 0), new Vector3(1, 0, 1), new Vector3(0, 0, 1)
};
//Create the uv for the cube
//How this works:
//If a triangle has the same x coords for all 3 coords then it is not visible "always"
// on the x coords. There will come a time where it appears to be a thin line. As such,
// let the UV focus on the other 2 axises.
//The same thing applies for y and z coordonates.
//However, if there are no 3 coords for a triangle that match, the it is visible on both
//The x and y axis at all times so long as the depth(z) doesn't cause it to be hidden(i.e.
//an object in front of it would be the depth). Because of this, the UV should focus on
//x and y at all times.
//Moral of the story? Set the damn UV to the coords where the triangle will be visible mostly, if
//not at all times.
Vector2[] uvs = new Vector2[mesh.vertices.Length];
for(int i = 0; i < uvs.Length;) {
if(mesh.vertices[i].x == mesh.vertices[i+1].x && mesh.vertices[i].x == mesh.vertices[i+2].x) {
uvs[i] = new Vector2(mesh.vertices[i].y, mesh.vertices[i].z);
uvs[i+1] = new Vector2(mesh.vertices[i+1].y, mesh.vertices[i+1].z);
uvs[i+2] = new Vector2(mesh.vertices[i+2].y, mesh.vertices[i+2].z);
}
else
if(mesh.vertices[i].y == mesh.vertices[i+1].y && mesh.vertices[i].y == mesh.vertices[i+2].y) {
uvs[i] = new Vector2(mesh.vertices[i].x, mesh.vertices[i].z);
uvs[i+1] = new Vector2(mesh.vertices[i+1].x, mesh.vertices[i+1].z);
uvs[i+2] = new Vector2(mesh.vertices[i+2].x, mesh.vertices[i+2].z);
}
else
if(mesh.vertices[i].z == mesh.vertices[i+1].z && mesh.vertices[i].z == mesh.vertices[i+2].z) {
uvs[i] = new Vector2(mesh.vertices[i].x, mesh.vertices[i].y);
uvs[i+1] = new Vector2(mesh.vertices[i+1].x, mesh.vertices[i+1].y);
uvs[i+2] = new Vector2(mesh.vertices[i+2].x, mesh.vertices[i+2].y);
}
else {
uvs[i] = new Vector2(mesh.vertices[i].x, mesh.vertices[i].y);
uvs[i+1] = new Vector2(mesh.vertices[i+1].x, mesh.vertices[i+1].y);
uvs[i+2] = new Vector2(mesh.vertices[i+2].x, mesh.vertices[i+2].y);
}
i += 3;
}
mesh.uv = uvs;
//...
}
Your answer
Follow this Question
Related Questions
C# PackTextures & UV Mapping 2 Answers
code generated cube uv map for each sub mesh 1 Answer
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers