marcb152

Wind creator

Jun 29th, 2020
842
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.57 KB | None | 0 0
  1. //Forum thread : https://forum.unity.com/threads/how-to-add-wind-to-custom-trees-grass-in-unity-using-tree-creator-shaders.871126/
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5.  
  6. public class WindCreator : MonoBehaviour
  7. {
  8.     private Mesh treeMesh;
  9.     private List<Material> mats = new List<Material>();
  10.     private bool barkMatFirst;
  11.  
  12.     [SerializeField]
  13.     [Tooltip("If set to true, all the vertex colors and uv2 already set in this mesh will be replaced with new ones")]
  14.     private bool overwriteExistingChannels = false;
  15.  
  16.     //Vertex colors variables
  17.     [Header("Vertex Colors")]
  18.     [SerializeField]
  19.     [Tooltip("Do you want to use vertex colors on your mesh ?")]
  20.     private bool useVertexColors = true;
  21.  
  22.     [SerializeField]
  23.     [Tooltip("The type of gradient that will be apllied to the vertex colors")]
  24.     private GradientType colorGradientType = GradientType.Linear;
  25.  
  26.     [SerializeField]
  27.     [Tooltip("Put the bark material of your tree here")]
  28.     private Material barkMat;
  29.  
  30.     [SerializeField]
  31.     [Tooltip("Put the leaves material of your tree here")]
  32.     private Material leafMat;
  33.  
  34.     [SerializeField]
  35.     [Tooltip("How much the red value of the vertex colors should be painted ?")]
  36.     [Range(0, 1)]
  37.     private float vertexPercent = 0.5f;
  38.  
  39.     //Uv2 variables
  40.     [Header("UV2 Channel")]
  41.     [SerializeField]
  42.     [Tooltip("Do you want to use uv2 on your mesh ?")]
  43.     private bool useUv2 = true;
  44.  
  45.     [SerializeField]
  46.     [Tooltip("The type of gradient that will be apllied to the uv2")]
  47.     private GradientType uv2GradientType = GradientType.Circular;
  48.  
  49.     [SerializeField]
  50.     [Tooltip("How much the values of the uv2 should be painted ?")]
  51.     [Range(0, 1)]
  52.     private float uv2Percent = 0.3f;
  53.  
  54.     [SerializeField]
  55.     [Tooltip("How much the X value of the uv2 for the bark should be painted ?")]
  56.     [Range(0, 1)]
  57.     private float barkMultiplierX = 1f;
  58.  
  59.     [SerializeField]
  60.     [Tooltip("How much the Y value of the uv2 for the bark should be painted ?")]
  61.     [Range(0, 1)]
  62.     private float barkMultiplierY = 0.5f;
  63.  
  64.     [SerializeField]
  65.     [Tooltip("How much the X value of the uv2 for the leaves should be painted ?")]
  66.     [Range(0, 1)]
  67.     private float leafMutliplierX = 1;
  68.  
  69.     [SerializeField]
  70.     [Tooltip("How much the Y value of the uv2 for the leaves should be painted ?")]
  71.     [Range(0, 1)]
  72.     private float leafMutliplierY = 1;
  73.  
  74.  
  75.     /// <summary>
  76.     /// This is the main function
  77.     /// </summary>
  78.     [ContextMenu("Create wind")]
  79.     private void CreateWind()
  80.     {
  81.         try
  82.         {
  83.             treeMesh = CopyMesh(GetComponent<MeshFilter>().sharedMesh);
  84.             mats.Clear();
  85.             mats.AddRange(GetComponent<MeshRenderer>().sharedMaterials);
  86.             if (mats[0].Equals(barkMat)) barkMatFirst = true;
  87.             else if (mats[0].Equals(leafMat)) barkMatFirst = false;
  88.  
  89.             if (useVertexColors)
  90.             {
  91.                 if (treeMesh.colors.Length > 0 && !overwriteExistingChannels)
  92.                     Debug.LogWarning("Existing vertex colors channel detected, wind wont be set to this channel, consider enabling overwriteExistingChannels.");
  93.                 else if ((treeMesh.colors.Length <= 0 && !overwriteExistingChannels) || (treeMesh.colors.Length > 0 && overwriteExistingChannels))
  94.                     PaintColors();
  95.             }
  96.  
  97.             if (useUv2)
  98.             {
  99.                 if (treeMesh.uv2.Length > 0 && !overwriteExistingChannels)
  100.                     Debug.LogWarning("Existing uv2 channel detected, wind wont be set to this channel, consider enabling overwriteExistingChannels.");
  101.                 else if ((treeMesh.uv2.Length <= 0 && !overwriteExistingChannels) || (treeMesh.uv2.Length > 0 && overwriteExistingChannels))
  102.                     PaintUV2();
  103.             }
  104.  
  105.             if (useVertexColors || useUv2) CreateNewMesh();
  106.             else Debug.LogWarning("Nothing to add to the mesh, please set useVertexColors or useUv2 to true.");
  107.         }
  108.         catch (Exception ex)
  109.         {
  110.             Debug.LogError(ex.Message);
  111.         }
  112.     }
  113.     /// <summary>
  114.     /// This function will add the colors channel to the mesh
  115.     /// </summary>
  116.     private void PaintColors()
  117.     {
  118.         try
  119.         {
  120.             Vector3 range = treeMesh.bounds.max - treeMesh.bounds.min;
  121.             List<Color> colors = new List<Color>(new Color[treeMesh.vertexCount]);
  122.             HashSet<int> tris = new HashSet<int>();
  123.             for (int i = 0; i < treeMesh.subMeshCount; i++)
  124.             {
  125.                 int start = tris.Count;
  126.                 tris.UnionWith(new HashSet<int>(treeMesh.GetTriangles(i)));
  127.                 for (int a = start; a < tris.Count; a++)
  128.                 {
  129.                     float power = 0;
  130.                     //Linear gradient
  131.                     if (colorGradientType == GradientType.Linear)
  132.                         power = treeMesh.vertices[a].y / range.y * vertexPercent;
  133.                     //Circular gradient
  134.                     if (colorGradientType == GradientType.Circular)
  135.                         power = Mathf.Sqrt(Mathf.Pow(treeMesh.vertices[a].x / range.x, 2) + Mathf.Pow(treeMesh.vertices[a].y / range.y, 2) + Mathf.Pow(treeMesh.vertices[a].z / range.z, 2)) / Mathf.Sqrt(3) * vertexPercent;
  136.  
  137.                     //Bark mat
  138.                     if ((barkMatFirst && i == 0) || (!barkMatFirst && i != 0))
  139.                         colors[a] = new Color(power, 0, 0);
  140.  
  141.                     //Leaf mat
  142.                     else if ((!barkMatFirst && i == 0) || (barkMatFirst && i != 0))
  143.                         colors[a] = new Color(power, 1, 0);
  144.                 }
  145.             }
  146.             treeMesh.colors = colors.ToArray();
  147.         }
  148.         catch (Exception ex)
  149.         {
  150.             Debug.LogError(ex.Message);
  151.         }
  152.     }
  153.     /// <summary>
  154.     /// This function will add the second uv channel to the mesh
  155.     /// </summary>
  156.     private void PaintUV2()
  157.     {
  158.         try
  159.         {
  160.             Vector3 range = treeMesh.bounds.max - treeMesh.bounds.min;
  161.             List<Vector2> uv2 = new List<Vector2>(new Vector2[treeMesh.vertexCount]);
  162.             HashSet<int> tris = new HashSet<int>();
  163.             for (int i = 0; i < treeMesh.subMeshCount; i++)
  164.             {
  165.                 int start = tris.Count;
  166.                 tris.UnionWith(new HashSet<int>(treeMesh.GetTriangles(i)));
  167.                 for (int a = start; a < tris.Count; a++)
  168.                 {
  169.                     float power = 0;
  170.                     //Linear gradient
  171.                     if (uv2GradientType == GradientType.Linear)
  172.                         power = treeMesh.vertices[a].y / range.y * uv2Percent;
  173.                     //Circular gradient
  174.                     if (uv2GradientType == GradientType.Circular)
  175.                         power = Mathf.Sqrt(Mathf.Pow(treeMesh.vertices[a].x / range.x, 2) + Mathf.Pow(treeMesh.vertices[a].y / range.y, 2) + Mathf.Pow(treeMesh.vertices[a].z / range.z, 2))  / Mathf.Sqrt(3) * uv2Percent;
  176.                    
  177.                     //Bark mat
  178.                     if ((barkMatFirst && i == 0) || (!barkMatFirst && i != 0))
  179.                         uv2[a] = new Vector2(power * barkMultiplierX, power * barkMultiplierY);
  180.  
  181.                     //Leaf mat
  182.                     else if ((!barkMatFirst && i == 0) || (barkMatFirst && i != 0))
  183.                         uv2[a] = new Vector2(power * leafMutliplierX, power * leafMutliplierY);
  184.                 }
  185.             }
  186.             treeMesh.uv2 = uv2.ToArray();
  187.         }
  188.         catch (Exception ex)
  189.         {
  190.             Debug.LogError(ex.Message);
  191.         }
  192.     }
  193.     /// <summary>
  194.     /// This function will create the new gameobject with all the needed components
  195.     /// </summary>
  196.     private void CreateNewMesh()
  197.     {
  198.         GameObject tree = new GameObject(gameObject.name + "_Wind");
  199.         tree.AddComponent<MeshFilter>().sharedMesh = treeMesh;
  200.         tree.AddComponent<MeshRenderer>().sharedMaterials = mats.ToArray();
  201.         tree.AddComponent<WindMultipleMat>();
  202.         Debug.Log("Wind successfully added to : " + gameObject.name, tree);
  203.         gameObject.SetActive(false);
  204.     }
  205.     /// <summary>
  206.     /// This function makes a copy of a Mesh, it breaks the reference
  207.     /// </summary>
  208.     /// <param name="mesh">The Mesh to copy</param>
  209.     /// <returns>The copied Mesh</returns>
  210.     private Mesh CopyMesh(Mesh mesh)
  211.     {
  212.         return Instantiate(mesh);
  213.     }
  214.     /// <summary>
  215.     /// The gradient that will be applied
  216.     /// </summary>
  217.     private enum GradientType
  218.     {
  219.         Linear,
  220.         Circular
  221.     }
  222.  
  223. }
Add Comment
Please, Sign In to add comment