using UnityEngine.UI; using UnityEngine; using System; using TMPro; using UnityEngine.UI.Extensions; using System.Text.RegularExpressions; using System.Collections.Generic; using System.Linq; using Jobberwocky.GeometryAlgorithms.Source.API; using Jobberwocky.GeometryAlgorithms.Source.Parameters; using Jobberwocky.GeometryAlgorithms.Source.Core; using System.Diagnostics; public class Create3D : MonoBehaviour { static public ResizeRoomCommand _resizeCommand; [SerializeField] VaultedCeiling vaultedCeiling; private void OnDisable() { Invoke(nameof(CancelRoomChanges), 0f); } public static float getValueMeasure(String S) { Text Vs = GameObject.Find(S).GetComponent(); String dataF = Vs.text; float Vn = DOIT.ConvertStringToNumber(dataF); return Vn; } public static void SetRoom() { _G.ceilx = 0; _G.ceily = _G.HEIGHT / 2; _G.ceilz = 0; _G.ceilw = _G.WIDE; _G.ceild = _G.DEPTH; } public static float lonvalue(string S1, string S2) { float V = 0; if (getValueMeasure(S1) > getValueMeasure(S2)) V = getValueMeasure(S1); else V = getValueMeasure(S2); return V; } public static void SetMeasureNew(float M, string m) { string Vs = DOIT.ConvertNumberToString(M); GameObject go = GameObject.Find(m); if (go != null) { Text text = go.GetComponent(); if (text) { text.text = Vs; } else { var textPro = go.GetComponent(); if (textPro != null) { textPro.text = Vs; } else { UnityEngine.Debug.LogError("Couldn't find reference to text object : " + m); } } } else { UnityEngine.Debug.LogError("Couldn't find reference to text object : " + m); } } //------------------------------------------Create Room----------------------------------------------------------------- public static void CreateRoom() { if (SceneModeManager.Floor) { DOIT.DELETEAllChild(SceneModeManager.Room); } RectTransform wallContainer = WallCreationManager.GetWallLineContainer(); List WallThicknesslist = new(); foreach (Transform wall in wallContainer.transform) { WallThicknesslist.Add(wall.gameObject.GetComponent().Thickness); //print("wall name========fff====" + wall + " thick====" + wall.gameObject.GetComponent().Thickness); } UnifyWalls.FollowOnSameDirection(); for (int i = 0; i < _G.NWExterior; i++) { if (wallContainer.GetChild(i).gameObject.GetComponent()._category == "Exterior") { float halfWidthWall = 0.25f; float angleWall = _G.WallsAngle[i]; float osx = -Mathf.Sin(angleWall * Mathf.Deg2Rad) * halfWidthWall; float osz = -Mathf.Cos(angleWall * Mathf.Deg2Rad) * halfWidthWall; //_G.WallAssociateWallLine.Add("w" + (i + 1) + "_" + i); CreateWallbyPoints(_G.WALL[i], "w" + (i + 1).ToString(), Mathf.Abs(_G.WallsWidth[i]), _G.WallsPointCenter[i].x, _G.WallsPointCenter[i].y, _G.WallsAngle[i]); //CreateWall(_G.WALL[i], "w" + (i + 1).ToString(), Mathf.Abs(_G.WallsWidth[i]), _G.HEIGHT, _G.WallsPointCenter[i].x, 0, _G.WallsPointCenter[i].y, 0, _G.WallsAngle[i], 0); //CreateSELECTOR(_G.Ws[i], "m" + (i + 1).ToString(), Mathf.Abs(_G.WallsWidth[i]), _G.HEIGHT, _G.WallsPointCenter[i].x + osx, 0, _G.WallsPointCenter[i].y + osz, 0, _G.WallsAngle[i], 0); } } CreateCeiling(); CreateFLOOR(); //Debug.Log("wall") float deltaHeight = _G.FLOOR != null ? _G.FLOOR.transform.position.y : -_G.ceily; deltaHeight = _G.FLOOR.transform.position.y - deltaHeight; //VaultedCeiling.Instance.CreateCeiling(); // TODO //vaultedCeiling.CreateCeiling(); _G.NAVIGATE = true; //_G.Count += 1; //REPOSITION opens Transform scene = SceneModeManager.Scene; if (scene.childCount > 0) { foreach (Transform O in scene) { O.gameObject.SetActive(true); } //print("-------Scene not empty---------------"); //GameObject SC = GameObject.Find("SCENE"); foreach (Transform O in scene) { float PX = 0; float PZ = 0; if (O.name.Length > 4) { int nO = Get.GetObjectIndex(O.name); string nW = _G.OBJs[nO][22]; //Debug.Log(O.name + " --- wall/ceil/floor : " + nW); PX = DOIT.ConvertStringToNumber(_G.OBJs[nO][15]); PZ = DOIT.ConvertStringToNumber(_G.OBJs[nO][17]); float py = deltaHeight; //if (!_P.DrawRoomRewrite && nW[..1] == "w") //{ // // get new XZ position // int wallIndex = int.Parse(nW[1..]) - 1; // Vector2 oldPosXZ = new Vector2(PX, PZ); // Vector2 newPosXZ = oldPosXZ - _G.OP[wallIndex] + _G.wP[wallIndex]; // Debug.Log($"op {_G.OP[wallIndex]} ; wp {_G.wP[wallIndex]}"); // // check if object is within wall boundries // int nextWallIndex = (wallIndex + 1) % _G.wP.Count; // Vector2 directionWallPoints = (_G.wP[nextWallIndex] - _G.wP[wallIndex]).normalized; // float boundWidthSize = DOIT.ConvertStringToNumber(_G.OBJs[nO][6]); // Vector2 pointRightWidthBound = newPosXZ + (directionWallPoints * boundWidthSize / 2.0f); // Vector2 directionRightwardBound = (pointRightWidthBound - _G.wP[nextWallIndex]).normalized; // float dotWallEnd = Vector2.Dot(-directionWallPoints, directionRightwardBound); // Debug.Log($"before : new xz {newPosXZ} ; old xz {oldPosXZ}"); // if (dotWallEnd < 0f) // { // newPosXZ += (Vector2)Vector3.Project(_G.wP[nextWallIndex] - pointRightWidthBound, -directionWallPoints); // } // Debug.Log($"after : new xz {newPosXZ}"); // // set new XZ position // PX = newPosXZ.x; // PZ = newPosXZ.y; //} if (nW[..1] == "w" || nW == SceneModeManager.Ceil.name) { if (_G.OBJs[nO][5] == "WA" || _G.OBJs[nO][5] == "CW" || O.name[..4] == "lamp") //Cabinet type : wall, cornerwall { py *= -1.0f; } } py += DOIT.ConvertStringToNumber(_G.OBJs[nO][16]); Vector3 objectExtents = O.GetComponent().bounds.extents; //Debug.Log($"before : {O.name} positioned at {new Vector3(PX, py, PZ)} ; z extent : {objectExtents.z}"); float roomBoundX = (_G.WIDE + 0.5f) / 2.0f - objectExtents.x; if (PX > roomBoundX) { PX = roomBoundX; } else if (PX < -roomBoundX) { PX = -roomBoundX; } float roomBoundZ = (_G.DEPTH + 0.5f) / 2.0f - objectExtents.z; if (PZ > roomBoundZ) { PZ = roomBoundZ; } else if (PZ < -roomBoundZ) { PZ = -roomBoundZ; } float roomBoundY = (_G.HEIGHT + 0.5f) / 2.0f - objectExtents.y; if (py > roomBoundY) { py = roomBoundY; } else if (py < -roomBoundY) { py = -roomBoundY; } _G.OBJs[nO][15] = PX.ToString(); _G.OBJs[nO][17] = PZ.ToString(); _G.OBJs[nO][16] = py.ToString(); O.position = new Vector3(PX, py, PZ); //Debug.Log($"after : {O.name} positioned at {O.position} ; room bound z : {roomBoundZ}"); } } } //StaticCoroutine.Start(SetHole()); //SetHole(); for (int i = 1; i < _G.NWExterior; i++) { _G.WallsDirection[i - 1] = DRAW.CalculateSense(_G.WallsPointStart[i - 1], _G.WallsPointStart[i]); } _G.WallsDirection[_G.NWExterior - 1] = DRAW.CalculateSense(_G.WallsPointStart[_G.NWExterior - 1], _G.WallsPointStart[0]); // connect last wall to first wall? //DeleteLastWall(); SetRoom(); if (_G.WMK[0] != "ND") ConstructMolding.AddMolding("B"); if (_G.WMO[0] != "ND") ConstructMolding.AddMolding("O"); _G.OW = _G.WallsPointCenter.GetRange(0, _G.WallsPointCenter.Count); _G.OP = _G.WallsPointStart.GetRange(0, _G.WallsPointStart.Count); if (_P.AutoSave_RoomId) { BackgroundSave.Instance.InitTimer(); } //Hide Wall foreach (Transform Wall in wallContainer) { if (Wall.gameObject.GetComponent().LineThickness == 2) { int WallNumber = int.Parse(string.Join(null, Regex.Split(Wall.name, "[^\\d]"))); GameObject wall = Get.o2("ROOM", "w" + WallNumber.ToString()); foreach (Transform s in wall.transform) { s.gameObject.GetComponent().material = _G.INV; } } } } public static void DeleteLastWall() { UnityEngine.Debug.Log(_G.NWExterior); if (_G.deleteLastWall == true) { if (_G.NWExterior < 1) return; GameObject wl = GameObject.Find("w" + _G.NWExterior).gameObject; GameObject ml = GameObject.Find("m" + _G.NWExterior).gameObject; Destroy(wl); Destroy(ml); } } private static void SetHole() //IEnumerator SetHole() { //yield return null; for (int i = 1; i < _G.NW + 1; i++) { //print("i=from crate3D=="+i); if (GameObject.Find("w" + i.ToString())) HOLE.wall("w" + i.ToString()); } } //------------------------------------------Create SHAPE-----------------------------------------------------------------// static void CreateWallbyPoints( GameObject Wall, string wallName, float wide, float positionX, float positionZ, float rotationY){ Wall = new() { name = wallName, tag = "wall" }; GameObject S = new() {name = "s1" }; int IndWall=int.Parse(wallName[1..]); Vector3 CenterWallPoint = GetCentroidXZ(_G.ExteriorWallPoints[IndWall-1]); List Newpoints=new(){}; foreach(Vector3 pt in _G.ExteriorWallPoints[IndWall-1]){ Newpoints.Add(pt-CenterWallPoint); } Vector3 CENTER = new(0, 0, 0); rotationY= _G.WallsAngle[IndWall-1];//GetAngleFromMaxXMinZ(_G.ExteriorWallPoints[IndWall-1]); //rint("rotationY===of "+wallName+" === "+rotationY); // foreach(Vector3 pt in Newpoints){ // if(wallName=="w3")//print(wallName+" Pts =====start"+pt); // } //Step 1 Position all points front of camera Z=0; List ListPoints= new (){}; foreach(Vector3 pt in Newpoints){ Vector3 translatedPoint = pt + CENTER; //if(wallName=="w3")print(wallName+" Pts ===== translatedPoint"+ translatedPoint); Quaternion R= Quaternion.AngleAxis(-rotationY, Vector3.up); //if(wallName=="w3")print(wallName+" Pts =====R"+R); Vector3 Newpoint=R * translatedPoint; //if(wallName=="w3")print(wallName+" Pts ===== Newpoint"+ Newpoint); Newpoint=new(Newpoint.x,Newpoint.y,0); ListPoints.Add(Newpoint); } CutHolesinMesh.SortPointsCounterClockwise(ListPoints); //(" Pts ========================================================="+wallName); // foreach(Vector3 pt in ListPoints){ // if(wallName=="w3")print(wallName+" Pts ====="+pt); // } S.AddComponent(typeof(MeshRenderer)); S.AddComponent(typeof(MeshFilter)); S.AddComponent(typeof(MeshCollider)); S.GetComponent().mesh = CreateMeshFromListPoints(ListPoints); S.GetComponent().sharedMesh = S.GetComponent().mesh; S.GetComponent().enabled = false; S.GetComponent().material = _G.WallsMaterial[IndWall-1]; S.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; S.GetComponent().probeAnchor = GameObject.Find("Reflection Probe").transform; DOIT.SetSizeTex(S, 48, 48, 0, 0, 0, 0, 90, 90); S.transform.SetParent(Wall.transform); Wall.transform.localRotation = Quaternion.Euler(0, rotationY, 0); Wall.transform.position =new Vector3(CenterWallPoint.x, 0, CenterWallPoint.z); Wall.transform.SetParent(SceneModeManager.Room); List Resetpoint=new(){}; foreach(Vector3 Point in ListPoints){ Vector3 NewPoint=new(Point.x,Point.y,-0.25f); Resetpoint.Add(NewPoint); } //SELECTION MESH GameObject SelMesh = new() { name = wallName, tag = "wall" }; SelMesh.name = "m"+IndWall.ToString(); SelMesh.tag = "mesh"; SelMesh.AddComponent(typeof(MeshRenderer)); SelMesh.AddComponent(typeof(MeshFilter)); SelMesh.AddComponent(typeof(MeshCollider)); //SelMesh.GetComponent().enabled = true; SelMesh.GetComponent().mesh = CreateMeshFromListPoints(ListPoints); SelMesh.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; SelMesh.GetComponent().receiveShadows = false; SelMesh.GetComponent().material = _G.INV; SelMesh.GetComponent().sharedMesh = SelMesh.GetComponent().mesh; SelMesh.transform.position = Wall.transform.position; SelMesh.transform.localRotation = Quaternion.Euler(0, rotationY, 0); SelMesh.transform.SetParent(SceneModeManager.Room); Vector3 Forward = SelMesh.transform.forward.normalized; SelMesh.transform.position -= 0.1f * Forward; wide =GetWideWallFromPoints(ListPoints);//_G.WallsWidth[IndWall-1]; DOIT.SetSizeTex(SelMesh , wide, _G.HEIGHT, 0, 0, 0, 0, 90, 90); //print("wide===="+wide); //TOP // GameObject WT = new("Top" + wallName); // GameObject top = GameObject.CreatePrimitive(PrimitiveType.Quad); // top.transform.localScale = new Vector3(wide + 6, 6, 0.1f); // top.transform.SetLocalPositionAndRotation(new Vector3(positionX, _G.HEIGHT*0.5f, positionZ), Quaternion.Euler(90, rotationY, 0)); // top.transform.SetParent(WT.transform); // top.name = "top"; // top.GetComponent().material = UIT_MATERIAL.GetMaterial("888888_Matt"); // WT.transform.SetParent(SceneModeManager.Room); // WT.tag = "TopWall"; // _G.WallsWidth[IndWall-1]=wide; // WT.SetActive(true); // top.SetActive(true); //Covers for wall light bleeding // GameObject Cover = new("CoverWall " + wallName); // //TOP // Vector3 Size = new( wide+ 6, 6, 0.1f); // Vector3 Position = new(0,_G.HEIGHT*0.5f+ 1, 0); // AddCoverCorner(Cover, "Top", Size, Position, 90, 0); // //Left // Size = new(6, _G.HEIGHT+ 2, 1f); // Position = new(- wide*0.5f - 1, 0, 0); // AddCoverCorner(Cover, "Left", Size, Position, 0, 90); // //Right // Size = new(6, _G.HEIGHT + 2, 1f); // Position = new(wide*0.5f+ 1, 0, 0); // AddCoverCorner(Cover, "Right", Size, Position, 0, -90); //Set to Room // Cover.transform.localRotation = Quaternion.Euler(0, rotationY, 0); // Cover.transform.position = new Vector3(positionX, 0, positionZ); // Cover.transform.SetParent(SceneModeManager.Room); // Cover.layer = 17; int wn = int.Parse(wallName[1..]); } static void AddCoverCorner(GameObject Cover, string Name, Vector3 Size, Vector3 Position, float Ax, float Ay) { GameObject CoverMCX = GameObject.CreatePrimitive(PrimitiveType.Quad); CoverMCX.name = "Covert" + Name; CoverMCX.transform.localScale = Size; CoverMCX.transform.SetLocalPositionAndRotation(Position, Quaternion.Euler(Ax, Ay, 0)); CoverMCX.GetComponent().material = UIT_MATERIAL.GetMaterial("888888_Matt"); Destroy(CoverMCX.GetComponent()); CoverMCX.transform.SetParent(Cover.transform); CoverMCX.layer = 17; } static GameObject CreatePoint(string Name, float x, float y, float z) { //print("createRoom()--3----"); GameObject point = GameObject.CreatePrimitive(PrimitiveType.Cube); //point.GetComponent().enabled = false; point.name = Name; point.transform.position = new Vector3(x, y, z); point.transform.localScale = new Vector3(0, 0, 0); point.transform.GetComponent().material = _G.INV; return point; } static void CreateFLOOR() { UnifyWalls.CreateFloorPoints(); List NewFloor=new(){}; foreach(Vector3 V3 in _G.FloorPoints[0]) { NewFloor.Add(V3); } List FloorFacing=new(){}; foreach(Vector3 V3 in NewFloor) { Vector3 NewPts = new(V3.x,V3.z,0); FloorFacing.Add(NewPts); } _G.FLOOR = new(name: "floor") { tag = "floor" }; _G.FLOOR.AddComponent(typeof(MeshFilter)); _G.FLOOR.AddComponent(typeof(MeshRenderer)); _G.FLOOR.AddComponent(typeof(MeshCollider)); _G.FLOOR.GetComponent().mesh = CreateMeshTriangulate(FloorFacing,"Back",null); _G.FLOOR.transform.eulerAngles=new(90,0,0); _G.FLOOR.transform.SetParent(SceneModeManager.Room); _G.FLOOR.GetComponent().enabled = false; _G.FLOOR.GetComponent().sharedMesh = _G.FLOOR.GetComponent().mesh; _G.FLOOR.transform.position = new Vector3(0, -_G.HEIGHT*0.5f, 0);//+_G.RoomOffset; DOIT.SetSizeTex(_G.FLOOR, 96, 96, 0, 0, 0, 0, 90, 90); _G.FLOOR.GetComponent().probeAnchor = ReflectionProbesUpdater.ReflectionProbeNormal.transform; _G.FLOOR.GetComponent().probeAnchor = GameObject.Find("Reflection Probe").transform; CreateFloor.SetFloor(isFirstCreation: _G.FLC[0] == "Plywood12x14"); //_G.FLOOR.SetActive(false); //Selected Mesh _G.Fs = Instantiate(_G.FLOOR); _G.Fs.name="sfloor"; _G.Fs.tag = "floor"; _G.Fs.transform.position = new Vector3(0, -_G.HEIGHT*0.5f+0.25f, 0);//+_G.RoomOffset; _G.Fs.GetComponent().enabled = true; _G.Fs.GetComponent().material = _G.INV; DOIT.SetSizeTex(_G.Fs, _G.WIDE, _G.DEPTH, 0, 0, 0, 0, 90, 90); _G.Fs.GetComponent().sharedMesh = _G.Fs.GetComponent().mesh; _G.Fs.transform.SetParent(SceneModeManager.Room); _G.Fs.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; _G.Fs.GetComponent().probeAnchor = GameObject.Find("Reflection Probe").transform; } static void CreateCeiling() { CathedralCeiling.DefaultCeilingRecipe(); _G.CEIL = new("ceil") { tag = "ceilling", layer = 6 }; for(int i=0; i<_G.CeilingPoints.Length; i++) { // foreach(Vector3 V3 in _G.CeilingPoints[i]) // { // print("Ceiling point start=t==="+V3); // } List NewHeight = new(){}; foreach(Vector3 V3 in _G.CeilingPoints[i]) { Vector3 Point = new(V3.x,V3.y-_G.HEIGHT,V3.z); NewHeight.Add(Point); } Vector3 normal = CalculateNormal(NewHeight);//print("normal=============================================="+normal); Vector3 CenterPlane = CalculateCenter(NewHeight);//print("CenterPlane=============================================="+CenterPlane); Quaternion rotationFlip = Quaternion.FromToRotation(normal,new(0,0,-1)); //print("rotationFlip==========================================="+rotationFlip); Quaternion rotationReFlip = Quaternion.FromToRotation(new(0,0,-1),normal); //print("rotationFlip==========================================="+rotationFlip); for (int n = 0; n < NewHeight.Count; n++){ NewHeight[n] = rotationFlip*NewHeight[n]; } float CenterY=Calculate_Y_Center(NewHeight); List CeilingFacing=NewHeight;//new(){}; GameObject S = new() {name = "s"+(i+1).ToString() }; S.AddComponent(typeof(MeshFilter)); S.AddComponent(typeof(MeshRenderer)); S.AddComponent(typeof(MeshCollider)); S.tag= "ceilling"; S.layer= 6; S.GetComponent().renderingLayerMask |= (1u << 1); //int LayerIgnoreRaycast = LightLayerMask.NameToLayer("Light Layer 1"); //print("Current layer: " + S.layer); //S.GetComponent().renderingLayerMask=2; //S.transform.eulerAngles=new(180,0,0); S.GetComponent().mesh = CreateMeshTriangulate(CeilingFacing,"Front",null); DOIT.SetSizeTex(S, 48, 48, 0, 0, 0, 0, 90, 90); S.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; S.GetComponent().material = _G.ceilm; // gypse mat if (!string.IsNullOrEmpty(_P.ceiling_Color)) { MeshRenderer ceilingRenderer=S.GetComponent(); if(ColorUtility.TryParseHtmlString(_P.ceiling_Color, out Color myColor)) { ceilingRenderer.material.SetTexture("_MainTex", null); ceilingRenderer.material.SetColor("_c1", myColor); ceilingRenderer.material.SetColor("_c2", myColor); ceilingRenderer.material.SetColor("_c3", myColor); ceilingRenderer.material.SetFloat("_smoothness", 0.5f); ceilingRenderer.material.SetFloat("_normal", 0f); } else { UnityEngine.Debug.Log($"The hexadecimal value {_P.ceiling_Color} of Ceiling Color is wrong, reverting to default setting"); } } S.GetComponent().sharedMesh = S.GetComponent().mesh; S.GetComponent().enabled=false; S.GetComponent().probeAnchor = ReflectionProbesUpdater.ReflectionProbeNormal.transform; //S.transform.position+=_G.RoomOffset; //Vector3 Rot= S.transform.eulerAngles; S.transform.rotation=rotationReFlip; S.transform.position=new(0,0,0); S.transform.SetParent(_G.CEIL.transform); S.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; S.GetComponent().probeAnchor = GameObject.Find("Reflection Probe").transform; _G.CEIL.transform.transform.eulerAngles=new(0,0,0 ); _G.CEIL.transform.SetParent(SceneModeManager.Room); _G.Cs = Instantiate(S); _G.Cs.name="sceil"+i; _G.Cs.GetComponent().material = _G.INV; _G.Cs.GetComponent().enabled=true; _G.Cs.transform.position=new(0,-0.25f,0); DOIT.SetSizeTex(_G.Cs, _G.WIDE, _G.DEPTH, 0, 0, 0, 0, 90, 90); _G.Cs.transform.SetParent(SceneModeManager.Room); _G.Cs.transform.position=new Vector3(S.transform.position.x, _G.HEIGHT*0.5f-0.25f,S.transform.position.z); _G.Cs.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; _G.Cs.GetComponent().probeAnchor = GameObject.Find("Reflection Probe").transform; } _G.CEIL.transform.position=new Vector3(0, _G.HEIGHT*0.5f,0); } static Vector3 CalculateCenter(List points) { if (points == null || points.Count == 0) { UnityEngine.Debug.LogWarning("Point list is empty or null!"); return Vector3.zero; } // Initialize min and max values float minX = float.MaxValue, minY = float.MaxValue, minZ = float.MaxValue; float maxX = float.MinValue, maxY = float.MinValue, maxZ = float.MinValue; // Iterate through the points to find min and max for each axis foreach (Vector3 point in points) { if (point.x < minX) minX = point.x; if (point.y < minY) minY = point.y; if (point.z < minZ) minZ = point.z; if (point.x > maxX) maxX = point.x; if (point.y > maxY) maxY = point.y; if (point.z > maxZ) maxZ = point.z; } // Calculate the center as the midpoint of min and max on each axis float centerX = (minX + maxX) / 2f; float centerY = (minY + maxY) / 2f; float centerZ = (minZ + maxZ) / 2f; return new Vector3(centerX, centerY, centerZ); } static float Calculate_Y_Center(List points) { // Initialize min and max values float minX = float.MaxValue, minY = float.MaxValue, minZ = float.MaxValue; float maxX = float.MinValue, maxY = float.MinValue, maxZ = float.MinValue; // Iterate through the points to find min and max for each axis foreach (Vector3 point in points) { if (point.x < minX) minX = point.x; if (point.y < minY) minY = point.y; if (point.z < minZ) minZ = point.z; if (point.x > maxX) maxX = point.x; if (point.y > maxY) maxY = point.y; if (point.z > maxZ) maxZ = point.z; } // Calculate the center as the midpoint of min and max on each axis float centerX = (minX + maxX) / 2f; float centerY = Math.Abs(minY - maxY) / 2f; float centerZ = (minZ + maxZ) / 2f; return centerY; } static Vector3 CalculateNormal(List points) { Vector3 normal = Vector3.zero; // Use Newell's method to calculate the normal for (int i = 0; i < points.Count; i++) { Vector3 current = points[i]; Vector3 next = points[(i + 1) % points.Count]; normal.x += (current.y - next.y) * (current.z + next.z); normal.y += (current.z - next.z) * (current.x + next.x); normal.z += (current.x - next.x) * (current.y + next.y); } return normal.normalized; } //MESH---------------------------------------------------------------------------------//MESH //------------------------------------------Creatye MESH-----------------------------------------------------------------// // } private void CancelRoomChanges() { GameObject buttonX = Get.o2("Panel_ShowPlan", "X"); if (buttonX != null) { return; } if (_resizeCommand != null) { _resizeCommand.Undo(); _resizeCommand = null; } } private static Mesh CreateMesh4Points( Vector3 P1, Vector3 P2, Vector3 P3, Vector3 P4) { Mesh m = new() { vertices = new[] { P1, P2, P3, P4 }, uv = new Vector2[] { new (0, 0), new (0, 1), new (1, 1), new (1, 0), }, triangles = new int[] { 0, 1, 2, 0, 2, 3 } }; m.RecalculateNormals(); m.RecalculateTangents(); return m; } static List SortVectorsClockwise(List vectors) { // Group vectors by their Y value var groupedByY = vectors .GroupBy(v => v.y) .OrderBy(g => g.Key) // Optional: Sort groups by Y value .ToList(); List sortedList = new List(); foreach (var group in groupedByY) { // Sort vectors in each group by angle in the XZ plane (ignoring Y) var sortedGroup = group .OrderBy(v => Mathf.Atan2(v.z, v.x)).Reverse() // Sort by angle using arctangent .Select(v => new Vector2(v.x, v.z)) // Convert Vector3 to Vector2 (discarding Y) .ToList(); // Add the sorted group to the final list sortedList.AddRange(sortedGroup); } return sortedList; } static Mesh CreateMeshCeilling(List LineVectors) { Vector3[] vertices=new Vector3[LineVectors.Count]; Vector2[] vertices2D =new Vector2[LineVectors.Count]; for(int i=0; i LineVectors) { Vector3[] vertices=new Vector3[LineVectors.Count]; Vector2[] vertices2D =new Vector2[LineVectors.Count]; for(int i=0; i ListVectors) { Vector3[] vertices=new Vector3[ListVectors.Count]; Vector2[] vertices2D =new Vector2[ListVectors.Count]; for(int i=0; i points) { // Calculate the centroid (or you could use the origin if preferred) //Vector3 centroid = GetCentroid(points); Vector3 centroid=Vector3.zero; // Sort the points based on their angle relative to the centroid points.Sort((a, b) => CompareCounterclockwise(a, b, centroid)); //return points; } public static List 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)); return points; } 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 Vector3 GetCentroidXZ(List points) { float MinX=points[0].x; float MaxX=points[0].x; float MinZ=points[0].z; float MaxZ=points[0].z; foreach (Vector3 point in points) { if(point.xMaxX)MaxX=point.x; if(point.zMaxZ)MaxZ=point.z; } Vector3 VMin=new(MinX,0,MinZ); Vector3 VMax=new(MaxX,0,MaxZ); Vector3 centroid=Vector3.Lerp(VMin, VMax,0.5f); 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.z, dirA.x); float angleB = Mathf.Atan2(dirB.z, 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); } public static float GetAngleFromMaxXMinZ(List points) { if (points == null || points.Count < 2) { UnityEngine.Debug.LogWarning("Not enough points to calculate angle."); return 0f; } float MaxX=points[0].x; float MinX=points[0].x; float MaxZ=points[0].z; float MinZ=points[0].z; foreach (Vector3 point in points) { if (point.x > MaxX ) {MaxX=point.x; } if (point.x < MinX ) {MinX=point.x; } if (point.z > MaxZ ) {MaxZ=point.z; } if (point.z < MinZ ) {MinZ=point.z; } } Vector2 MaxPoint=new(MaxX,MaxZ); Vector2 MinPoint=new(MinX,MinZ); Vector2 direction=MinPoint-MaxPoint; direction=direction.normalized; Vector2 xAxis = Vector2.right; // (1, 0) float angle = Vector2.Angle(direction, xAxis); float cross = direction.x * xAxis.y - direction.y * xAxis.x; if (cross < 0) // Negative cross means clockwise { angle = 360f - angle; } //print("angle===="+angle); return angle; } public static float GetWideFromMaxXMinZ(List points) { if (points == null || points.Count < 2) { UnityEngine.Debug.LogWarning("Not enough points to calculate angle."); return 0f; } float MaxX=points[0].x; float MinX=points[0].x; float MaxZ=points[0].z; float MinZ=points[0].z; foreach (Vector3 point in points) { if (point.x > MaxX ) {MaxX=point.x; } if (point.x < MinX ) {MinX=point.x; } if (point.z > MaxZ ) {MaxZ=point.z; } if (point.z < MinZ ) {MinZ=point.z; } } Vector2 MaxPoint=new(MaxX,MaxZ); Vector2 MinPoint=new(MinX,MinZ); float Distance=Vector2.Distance(MaxPoint, MinPoint); return Distance; } public static List SortCounterClockwise(List points, Vector3 center) { // Reference direction for angle calculations Vector3 reference = new Vector3(1, 0, 0); const float angleThreshold = 0.001f; // Precision threshold for angle comparison points.Sort((a, b) => { // Compute vectors from center to points Vector3 dirA = a - center; Vector3 dirB = b - center; // Compute angles relative to the reference vector float angleA = Vector3.SignedAngle(reference, dirA, Vector3.up); float angleB = Vector3.SignedAngle(reference, dirB, Vector3.up); // Normalize angles to [0, 360) if (angleA < 0) angleA += 360; if (angleB < 0) angleB += 360; // Debugging output UnityEngine.Debug.Log($"Point A: {a}, Angle A: {angleA}, Distance A: {dirA.magnitude}"); UnityEngine.Debug.Log($"Point B: {b}, Angle B: {angleB}, Distance B: {dirB.magnitude}"); // Compare angles with threshold if (Mathf.Abs(angleA - angleB) > angleThreshold) { return angleA.CompareTo(angleB); // Counterclockwise order } // Fallback: Use distance from center to break tie float distanceA = dirA.magnitude; float distanceB = dirB.magnitude; if (!Mathf.Approximately(distanceA, distanceB)) { return distanceA.CompareTo(distanceB); } // Final fallback: Use coordinate comparison (X, then Z) to ensure stability if (!Mathf.Approximately(a.x, b.x)) { return a.x.CompareTo(b.x); } return a.z.CompareTo(b.z); }); return points; } public static List SortClockwise(List points, Vector3 center){ points.Sort((a, b) => CompareClockwise(a, b)); // foreach(Vector3 point in points){ // print("point==cw"+point); // } return points; } public static int CompareClockwise(Vector3 a, Vector3 b) {// Compute angles relative to the positive X-axis float angleA = Mathf.Atan2(a.z, a.x); float angleB = Mathf.Atan2(b.z, b.x); // If angles are the same, prioritize closer points (optional) if (Mathf.Approximately(angleA, angleB)) { float distanceA = a.x * a.x + a.z * a.z; // Avoid costly square root float distanceB = b.x * b.x + b.z * b.z; return distanceA.CompareTo(distanceB); } // Sort by angle in ascending order (clockwise) return angleA.CompareTo(angleB); } 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; } public static float GetWideWallFromPoints(List ListPoints){ float Xmin=0; float Xmax=0; foreach(Vector3 Point in ListPoints){ if(Point.xXmax){Xmax=Point.x;} } return Mathf.Abs(Xmax-Xmin); } //TRAINGULATION-------------------------------------------------------------------------------- public static Mesh CreateMeshTriangulate( List PointsContour,string side,List[] HolesArray) { GameObject.Find("HIDER").transform.Find("LoadingCircle").gameObject.SetActive(true); 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); return mesh; } }