duck

Procedural mesh code for "You Are The Road"

May 4th, 2012
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.47 KB | None | 0 0
  1. // Road generation script from "You Are The Road", which is a hacked version of:
  2. // http://www.unifycommunity.com/wiki/index.php?title=OptimizedTrailRenderer
  3. // There are a few things left in this script which were not used, such as
  4. // the trail width, colour fading, etc.
  5.  
  6. // As this was hastily modified for a 48h game jam game, this may not be the
  7. // best learning example!
  8.  
  9. using UnityEngine;
  10. using System.Collections;
  11.  
  12. public class Road : MonoBehaviour
  13. {
  14.     // Material - Must be a particle material that has the "Tint Color" property
  15.     public Material material;
  16.     Material instanceMaterial;
  17.     public float uMapScale = 0.1f;
  18.     // Emit
  19.     public bool emit = true;
  20.     bool emittingDone = false;
  21.    
  22.     // Lifetime of each segment
  23.     public float lifeTime = 1;
  24.     float lifeTimeRatio = 1;
  25.     float fadeOutRatio;
  26.  
  27.     // Colors
  28.     public Color[] colors;
  29.  
  30.     // Widths
  31.     public float[] widths;
  32.    
  33.     // Segment creation data
  34.     public float maxAngle = 2;
  35.     public float minVertexDistance = 0.1f;
  36.     public float maxVertexDistance = 1f;
  37.    
  38.     public int pointCount = 30;
  39.    
  40.     public bool useCollider = false;
  41.    
  42.     MeshCollider meshCollider;
  43.    
  44.     // Object
  45.     GameObject trailObj = null;
  46.     Mesh mesh = null;
  47.    
  48.     // Points
  49.     Point[] points;
  50.    
  51.    
  52.    
  53.     void Start ()
  54.     {
  55.         points = new Point[pointCount];
  56.         trailObj = new GameObject("Trail");
  57.         trailObj.transform.parent = null;
  58.         trailObj.transform.position = Vector3.zero;
  59.         trailObj.transform.rotation = Quaternion.identity;
  60.         trailObj.transform.localScale = Vector3.one;
  61.         MeshFilter meshFilter = (MeshFilter) trailObj.AddComponent(typeof(MeshFilter));
  62.        
  63.         mesh = meshFilter.mesh;
  64.        
  65.         if (useCollider) {
  66.             meshCollider = trailObj.AddComponent<MeshCollider>();
  67.             meshCollider.sharedMesh = mesh;
  68.         }
  69.        
  70.         trailObj.AddComponent(typeof(MeshRenderer));
  71.         instanceMaterial = new Material(material);
  72.         fadeOutRatio = 1;//f / instanceMaterial.GetColor("_TintColor").a;
  73.         trailObj.renderer.material = instanceMaterial;
  74.     }
  75.    
  76.     public void Update ()
  77.     {
  78.         // Emitting - Designed for one-time use
  79.         if( ! emit )
  80.             emittingDone = true;
  81.         if(emittingDone)
  82.             emit = false;
  83.            
  84.         // Remove expired points
  85.         for(int i = pointCount-1; i >=0; i--)
  86.         {
  87.             Point point = points[i];
  88.             if(point == null || point.timeAlive > lifeTime)
  89.             {
  90.                 points[i] = null;
  91.                 pointCount--;
  92.             }
  93.             else
  94.                 break;
  95.         }
  96.        
  97.  
  98.    
  99.         // Do we add any new points?
  100.          bool add = false;
  101.         if(emit)
  102.         {
  103.             if(pointCount == 0)
  104.             {
  105.                 points[pointCount++] = new Point(transform);
  106.                 points[pointCount++] = new Point(transform);
  107.             }
  108.             if(pointCount == 1)
  109.                 insertPoint();
  110.  
  111.            
  112.             float sqrDistance = (points[1].position - transform.position).sqrMagnitude;
  113.             if(sqrDistance > minVertexDistance * minVertexDistance)
  114.             {
  115.                 if(sqrDistance > maxVertexDistance * maxVertexDistance)
  116.                 {
  117.                     add = true;
  118.                 }
  119.                 else if(Quaternion.Angle(transform.rotation, points[1].rotation) > maxAngle)
  120.                 {
  121.                     add = true;
  122.                 }
  123.             }
  124.             if(add)
  125.             {
  126.                 //if(pointCount == points.Length)
  127.                     //System.Array.Resize(ref points, points.Length + 50);
  128.                 insertPoint();
  129.             }
  130.             if( ! add )
  131.                 points[0].update(transform);
  132.         }
  133.        
  134.         // Do we render this?
  135.         if(pointCount < 2)
  136.         {
  137.             trailObj.renderer.enabled = false;
  138.             return;
  139.         }
  140.         trailObj.renderer.enabled = true;
  141.        
  142.         Color[] meshColors;
  143.         lifeTimeRatio = 1 / lifeTime;
  144.  
  145.         // Do we fade it out?
  146.         if( ! emit )
  147.         {
  148.             if(pointCount == 0)
  149.                 return;
  150.             Color color = instanceMaterial.GetColor("_TintColor");
  151.             color.a -= fadeOutRatio * lifeTimeRatio * Time.deltaTime;
  152.             if(color.a > 0)
  153.                 instanceMaterial.SetColor("_TintColor", color);
  154.             else
  155.             {
  156.                 Destroy(trailObj);
  157.                 Destroy(this);
  158.             }
  159.             return;
  160.         }
  161.        
  162.  
  163.         points[0].distance = points[1].distance+((points[0].position-points[1].position).magnitude);   
  164.  
  165.         {
  166.             // Rebuild it
  167.             Vector4[] tangents = new Vector4[pointCount * 2];
  168.             Vector3[] vertices = new Vector3[pointCount * 2];
  169.             Vector2[] uvs = new Vector2[pointCount * 2];
  170.             int[] triangles = new int[(pointCount-1) * 6];
  171.             meshColors = new Color[pointCount * 2];
  172.        
  173.             float uvMultiplier = 1 / (points[pointCount-1].timeAlive - points[0].timeAlive);
  174.             for(int i = 0; i < pointCount; i++)
  175.             {
  176.                 Point point = points[i];
  177.    
  178.                 float ratio = point.timeAlive * lifeTimeRatio;
  179.                 // Color
  180.                 Color color;
  181.                 if(colors.Length == 0)
  182.                     color = Color.Lerp(Color.white, Color.clear, ratio);
  183.                 else if(colors.Length == 1)
  184.                     color = Color.Lerp(colors[0], Color.clear, ratio);
  185.                 else if(colors.Length == 2)
  186.                     color = Color.Lerp(colors[0], colors[1], ratio);
  187.                 else
  188.                 {
  189.                     float colorRatio = ratio * (colors.Length-1);
  190.                     int min = (int) Mathf.Floor(colorRatio);
  191.                     float lerp = Mathf.InverseLerp(min, min+1, colorRatio);
  192.                     color = Color.Lerp(colors[min], colors[min+1], lerp);
  193.                 }
  194.                 meshColors[i * 2] = color;
  195.                 meshColors[(i * 2) + 1] = color;
  196.                
  197.                 // Width
  198.                 float width;
  199.                 if(widths.Length == 0)
  200.                     width = 1;
  201.                 else if(widths.Length == 1)
  202.                     width = widths[0];
  203.                 else if(widths.Length == 2)
  204.                     width = Mathf.Lerp(widths[0], widths[1], ratio);
  205.                 else
  206.                 {
  207.                     float widthRatio = ratio * (widths.Length-1);
  208.                     int min = (int) Mathf.Floor(widthRatio);
  209.                     float lerp = Mathf.InverseLerp(min, min+1, widthRatio);
  210.                     width = Mathf.Lerp(widths[min], widths[min+1], lerp);
  211.                 }
  212.                 trailObj.transform.position = point.position;
  213.                 trailObj.transform.rotation = point.rotation;
  214.                 vertices[i * 2] = trailObj.transform.TransformPoint(-width*0.5f,0,0);
  215.                 vertices[(i * 2) + 1] = trailObj.transform.TransformPoint( width*0.5f,0 , 0);
  216.                
  217.                 // UVs
  218.                 //float uvRatio;
  219.                 //uvRatio = (point.timeAlive - points[0].timeAlive) * uvMultiplier;
  220.                 float u = point.distance * uMapScale;
  221.                 uvs[i * 2] = new Vector2(0,u);
  222.                 uvs[(i * 2) + 1] = new Vector2(1,u);
  223.                
  224.                 tangents[i * 2] = new Vector4(1,0,0,1);
  225.                 tangents[(i * 2) + 1] = new Vector4(1,0,0,1);
  226.                
  227.                 if(i > 0)
  228.                 {
  229.                     // Triangles
  230.                     int triIndex = (i - 1) * 6;
  231.                     int vertIndex = i * 2;
  232.                     triangles[triIndex+0] = vertIndex - 2;
  233.                     triangles[triIndex+1] = vertIndex - 1;
  234.                     triangles[triIndex+2] = vertIndex - 0;
  235.                    
  236.                     triangles[triIndex+3] = vertIndex + 1;
  237.                     triangles[triIndex+4] = vertIndex + 0;
  238.                     triangles[triIndex+5] = vertIndex - 1;
  239.                 }
  240.             }
  241.            
  242.             trailObj.transform.position = Vector3.zero;
  243.             trailObj.transform.rotation = Quaternion.identity;
  244.             mesh.Clear();
  245.            
  246.             mesh.vertices = vertices;
  247.             mesh.colors = meshColors;
  248.             mesh.uv = uvs;
  249.             mesh.triangles = triangles;
  250.             mesh.RecalculateNormals();
  251.             mesh.tangents = tangents;
  252.                
  253.             if (useCollider && add) {
  254.                 meshCollider.sharedMesh = null;
  255.                 meshCollider.sharedMesh = mesh;
  256.                
  257.                
  258.             }
  259.         }
  260.     }
  261.  
  262.     void insertPoint()
  263.     {
  264.         for(int i = pointCount; i > 0; i--)
  265.         {
  266.             points[i] = points[i-1];
  267.         }
  268.         points[0] = new Point(transform);
  269.        
  270.         points[0].distance = points[1].distance + (points[0].position-points[1].position).magnitude;
  271.         if (pointCount < points.Length-1) {
  272.             pointCount++;
  273.         }
  274.        
  275.         Car.waypoints.Add(points[0]);
  276.        
  277.     }
  278.  
  279.  
  280. }
  281.  
  282.     public class Point
  283.     {
  284.         public float timeCreated = 0;
  285.         public float distance;
  286.        
  287.         public float timeAlive
  288.         {
  289.             get { return Time.time - timeCreated; }
  290.         }
  291.         public float fadeAlpha = 0;
  292.         public Vector3 position = Vector3.zero;
  293.         public Vector3 forward = Vector3.zero;
  294.         public Vector3 right = Vector3.zero;
  295.         public Quaternion rotation = Quaternion.identity;
  296.         public Point(Transform trans)
  297.         {
  298.             position = trans.position;
  299.             rotation = trans.rotation;
  300.             forward = trans.forward;
  301.             right = trans.right;
  302.            
  303.             timeCreated = Time.time;
  304.         }
  305.         public void update(Transform trans)
  306.         {
  307.             position = trans.position;
  308.             rotation = trans.rotation;
  309.             timeCreated = Time.time;
  310.         }
  311.     }
Advertisement
Add Comment
Please, Sign In to add comment