using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
public class MeshCurver : MonoBehaviour
|
|
{
|
|
|
|
[Header("References")]
|
|
[SerializeField]
|
|
private RotationController m_pivot;
|
|
|
|
[Header("Settings")]
|
|
[SerializeField]
|
|
private bool m_ApplyAtStart = true;
|
|
[SerializeField]
|
|
private bool m_UpdateCollider = true;
|
|
|
|
[Header("Debug")]
|
|
[SerializeField]
|
|
private bool m_CalculateEachUpdate = false;
|
|
|
|
|
|
private Mesh m_startMesh;
|
|
private MeshFilter m_meshFilter;
|
|
private MeshCollider m_meshCollider;
|
|
|
|
private void Start()
|
|
{
|
|
m_meshFilter = GetComponent<MeshFilter>();
|
|
m_meshCollider = GetComponent<MeshCollider>();
|
|
|
|
m_startMesh = m_meshFilter.mesh;
|
|
if (m_ApplyAtStart)
|
|
UpdateMesh();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (m_CalculateEachUpdate)
|
|
UpdateMesh();
|
|
}
|
|
|
|
[ContextMenu("Update Mesh")]
|
|
public void UpdateMesh()
|
|
{
|
|
Mesh newMesh = UpdateMesh(m_pivot.Position, m_startMesh, m_pivot.RotationAxis, transform);
|
|
m_meshFilter.mesh = newMesh;
|
|
|
|
if (m_meshCollider != null && m_UpdateCollider)
|
|
m_meshCollider.sharedMesh = newMesh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public Mesh UpdateMesh(Vector3 centre, Mesh mesh, Vector3 Axis, Transform origin)
|
|
{
|
|
|
|
List<Vector3> transformedVertices = new List<Vector3>();
|
|
Vector3[] vertices = mesh.vertices;
|
|
Vector3 closestPoint = origin.TransformPoint(vertices.OrderBy(p => Vector3.Distance(centre, origin.TransformPoint(p))).First());
|
|
Vector3 direction = closestPoint - centre;
|
|
Vector3 perpendicular = Vector3.Cross(Axis, direction).normalized;
|
|
|
|
Debug.DrawLine(centre, closestPoint, Color.red);
|
|
|
|
float radius = direction.magnitude;
|
|
|
|
foreach (Vector3 vertex in vertices)
|
|
{
|
|
Vector3 worldPosition = origin.TransformPoint(vertex);
|
|
Vector3 directionFromStartPoint = Vector3.ProjectOnPlane(worldPosition - closestPoint, Axis);
|
|
Vector3 planeOffset = Vector3.Project(worldPosition - closestPoint, Axis);
|
|
float heightOffset = radius - Vector3.Project(worldPosition-centre,direction.normalized).magnitude;
|
|
|
|
float arcLength = directionFromStartPoint.magnitude;
|
|
float angle = (arcLength / radius);
|
|
if (Vector3.Dot(directionFromStartPoint, perpendicular) < 0)
|
|
angle = -angle;
|
|
|
|
Vector3 directionFromCentre = Quaternion.AngleAxis(Mathf.Rad2Deg * angle, Axis) * ((direction));
|
|
transformedVertices.Add((origin.InverseTransformPoint(centre + directionFromCentre.normalized * (radius - heightOffset) + planeOffset)));
|
|
}
|
|
|
|
Mesh retVal = new Mesh();
|
|
retVal.vertices = transformedVertices.ToArray();
|
|
retVal.triangles = mesh.triangles;
|
|
retVal.uv = mesh.uv;
|
|
|
|
retVal.RecalculateNormals();
|
|
retVal.RecalculateTangents();
|
|
retVal.RecalculateBounds();
|
|
|
|
return retVal;
|
|
}
|
|
|
|
}
|