using System.Collections.Generic; using UnityEngine; using Habrador_Computational_Geometry; using System.Diagnostics; using Unity.Collections; using Unity.Mathematics; using Jobberwocky.GeometryAlgorithms.Source.API; using Jobberwocky.GeometryAlgorithms.Source.Parameters; using Jobberwocky.GeometryAlgorithms.Source.Core; using System; using System.Collections; public class CutHolesinMesh: MonoBehaviour { //static List PointsContour; //static List[] HolesArray; //static Mesh Newmesh; //static MeshFilter filter; public static void RedoMesh(GameObject Wall, List OuterPolygon,List[] Holes){ //GameObject.Find("HIDER").transform.Find("LoadingCircle").gameObject.SetActive(true); //Step 1: Move all points by offset-------------------------------------------------Step 1: Vector3 CENTER = new(0, 0, 0); Vector3 centerFace = Wall.transform.position; Vector3 Offset=centerFace-CENTER; List NewOuterPolygon=new(){}; for(int i=0; i holeIn in Holes){ for(int i=0; i< holeIn.Count; i++){ holeIn[i]-=Offset; } } } //Step 2: Rotate all points--------------------------------------------------------Step 2: float Rotation= Wall.transform.eulerAngles.y;//0 ,90, 180, 270 for(int i=0; i holeIN in Holes) { for(int i=0; i< holeIN.Count; i++){ Vector3 translatedPoint = holeIN[i] + CENTER; Quaternion R= Quaternion.AngleAxis(-Rotation, Vector3.up); holeIN[i]=R * translatedPoint; holeIN[i]+=CENTER; } } } //Set clock rotaion SortPointsCounterClockwise(NewOuterPolygon); //Step 3: Set Out and Holes points----------------------------------------------Step 3 ///EAR CLIPPING-------------------------------------------------------------/EAR CLIPPING //List outerPolygon= new(); //List holeVertices; // foreach (Vector3 vec3 in NewOuterPolygon) // { // outerPolygon.Add(new(vec3.x, vec3.y)); // } // List> holes = new (); // for(int i=0; i(); // meshFilter.mesh= Newmesh; // meshFilter.transform.position=s.transform.position; // Vector3[] vertices = Newmesh.vertices; // Quaternion rotation = Quaternion.Euler(0, 0, 0f); // Vector3 position=s.transform.position; // for (int i = 0; i < vertices.Length; i++) // { // vertices[i] = rotation * vertices[i]; // } // Newmesh.vertices = vertices; // Newmesh.RecalculateBounds(); // Newmesh.RecalculateNormals(); // DOIT.SetSizeTex(s, 48, 48, 0, 0, 0, 0, 90, 90); } public static float GetWallRotation(Vector3 PointStart, Vector3 PointEnd) { Vector3 DirCurrent = (PointStart-PointEnd).normalized; Vector3 AxeX = new(-1, 0, 0); float Angle=Vector2.Angle(DirCurrent, AxeX); float newAngle = (Angle + 360) % 360; return newAngle; } public static Mesh CreateMesh(List outerPolygon,List> holes ){ Stopwatch timer = new (); timer.Start(); //Perform triangulation and check if it's valid HashSet triangulation = _EarClipping.Triangulate(outerPolygon, holes); if (triangulation == null) { UnityEngine.Debug.LogError("Triangulation failed, check input data."); //return } // Convert the triangulated data to a Unity mesh and check if it's valid Mesh mesh = _TransformBetweenDataStructures.Triangles2ToMesh(triangulation, true); if (mesh == null) { UnityEngine.Debug.LogError("Mesh conversion failed."); } timer.Stop(); UnityEngine.Debug.Log("Triangulation and mesh generation took: " + timer.ElapsedMilliseconds + " ms"); //mesh.uv = uvs; // mesh.RecalculateNormals(); mesh.RecalculateBounds(); mesh.RecalculateTangents(); // outerPolygon.Dispose(); // outTriangles.Dispose(); //GameObject.Find("HIDER").transform.Find("LoadingCircle").gameObject.SetActive(false); return mesh; } public static List CreateConstraints(List outerBoundary, List holeBoundary) { var constraints = new List(); // Add constraints for outer boundary for (int i = 0; i < outerBoundary.Count; i++) { constraints.Add(new int2(i, (i + 1) % outerBoundary.Count)); } // Add constraints for hole boundary int offset = outerBoundary.Count; for (int i = 0; i < holeBoundary.Count; i++) { constraints.Add(new int2(offset + i, offset + (i + 1) % holeBoundary.Count)); } return constraints; } public static void SortPointsCounterClockwise(List points) { // Calculate the centroid (or you could use the origin if preferred) Vector3 centroid = GetCentroid(points); // Sort the points based on their angle relative to the centroid points.Sort((a, b) => CompareCounterclockwise(a, b, centroid)); } public static void SortPointsClockwise(List points) { // Calculate the centroid (or you could use the origin if preferred) Vector3 centroid = GetCentroid(points); // Sort the points based on their angle relative to the centroid points.Sort((a, b) => CompareAngles(a, b, centroid)); } // Calculate centroid of the points (ignore y) public static Vector3 GetCentroid(List points) { Vector3 centroid = Vector3.zero; foreach (Vector3 point in points) { centroid.x += point.x; centroid.z += point.z; } centroid.x /= points.Count; centroid.z /= points.Count; return centroid; } public static int CompareAngles(Vector3 a, Vector3 b, Vector3 centroid) { // Calculate the angle of the points relative to the centroid float angleA = Mathf.Atan2(a.z - centroid.z, a.x - centroid.x); float angleB = Mathf.Atan2(b.z - centroid.z, b.x - centroid.x); // We want to sort in clockwise order, so reverse the order return angleA.CompareTo(angleB); } public static int CompareCounterclockwise(Vector3 a, Vector3 b, Vector3 center) { // Calculate vectors relative to the center Vector3 dirA = a - center; Vector3 dirB = b - center; // Compute angles from the positive X-axis (projected onto the XY plane) float angleA = Mathf.Atan2(dirA.y, dirA.x); float angleB = Mathf.Atan2(dirB.y, dirB.x); // Ensure angles are in [0, 2π] range angleA = (angleA + Mathf.PI * 2) % (Mathf.PI * 2); angleB = (angleB + Mathf.PI * 2) % (Mathf.PI * 2); // Compare angles for sorting return angleA.CompareTo(angleB); } //TRAINGULATION-------------------------------------------------------------------------------- public static IEnumerator CreateMeshTriangulate( List PointsContour,string side,List[] HolesArray,GameObject Wall) { //Stopwatch timer = new (); //timer.Start(); Vector3[] Boundarys = PointsContour.ToArray(); Triangulation2DParameters parameters = new() { Points = PointsContour.ToArray(), Boundary = Boundarys, Side = Side.Back, Delaunay = true }; if(side=="Front")parameters .Side = Side.Front; TriangulationAPI triangulationAPI = new(); if(HolesArray !=null){ parameters.Holes = ConvertHolesToArray(HolesArray); } var mesh = triangulationAPI.Triangulate2D(parameters); //timer.Stop(); Vector3[] vertices = mesh.vertices; Quaternion rotation = Quaternion.Euler(0, 0, 0f); for (int i = 0; i < vertices.Length; i++) { vertices[i] = rotation * vertices[i]; } mesh.vertices = vertices; mesh.RecalculateBounds(); mesh.RecalculateNormals(); //DOIT.SetSizeTex(s, 48, 48, 0, 0, 0, 0, 90, 90); Mesh Newmesh=mesh; GameObject s=Wall.transform.Find("s1").gameObject; MeshFilter meshFilter = s.GetComponent(); meshFilter.mesh= Newmesh; meshFilter.transform.position=s.transform.position; vertices = Newmesh.vertices; rotation = Quaternion.Euler(0, 0, 0f); Vector3 position=s.transform.position; for (int i = 0; i < vertices.Length; i++) { vertices[i] = rotation * vertices[i]; } Newmesh.vertices = vertices; Newmesh.RecalculateBounds(); Newmesh.RecalculateNormals(); DOIT.SetSizeTex(s, 48, 48, 0, 0, 0, 0, 90, 90); yield return new WaitForSeconds(0.25f); // GameObject.Find("HIDER").transform.Find("LoadingCircle").gameObject.SetActive(false); //yield return null; } public static Vector3[][] ConvertHolesToArray(List[] holesListArray) { Vector3[][] result = new Vector3[holesListArray.Length][]; for (int i = 0; i < holesListArray.Length; i++) { result[i] = holesListArray[i].ToArray(); } return result; } }