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(); m_meshCollider = GetComponent(); 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 transformedVertices = new List(); 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; } }