Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Creating UV for partial cube

Discussion in 'Scripting' started by cel6586, May 24, 2024.

  1. cel6586

    cel6586

    Joined:
    May 8, 2018
    Posts:
    21
    I have this code that creates a partial cube and tries to create the UVs, but it fails at creating the Uvs. Would anyone know how to properly create a cube with only a few of its faces and generate the Uv for them?


    Code (CSharp):
    1. static void CreateCube()
    2.     {
    3.  
    4.         GameObject gameObject = new GameObject("Cube");
    5.         gameObject.AddComponent<MeshFilter>();
    6.         gameObject.AddComponent<MeshRenderer>();
    7.  
    8.         Mesh mesh = new Mesh();
    9.         gameObject.GetComponent<MeshFilter>().sharedMesh = mesh;
    10.         mesh.Clear();
    11.  
    12.         List<Vector3> vertices = new List<Vector3>();
    13.         List<int> triangles = new List<int>();
    14.  
    15.         // Front face
    16.         AddFace(vertices, triangles, Vector3.zero, Vector3.right, Vector3.up);
    17.  
    18.    
    19.         // Bottom face
    20.         AddFace(vertices, triangles, Vector3.zero, Vector3.right, Vector3.forward, true);
    21.  
    22.  
    23.         // Right face
    24.         AddFace(vertices, triangles, Vector3.right, Vector3.up, Vector3.forward);
    25.  
    26.         mesh.vertices = vertices.ToArray();
    27.         mesh.triangles = triangles.ToArray();
    28.  
    29.         mesh.RecalculateNormals();
    30.         mesh.RecalculateBounds();
    31.         AutoUnwrap(gameObject);
    32.  
    33.     }
    34.  
    35.     static void AddFace(List<Vector3> vertices, List<int> triangles, Vector3 origin, Vector3 u, Vector3 v, bool reverse = false)
    36.     {
    37.         int startIndex = vertices.Count;
    38.  
    39.         // Add vertices for the face
    40.         vertices.Add(origin);
    41.         vertices.Add(origin + u);
    42.         vertices.Add(origin + u + v);
    43.         vertices.Add(origin + v);
    44.  
    45.         // Determine triangle winding order
    46.         if (reverse)
    47.         {
    48.             triangles.Add(startIndex);
    49.             triangles.Add(startIndex + 2);
    50.             triangles.Add(startIndex + 1);
    51.  
    52.             triangles.Add(startIndex);
    53.             triangles.Add(startIndex + 3);
    54.             triangles.Add(startIndex + 2);
    55.         }
    56.         else
    57.         {
    58.             triangles.Add(startIndex);
    59.             triangles.Add(startIndex + 1);
    60.             triangles.Add(startIndex + 2);
    61.  
    62.             triangles.Add(startIndex);
    63.             triangles.Add(startIndex + 2);
    64.             triangles.Add(startIndex + 3);
    65.         }
    66.     }
    67.  
    68. static void AutoUnwrap(GameObject go)
    69.     {
    70.         var mesh = go.GetComponent<MeshFilter>().mesh;
    71.         var a = Unwrapping.GeneratePerTriangleUV(mesh);
    72.         int count = 0;
    73.         foreach (var i in a)
    74.         {
    75.            
    76.             count = count + 1;
    77.         }
    78.         mesh.uv = a;
    79.     }
     
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,190
    Do you understand how UV mapping actually works? Each vertex has a UV coordinate associated which specifies which part of the texture is mapped to this corner. You do this for every corner and the triangles between the vertices are interpolated.

    Some time ago I made this WebGL example that might help to better understand how UV coordinates work. This actually is a partial cube (just 3 faces) and you can select one by pressing the corresponding select button. You can then "move" the 4 UV coorddinates in texture space. You will see the resulting mapping in the 3d model.

    UV coordinates are in the range 0 to 1 and correspond to the texture. (0,0) is usually the bottom left corner of the texture while (1,1) is the top right corner.

    If you use some kind of texture atlas, you have to map your quad to your desired portion of the texture. That may be the full texture or just a sub portion. You can play with my example to get a better understanding how UV mapping works.

    We don't know what you actually want to map to your quads, so that's something you have to figure out. "GeneratePerTriangleUV" is a pretty useless method. When you have a complex model, unwrapping can be a quite complex topic and can almost never be done automatically as there's not just one way how you may want to map a texture onto a triangle.
     
  3. cel6586

    cel6586

    Joined:
    May 8, 2018
    Posts:
    21
    Yes I know how UV coordinates work, but creating them manually in code is bit complex and confusing in unity. If I create a full box with 6 sides, then "GeneratePerTriangleUV" actually does work ,and will map out all 6 sides and layout the UVS across the 0 to 1 space. With my current problem I have a partial cube in which I do not know beforehand which faces will be generated and I am trying to layout the UVs of all the partial cube across the 0 to 1 space, with each UV matching the shape of its face (doesn't matter where, just needs to maximize the space. I have a feeling I am doing something wrong when creating the partial cube but not sure.
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,190
    I don't quite get this. This works the same everywhere and isn't Unity specific. In your AddFace method you add 4 vertices in a particular order. You even use your two direction vectors and you called then u and v. For each vertex you would add a uv coordinates that matches the "relative" position.

    So something like this:

    Code (CSharp):
    1.     static void AddFace(List<Vector3> vertices, List<Vector2> uvs, List<int> triangles, Vector3 origin, Vector3 u, Vector3 v, bool reverse = false)
    2.     {
    3.         int startIndex = vertices.Count;
    4.         // Add vertices for the face
    5.         vertices.Add(origin);
    6.         vertices.Add(origin + u);
    7.         vertices.Add(origin + u + v);
    8.         vertices.Add(origin + v);
    9.  
    10.         uvs.Add(new Vector2(0, 0));
    11.         uvs.Add(new Vector2(1, 0));
    12.         uvs.Add(new Vector2(1, 1));
    13.         uvs.Add(new Vector2(0, 1));
    14.         // [ ... ]
    15.  
    ps: Usually it would make sense to create most of your vertex attributes manually. So usually we would also create a "normals" list at the same time and for quads all 4 vertices would have the same normal.

    Note that the mesh class now has methods like SetVertices which directly take a List. So no need to convert to an array
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,368
    Last edited: May 25, 2024
    Bunny83 likes this.