Advertisement
polyfied

Create a river from a Playground Spline

Jul 23rd, 2015
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.70 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. namespace PlaygroundSplines {
  5.     /// <summary>
  6.     /// The PlaygroundSplineMesh class lets you create a mesh from a Playground Spline.
  7.     /// </summary>
  8.     [ExecuteInEditMode()]
  9.     public class PlaygroundSplineMesh : MonoBehaviour {
  10.  
  11.         public PlaygroundSpline spline;
  12.         [Range(2,1000)]
  13.         public int points = 100;
  14.         [Range(.01f, 100f)]
  15.         public float width = 1f;
  16.         public bool noise = false;
  17.         [Range(.01f, 100f)]
  18.         public float noiseStrength = 1f;
  19.         public Vector2 noiseScale = new Vector2(1f,1f);
  20.  
  21.         int prevPoints;
  22.         float prevWidth;
  23.         bool prevNoise;
  24.         float prevNoiseStrength;
  25.         Vector2 prevNoiseScale;
  26.  
  27.         void OnEnable ()
  28.         {
  29.             if (GetComponent<Renderer>() == null)
  30.                 gameObject.AddComponent<MeshRenderer>();
  31.             if (spline == null)
  32.                 spline = GetComponent<PlaygroundSpline>();
  33.             if (spline != null)
  34.                 BuildSplineMesh(spline, points, width);
  35.             SetVals();
  36.         }
  37.  
  38.         void Update ()
  39.         {
  40.             if (prevPoints!=points || prevWidth!=width || prevNoise!=noise || noise && (prevNoiseScale!=noiseScale || prevNoiseStrength!=noiseStrength))
  41.             {
  42.                 if (spline != null)
  43.                     BuildSplineMesh(spline, points, width);
  44.                 SetVals ();
  45.             }
  46.         }
  47.  
  48.         void SetVals ()
  49.         {
  50.             prevPoints = points;
  51.             prevWidth = width;
  52.             prevNoise = noise;
  53.             prevNoiseStrength = noiseStrength;
  54.             prevNoiseScale = noiseScale;
  55.         }
  56.        
  57.         public void BuildSplineMesh (PlaygroundSpline spline, int points, float width)
  58.         {
  59.             if (points<2)
  60.                 points = 2;
  61.             int totalVertices = points*2;
  62.             MeshFilter _mf = GetComponent<MeshFilter>()!=null? GetComponent<MeshFilter>() : gameObject.AddComponent<MeshFilter>();
  63.             Mesh _m = new Mesh();
  64.             Vector3[] verts = new Vector3[totalVertices];
  65.             Vector2[] uvs = new Vector2[totalVertices];
  66.             int[] tris = new int[(points-1)*6];
  67.  
  68.             // Construct the mesh
  69.             for (int i = 0; i<points; i++)
  70.             {
  71.                 // Create a normalized time value
  72.                 float t = (i*1f)/(points-1);
  73.                 float tNext = ((i*1f)+1)/(points-1);
  74.                 if (t>=1 && !spline.Loop)
  75.                     t = .9999f;
  76.                 if (tNext>=1 && !spline.Loop)
  77.                     tNext = .99999f;
  78.  
  79.                 // Get the current and next position from the spline on time
  80.                 Vector3 currentPosition = spline.GetPoint (t);
  81.                 Vector3 nextPosition = spline.GetPoint (tNext);
  82.  
  83.                 // Raycast down to determine up direction (especially practical for roads / rivers)
  84.                 RaycastHit hit;
  85.                 Vector3 up = Vector3.up;
  86.                 if (Physics.Raycast (currentPosition, Vector3.down, out hit))
  87.                     up = hit.normal;
  88.  
  89.                 // Calculate noise (if enabled)
  90.                 float noiseAmountL = noise? Mathf.PerlinNoise((t%1f)*noiseScale.x, 0)*noiseStrength : 0;
  91.                 float noiseAmountR = noise? Mathf.PerlinNoise((t%1f)*noiseScale.y, 0)*noiseStrength : 0;
  92.  
  93.                 // Create two width point references based on current and next position
  94.                 Vector3 dir = (Vector3.Cross(up, nextPosition - currentPosition)).normalized;
  95.                 Vector3 lPoint = currentPosition + dir * ((width/2)+noiseAmountL);
  96.                 Vector3 rPoint = currentPosition - dir * ((width/2)+noiseAmountR);
  97.  
  98.                 // Draw debug
  99.                 Debug.DrawLine(lPoint, rPoint);
  100.  
  101.                 verts[i*2] = lPoint;
  102.                 verts[(i*2)+1] = rPoint;
  103.                 uvs[i*2] = new Vector2(t,0);
  104.                 uvs[(i*2)+1] = new Vector2(t,1f);
  105.  
  106.                 if (i>0)
  107.                 {
  108.                     int triIndex = (i-1)*6;
  109.                     int vertIndex = i*2;
  110.  
  111.                     tris[triIndex] = vertIndex-2;
  112.                     tris[triIndex+1] = vertIndex-1;
  113.                     tris[triIndex+2] = vertIndex;
  114.                     tris[triIndex+3] = vertIndex;
  115.                     tris[triIndex+4] = vertIndex-1;
  116.                     tris[triIndex+5] = vertIndex+1;
  117.                 }
  118.             }
  119.  
  120.             // Assign the data to the mesh
  121.             _m.vertices = verts;
  122.             _m.uv = uvs;
  123.             _m.triangles = tris;
  124.             _m.RecalculateNormals();
  125.  
  126.             // Assign the mesh to the MeshFilter
  127.             _mf.mesh = _m;
  128.         }
  129.     }
  130. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement