Search Unity

Mesh material problem

Discussion in 'Scripting' started by itsDmajster, Jan 26, 2015.

  1. itsDmajster

    itsDmajster

    Joined:
    Oct 27, 2014
    Posts:
    45
    I am making procedural terrain and now that i made the mesh for it ( vertices , normals , triangles ) i applied a material to it, for some reason the materials mesh unwraps correctly to the mesh except for 2 black lines on top and bottom of the texture. [SEE PICTURE 1]

    PICTURE 1

    Also, the mesh isn't one sided as it was supposed to be, and has the texture and a weird triangle pattern on the back [SEE PICTURE 2]

    PICTURE 2

    For generation i use 1 script which uses a custom terrain class with 3 scripts in it.

    SCRIPT
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class CreateTerrain : MonoBehaviour {
    6.  
    7.    public Vector3[] TerrainArray;
    8.    public Vector2[] TerrainUVs;
    9.  
    10.    // Use this for initialization
    11.    void Start ()
    12.    {
    13.      Mesh mesh = gameObject.AddComponent<MeshFilter>().mesh;
    14.      gameObject.AddComponent<MeshRenderer>();
    15.  
    16.      TerrainArray = STerrain.CreateField(20,20);
    17.      TerrainUVs = STerrain.CreateUVs(TerrainArray,20,20);
    18.  
    19.      mesh = STerrain.CreateMesh(TerrainArray,TerrainUVs,20,20);
    20.  
    21.      mesh.RecalculateBounds();
    22.      mesh.RecalculateNormals();
    23.    }
    24. }
    25.  

    CLASS STerrain
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class STerrain : MonoBehaviour
    7. {
    8.    public static Vector3[] CreateField(int width,int length)
    9.    {
    10.      List<Vector3> List3D = new List<Vector3>();
    11.  
    12.      for( int x = 0 ; x < width ; x++ )
    13.      {
    14.        for( int z = 0 ; z < length ; z++ )
    15.        {
    16.          List3D.Add ( new Vector3( x, 0, z ) );
    17.        }
    18.      }
    19.  
    20.      return List3D.ToArray();
    21.    }
    22.  
    23.    public static Vector2[] CreateUVs( Vector3[] field, int width, int length)
    24.    {
    25.  
    26.      Vector2[] uvs = new Vector2[width * length];
    27.  
    28.      for( int x = 0 ; x < width ; x++ )
    29.      {
    30.        for( int z = 0 ; z < length ; z++ )
    31.        {
    32.          uvs[( x * width ) + z].x = field[( x * width ) + z ].x / width;
    33.          uvs[( x * width ) + z].y = field[( x * width ) + z ].z / length;
    34.        }
    35.      }
    36.    
    37.      return uvs;
    38.    }
    39.  
    40.    public static Mesh CreateMesh( Vector3[] field, Vector2[] uvs, int width, int length)
    41.    {
    42.      Mesh mesh = new Mesh();
    43.  
    44.      int index;
    45.  
    46.      Vector3 point1;
    47.      Vector3 point2;
    48.      Vector3 point3;
    49.      Vector3 point4;
    50.  
    51.      List<int> tris = new List<int>();
    52.  
    53.      for( int x = 0 ; x < width ; x++ )
    54.      {
    55.        for( int z = 0 ; z < length ; z++ )
    56.        {
    57.          index = ( x * width ) + z;
    58.  
    59.          while(true)
    60.          {
    61.            point1 =  field[index];
    62.  
    63.            try
    64.            {
    65.              point2 = field[index + 1];
    66.            }
    67.            catch(System.IndexOutOfRangeException e)
    68.            {
    69.              break;
    70.            }
    71.            try
    72.            {
    73.              point3 = field[index + width];
    74.            }
    75.            catch(System.IndexOutOfRangeException e)
    76.            {
    77.              break;
    78.            }
    79.            try
    80.            {
    81.              point4 = field[index + width + 1];
    82.            }
    83.            catch(System.IndexOutOfRangeException e)
    84.            {
    85.              break;
    86.            }
    87.  
    88.            tris.Add(index);
    89.            tris.Add(index + 1);
    90.            tris.Add(index + width);
    91.  
    92.            tris.Add(index + width);
    93.            tris.Add(index + width + 1);
    94.            tris.Add(index);
    95.  
    96.            break;
    97.          }
    98.        }
    99.      }
    100.  
    101.      mesh.vertices = field;
    102.      mesh.uv = uvs;
    103.      mesh.triangles = tris.ToArray();
    104.    
    105.      mesh.RecalculateBounds();
    106.      mesh.RecalculateNormals();
    107.  
    108.      return mesh;
    109.  
    110.    }
    111. }
    112.  

    Thank you for even looking at this thread, and even more if you have any suggestions on what could be causing this error !

    Dmajster_
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    The single-sidedness might be a choice of shader. For instance I believe the sprite shader and possibly some other unlit shaders to not respect backface culling.

    As for the top/bottom bands, look at things like the wrap mode (Clamp vs Repeat), and perhaps toggling mipmaps on/off.

    Another thing to do is bring the UVs in so they only show the upper left 25% of the texture and see what you see, just to get some clues about what is going on.

    Also, make a better test texture (search for "uv test texture" on google) so you can see edges more clearly.
     
    itsDmajster likes this.
  3. itsDmajster

    itsDmajster

    Joined:
    Oct 27, 2014
    Posts:
    45
    Kurt thank you for your fast response! Currently i have no shaders in my project so i would assume that backface culling is already turned on? Also thank you for your suggestion on the UV test texture! as for the settings i will play around with it and report back !
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    Just create a diffuse material, assign the test texture to that and assign it to the mesh renderer's material property. Diffuse should definitely remove back faces.

    Also, like I said, try other uv cords, like from 0 to 0.25 or so, see what part of your texture you see.

    edit:typos
     
    itsDmajster likes this.
  5. itsDmajster

    itsDmajster

    Joined:
    Oct 27, 2014
    Posts:
    45
    Hello Kurt! I had no luck with the materials, as the black lines persisted even on a diffuse material, but i did manage to solve the problem by rewriting my code to work in 2D vector3 arrays instead of a 1D vector3 array. Thank you for your help non the less!

    *Edit* For anyone who found himself in a similar situation, here is the code i use now which is simpler and most importantly WORKS!

    CUSTOM CLASS
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class STerrain : MonoBehaviour
    7. {
    8.    public static Vector3[,] CreateField(int width,int length)
    9.    {
    10.      Vector3[,] field = new Vector3[width +1,length +1];
    11.  
    12.      for( int z = 0 ; z < length +1 ; z++ )
    13.      {
    14.        for( int x = 0 ; x < width +1 ; x++ )
    15.        {
    16.  
    17.          field[x,z] = new Vector3( x, 0, z );
    18.        }
    19.      }
    20.  
    21.      return field;
    22.    }
    23.  
    24.    public static Mesh CreateMesh( Vector3[,] field)
    25.    {  
    26.      int width = field.GetLength(0);
    27.      int length = field.GetLength(1);
    28.  
    29.      Debug.Log("DEBUG >> Terrain width is: " + System.Convert.ToString( width ));
    30.      Debug.Log("DEBUG >> Terrain length is: " + System.Convert.ToString( length ));
    31.  
    32.      List<Vector3> verts = new List<Vector3>();
    33.      List<Vector2> uvs = new List<Vector2>();
    34.  
    35.      //Calculate UVs
    36.      for( int z = 0 ; z < length ; z++ )
    37.      {
    38.        for( int x = 0 ; x < width ; x++ )
    39.        {
    40.  
    41.          float uvx = field[x,z].x / (width-1);
    42.          float uvz = field[x,z].z / (length-1);
    43.  
    44.          uvs.Add( new Vector2( uvx, uvz ) );
    45.          verts.Add( new Vector3( field[x,z].x, 0, field[x,z].z ) );
    46.        }
    47.      }
    48.  
    49.      Vector3 point1;
    50.      Vector3 point2;
    51.      Vector3 point3;
    52.      Vector3 point4;
    53.  
    54.      List<int> tris = new List<int>();
    55.      for( int z = 0 ; z < length ; z++ )
    56.      {
    57.        for( int x = 0 ; x < width ; x++ )
    58.        {
    59.  
    60.          while(true)
    61.          {
    62.            point1 =  field[x,z];
    63.  
    64.            try
    65.            {
    66.              point2 = field[x+1,z];
    67.            }
    68.            catch(System.IndexOutOfRangeException e)
    69.            {
    70.              break;
    71.            }
    72.            try
    73.            {
    74.              point3 = field[x+1,z+1];
    75.            }
    76.            catch(System.IndexOutOfRangeException e)
    77.            {
    78.              break;
    79.            }
    80.            try
    81.            {
    82.              point4 = field[x,z+1];
    83.            }
    84.            catch(System.IndexOutOfRangeException e)
    85.            {
    86.              break;
    87.            }
    88.  
    89.            tris.Add( (z+1) * width + x ); // 4
    90.            tris.Add( z * width + x +1 ); // 2
    91.            tris.Add( z * width + x ); // 1
    92.  
    93.            tris.Add( (z+1) * width + x ); // 4
    94.            tris.Add( (z+1) * width + x+1 ); // 3
    95.            tris.Add( z * width + x +1 ); // 2
    96.  
    97.  
    98.            break;
    99.          }
    100.        }
    101.      }
    102.  
    103.      Mesh mesh = new Mesh();
    104.  
    105.      mesh.vertices = verts.ToArray();
    106.      mesh.uv = uvs.ToArray();
    107.      mesh.triangles = tris.ToArray();
    108.      
    109.      mesh.RecalculateBounds();
    110.      mesh.RecalculateNormals();
    111.  
    112.      return mesh;
    113.  
    114.    }
    115. }
    116.  

    SCRIPT EXAMPLE OF USAGE
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. public class CreateTerrain : MonoBehaviour
    5. {
    6.    public Vector3[,] TerrainArray;
    7.  
    8.    public int lotWidth;
    9.    public int lotLength;
    10.    public Material lotTexture;
    11.  
    12.    void Start ()
    13.    {
    14.      TerrainArray = STerrain.CreateField( lotWidth, lotLength );
    15.      Mesh mesh = STerrain.CreateMesh( TerrainArray );
    16.      
    17.      MeshFilter meshFilter = gameObject.AddComponent<MeshFilter>();
    18.  
    19.      gameObject.AddComponent<MeshRenderer>();
    20.      gameObject.GetComponent<MeshRenderer>().material = lotTexture;
    21.  
    22.      meshFilter.mesh = mesh;
    23.  
    24.    }
    25. }
    26.  
     
    Last edited: Jan 27, 2015
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    Hey Dmajster_, that's very nice how you broke down the logical creation of the "field" and separated that step from the creation of the mesh to represent it. Gives you good flexibility if something needs to change.
     
  7. itsDmajster

    itsDmajster

    Joined:
    Oct 27, 2014
    Posts:
    45
    Hey Kurt, this is actually what i was aiming for, as my terrain won't be static, and making the mesh independent of the "field" will be crucial for having a nice and flexible code onwards.