Skip to content

Instantly share code, notes, and snippets.

@karl-
Created January 24, 2019 20:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karl-/47c7b8b60cccc9cd38b7f571cd6e7921 to your computer and use it in GitHub Desktop.
Save karl-/47c7b8b60cccc9cd38b7f571cd6e7921 to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.ProBuilder;
using UnityEngine.ProBuilder.MeshOperations;
namespace PipeDreams
{
sealed class Pipe : MonoBehaviour
{
static System.Random s_Random = new System.Random();
float m_ExtrudeSpeed = 1f;
float m_MinExtrudeDistance = 3f;
float m_MaxExtrudeDistance = 20f;
ProBuilderMesh m_Mesh;
Face[] m_ActiveFaces = new Face[1];
List<Vector3> m_Positions;
List<int> m_Indices = new List<int>();
Vector3 m_ExtrudeDirection;
float m_ExtrudeDistance;
Face activeFace
{
get { return m_ActiveFaces[0]; }
set { m_ActiveFaces[0] = value; }
}
public ProBuilderMesh mesh
{
get { return m_Mesh; }
}
void Awake()
{
m_Mesh = GetComponent<ProBuilderMesh>();
}
public void Begin(float extrudeSpeed, float minimumExtrudeDistance, float maximumExtrudeDistance)
{
m_ExtrudeSpeed = extrudeSpeed;
m_MinExtrudeDistance = minimumExtrudeDistance;
m_MaxExtrudeDistance = maximumExtrudeDistance;
activeFace = m_Mesh.faces[s_Random.Next(0, m_Mesh.faceCount)];
ChangeDirection();
}
void ChangeDirection()
{
// Extrude once to create a turn
Face[] extrudedSides = m_Mesh.Extrude(m_ActiveFaces, ExtrudeMethod.FaceNormal, 1f);
// Select a new active face
activeFace = extrudedSides[s_Random.Next(0, extrudedSides.Length)];
// Extrude again to create the extending segment
m_Mesh.Extrude(m_ActiveFaces, ExtrudeMethod.FaceNormal, .001f);
// Get the direction of the extruded face
m_ExtrudeDirection = Math.Normal(m_Mesh, activeFace);
m_Positions = m_Mesh.positions.ToList();
// Populate the list of coincident vertex indices
m_Mesh.GetCoincidentVertices(m_ActiveFaces, m_Indices);
float distance = m_MinExtrudeDistance + (float) s_Random.NextDouble() * (m_MaxExtrudeDistance - m_MinExtrudeDistance);
Ray dir =new Ray(
m_Mesh.transform.TransformPoint(Math.Average(m_Positions, activeFace.distinctIndexes)),
m_Mesh.transform.TransformDirection(m_ExtrudeDirection));
if (dir.GetPoint(distance).magnitude > m_MaxExtrudeDistance * 2f)
distance = m_MaxExtrudeDistance * 2f - dir.origin.magnitude;
StartCoroutine(ExtrudeFace(distance));
}
IEnumerator ExtrudeFace(float targetDistance)
{
float distance = 0f;
while (distance < targetDistance)
{
distance += m_ExtrudeSpeed * Time.deltaTime;
foreach (var index in m_Indices)
m_Positions[index] += m_ExtrudeDirection * m_ExtrudeSpeed * Time.deltaTime;
m_Mesh.positions = m_Positions;
m_Mesh.ToMesh();
m_Mesh.Refresh();
yield return null;
}
ChangeDirection();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment