Skip to content

Instantly share code, notes, and snippets.

@barbietunnie
Created July 24, 2015 19:17
Show Gist options
  • Save barbietunnie/7b689d5b8182ca042ca0 to your computer and use it in GitHub Desktop.
Save barbietunnie/7b689d5b8182ca042ca0 to your computer and use it in GitHub Desktop.
Create a mesh from a Playground Spline
using UnityEngine;
using System.Collections;
namespace PlaygroundSplines {
/// <summary>
/// The PlaygroundSplineMesh class lets you create a mesh from a Playground Spline.
/// </summary>
[ExecuteInEditMode()]
public class PlaygroundSplineMesh : MonoBehaviour {
public PlaygroundSpline spline;
[Range(2,1000)]
public int points = 100;
[Range(.01f, 100f)]
public float width = 1f;
int prevPoints;
float prevWidth;
void OnEnable ()
{
if (GetComponent<Renderer>() == null)
gameObject.AddComponent<MeshRenderer>();
if (spline == null)
spline = GetComponent<PlaygroundSpline>();
if (spline != null)
BuildSplineMesh(spline, points, width);
prevPoints = points;
prevWidth = width;
}
void Update ()
{
if (prevPoints!=points || prevWidth!=width)
{
if (spline != null)
BuildSplineMesh(spline, points, width);
prevPoints = points;
prevWidth = width;
}
}
public void BuildSplineMesh (PlaygroundSpline spline, int points, float width)
{
if (points<2)
points = 2;
int totalVertices = points*2;
MeshFilter _mf = GetComponent<MeshFilter>()!=null? GetComponent<MeshFilter>() : gameObject.AddComponent<MeshFilter>();
Mesh _m = new Mesh();
Vector3[] verts = new Vector3[totalVertices];
Vector2[] uvs = new Vector2[totalVertices];
int[] tris = new int[(points-1)*6];
// Construct the mesh
for (int i = 0; i<points; i++)
{
// Create a normalized time value
float t = (i*1f)/(points-1);
float tNext = ((i*1f)+1)/(points-1);
if (t>=1)
t = .9999f;
if (tNext>=1)
tNext = .99999f;
// Get the current and next position from the spline on time
Vector3 currentPosition = spline.GetPoint (t);
Vector3 nextPosition = spline.GetPoint (tNext);
// Raycast down to determine up direction (especially practical for roads / rivers)
RaycastHit hit;
Vector3 up = Vector3.up;
if (Physics.Raycast (currentPosition, Vector3.down, out hit))
up = hit.normal;
// Create two width point references based on current and next position
Vector3 dir = (Vector3.Cross(up, nextPosition - currentPosition)).normalized;
Vector3 lPoint = currentPosition + dir * (width/2);
Vector3 rPoint = currentPosition - dir * (width/2);
// Draw debug
Debug.DrawLine(lPoint, rPoint);
verts[i*2] = lPoint;
verts[(i*2)+1] = rPoint;
uvs[i*2] = new Vector2(t,0);
uvs[(i*2)+1] = new Vector2(t,1f);
if (i>0)
{
int triIndex = (i-1)*6;
int vertIndex = i*2;
tris[triIndex] = vertIndex-2;
tris[triIndex+1] = vertIndex-1;
tris[triIndex+2] = vertIndex;
tris[triIndex+3] = vertIndex;
tris[triIndex+4] = vertIndex-1;
tris[triIndex+5] = vertIndex+1;
}
}
// Assign the data to the mesh
_m.vertices = verts;
_m.uv = uvs;
_m.triangles = tris;
_m.RecalculateNormals();
// Assign the mesh to the MeshFilter
_mf.mesh = _m;
}
}
}
@barbietunnie
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment