Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Material applied to generated Mesh stretching on Vertical

Discussion in 'Scripting' started by M4XXX, Dec 1, 2018.

  1. M4XXX

    M4XXX

    Joined:
    Aug 27, 2017
    Posts:
    10
    I am generating a simple mesh to which I apply a texture - the mesh will end up being part of the terrain on a 2.5d game.
    All looks fine, but when the terrain slopes the texture stretches
    upload_2018-12-1_12-34-19.png

    What I want to happen is that the material 'rotates' to follow the terrain (in other words, it doesn't look stretched! - the squares stay square, not rectangular)

    Here's the code that generates the above - keeping it simple - the real game is more complex.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System.IO;
    6.  
    7. public class test : MonoBehaviour {
    8.  
    9.     public Material material;
    10.     void Start () {
    11.         var m = new Mesh();
    12.  
    13.         var heights = new List<Vector3>();
    14.         heights.Add(new Vector3(0, 0, 10));
    15.         heights.Add(new Vector3(10,1, 10));
    16.         heights.Add(new Vector3(20, 0,10));
    17.         heights.Add(new Vector3(30,20, 10));
    18.         heights.Add(new Vector3(40, 0, 10));
    19.         heights.Add(new Vector3(50, 3, 10));
    20.         heights.Add(new Vector3(60, 0, 10));
    21.         heights.Add(new Vector3(70, 0, 10));
    22.         heights.Add(new Vector3(80, 0, 10));
    23.         heights.Add(new Vector3(90, 0, 10));
    24.         heights.Add(new Vector3(100, 0, 10));
    25.  
    26.         var width = 120f;                   // The back point to draw the terrain
    27.         var metersPerTextureHeight = 10f;   // How many meters comprise the height of a texture square
    28.         var metersPerTextureWidth = 10f;    // How many meters comprise the width of a texture square
    29.  
    30.         var vertices = new List<Vector3>();
    31.         var uv = new List<Vector2>();
    32.         var triangles = new List<int>();
    33.  
    34.         foreach (var vertex in heights)
    35.         {
    36.             vertices.Add(new Vector3(vertex.x, vertex.y, width));
    37.             vertices.Add(vertex);
    38.             uv.Add(new Vector2(vertex.x / metersPerTextureWidth, 0));
    39.             uv.Add(new Vector2(vertex.x / metersPerTextureWidth, width / metersPerTextureHeight));
    40.         }
    41.  
    42.         m.vertices = vertices.ToArray();
    43.  
    44.         m.uv = uv.ToArray();
    45.  
    46.         for (int i = 0; i< vertices.Count-2; i+= 2)
    47.         {
    48.             triangles.Add(i);
    49.             triangles.Add(i+2);
    50.             triangles.Add(i+1);
    51.             triangles.Add(i+2);
    52.             triangles.Add(i+3);
    53.             triangles.Add(i+1);
    54.         }
    55.  
    56.         m.triangles = triangles.ToArray();
    57.  
    58.         var go = GameObject.Find("GameObject");
    59.         var mf = go.AddComponent(typeof(MeshFilter)) as MeshFilter;
    60.         var mr = go.AddComponent(typeof(MeshRenderer)) as MeshRenderer;
    61.  
    62.         mr.material = material;
    63.         mf.mesh = m;
    64.  
    65.         m.RecalculateBounds();
    66.         m.RecalculateNormals();
    67.     }
    68.  
    69. }
    70.  
    71.  
    I'd appreciate any guidance as to how to achieve this?

    Thanks
     
  2. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    As you iterate through your heights list, calculate the total length of the terrain edge (Get length between current and previous point, add to a total), and base your uv.x value on this value rather than the vertex.x coordinate.
    This will only work without shearing the texture in a planar width setup like yours, but you can use the same technique to uv-map pipes, tubes or toroids if you're okay with a bit of skewing.
     
    mannyhams likes this.
  3. M4XXX

    M4XXX

    Joined:
    Aug 27, 2017
    Posts:
    10
    Thank you so much - it seems obvious now but had me stumped!