using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text.RegularExpressions; using UnityEngine; public class CreateInteriorWalls : MonoBehaviour { static float thickness, thicknessStart, thicknessEnd, StartHeight, EndHeight; static Vector3[] AllPoints; static Vector3 PointStart, PointEnd; static RectTransform wallContainer; static Vector3[] PointsLineCurrent, PointsLinePrevious, PointsLineNext; static Vector3 DirectionFrontWall; static Vector3 FrontProjectionStart, BackProjectionStart, FrontProjectionEnd, BackProjectionEnd; static List InteriorWallContainer; static List WallSeries; static int NumberOfInteriorWalls; //-----------CREATE---------------------------------------------- public static void InteriorWall() { _G.INTERIOR_WALLS = new(); _G.InteriorWallsPoints= new(); _G.InteriorBackEndWall= new(); NumberOfInteriorWalls = _G.NWExterior + 1; AllPoints = new Vector3[8]; wallContainer = WallCreationManager.GetWallLineContainer(); InteriorWallContainer = GetInteriorWalls(); int wallQty = InteriorWallContainer.Count; for (int i = 0; i < wallQty; i++) { PointsLineCurrent = GetPointsFromLine(i); WallLine currentWallLine = InteriorWallContainer[i].GetComponent(); WallPoint startPoint, endPoint; WallLineInfo wallInfo; bool connectToPrevious, connectToNext; WallLine.CreateWallInfo(currentWallLine, out startPoint, out endPoint, out wallInfo, out connectToPrevious, out connectToNext); StartHeight = startPoint._PointHeight; EndHeight = endPoint._PointHeight; CreateWall(i, currentWallLine, wallInfo, connectToPrevious, connectToNext); wallInfo.ApplyOffset( _G.RoomOffset); } } public static void CreateWall(int i, WallLine wallLine, WallLineInfo wallInfo, bool connectToPrevious, bool connectToNext) { //_G.NW -= 1; float Floor = -_G.HEIGHT * 0.5f; AllPoints[0] = new(wallInfo.frontProjectionStart.x, Floor, wallInfo.frontProjectionStart.z); AllPoints[1] = new(wallInfo.frontProjectionStart.x, Floor + StartHeight, wallInfo.frontProjectionStart.z); AllPoints[2] = new(wallInfo.frontProjectionEnd.x, Floor + EndHeight, wallInfo.frontProjectionEnd.z); AllPoints[3] = new(wallInfo.frontProjectionEnd.x, Floor, wallInfo.frontProjectionEnd.z); AllPoints[4] = new(wallInfo.backProjectionStart.x, Floor, wallInfo.backProjectionStart.z); AllPoints[5] = new(wallInfo.backProjectionStart.x, Floor + StartHeight, wallInfo.backProjectionStart.z); AllPoints[6] = new(wallInfo.backProjectionEnd.x, Floor + EndHeight, wallInfo.backProjectionEnd.z); AllPoints[7] = new(wallInfo.backProjectionEnd.x, Floor, wallInfo.backProjectionEnd.z); wallLine.interiorWallFacesNumber.Clear(); int currentMatIndex = 0; CreateFacesCube(i, "Front", AllPoints, wallLine.mat[currentMatIndex], wallInfo, wallLine); CreateFacesCube(i, "Back", AllPoints, wallLine.mat[++currentMatIndex], wallInfo, wallLine); //if (!connectToPrevious) //{ CreateFacesCube(i, "Left", AllPoints, wallLine.mat[++currentMatIndex], wallInfo, wallLine); //} //if (!connectToNext) //{ CreateFacesCube(i, "Right", AllPoints, wallLine.mat[++currentMatIndex], wallInfo, wallLine); //} CreateFacesCube(i, "Top", AllPoints, wallLine.mat[++currentMatIndex], wallInfo, wallLine); } static void AddUpwardFacingTriangle(Vector3 p1, Vector3 p2, Vector3 p3, Material mat, Transform parent, int triangleIndex) { // Calculate the normal of the triangle Vector3 normal = Vector3.Cross(p2 - p1, p3 - p1).normalized; // Check if the triangle normal is pointing downwards (negative Y) if (normal.y < 0) { // If so, swap the last two points to reverse winding and face upward AddTriangleToMesh(p1, p3, p2, mat, parent, triangleIndex); } else { // Otherwise, add as usual AddTriangleToMesh(p1, p2, p3, mat, parent, triangleIndex); } } public static void CreateFacesCube(int i, string Name, Vector3[] AllPoints, Material Mat, WallLineInfo wallInfo, WallLine wallLine = null) { GameObject Face = new("w" + NumberOfInteriorWalls.ToString()) { tag = "wall" }; Face.transform.SetParent(SceneModeManager.Room); if (wallLine != null) { wallLine.interiorWallFacesNumber.Add(NumberOfInteriorWalls.ToString()); } _G.INTERIOR_WALLS.Add(Face.name); Vector3 centerFace = new(); _G.WallAssociateWallLine.Add("w" + NumberOfInteriorWalls.ToString() + "_" + (_G.NWExterior + i).ToString() + "_" + Name); float WallWide = 0; Vector3[] FacePoints = new Vector3[4]; if (Name == "Front") { FacePoints = GetFacePoints(0, 1, 2, 3); WallWide = GetWide(0, 3); _G.WallsWidth.Add(WallWide); _G.WallsPointStart.Add(FirstPoint(0)); _G.WallsPointCenter.Add(GetCenter(0, 3)); centerFace = GetCenterFace(0, 1, 2, 3); _G.WallsAngle.Add(GetWallRotation(0, 3)); _G.InteriorWallsPoints.Add(new Vector3[]{AllPoints[0],AllPoints[3],AllPoints[2],AllPoints[1]}); _G.InteriorBackEndWall.Add(NumberOfInteriorWalls.ToString()+"_"+(NumberOfInteriorWalls+1).ToString() ) ; } else if (Name == "Back") { FacePoints = GetFacePoints(7, 6, 5, 4); WallWide = GetWide(4, 7); _G.WallsWidth.Add(WallWide); _G.WallsPointStart.Add(FirstPoint(7)); _G.WallsPointCenter.Add(GetCenter(7, 4)); centerFace = GetCenterFace(7, 6, 5, 4); _G.WallsAngle.Add(GetWallRotation(7, 4)); _G.InteriorWallsPoints.Add(new Vector3[]{AllPoints[7],AllPoints[4],AllPoints[5],AllPoints[6]}); _G.InteriorBackEndWall.Add(NumberOfInteriorWalls.ToString()+"_"+(NumberOfInteriorWalls-1).ToString() ) ; } else if (Name == "Top") { FacePoints = GetFacePoints(1, 5, 6, 2); // Proceed with the rest of the "Top" face creation as normal WallWide = GetWide(0, 3); _G.WallsWidth.Add(WallWide); _G.WallsPointStart.Add(FirstPoint(1)); _G.WallsPointCenter.Add(GetCenter(1, 3)); centerFace = GetCenterFace(1, 5, 6, 2); _G.WallsAngle.Add(GetWallRotation(1, 2)); _G.InteriorWallsPoints.Add(new Vector3[]{AllPoints[7],AllPoints[4],AllPoints[5],AllPoints[6]}); _G.InteriorBackEndWall.Add(NumberOfInteriorWalls.ToString()+"_"+(NumberOfInteriorWalls-1).ToString() ) ; } else if (Name == "Under") { FacePoints = GetFacePoints(3, 7, 4, 0); WallWide = GetWide(0, 3); _G.WallsWidth.Add(WallWide); _G.WallsPointStart.Add(FirstPoint(4)); _G.WallsPointCenter.Add(GetCenter(0, 3)); centerFace = GetCenterFace(3, 7, 4, 0); _G.WallsAngle.Add(GetWallRotation(3, 0)); _G.InteriorWallsPoints.Add(new Vector3[]{AllPoints[7],AllPoints[4],AllPoints[5],AllPoints[6]}); _G.InteriorBackEndWall.Add(NumberOfInteriorWalls.ToString()+"_"+(NumberOfInteriorWalls-1).ToString() ) ; } else if (Name == "Left") { FacePoints = GetFacePoints(4, 5, 1, 0); WallWide = GetWide(4, 0); _G.WallsWidth.Add(WallWide); _G.WallsPointStart.Add(FirstPoint(4)); _G.WallsPointCenter.Add(GetCenter(4, 0)); centerFace = GetCenterFace(4, 5, 1, 0); _G.WallsAngle.Add(GetWallRotation(4, 0)); _G.InteriorWallsPoints.Add(new Vector3[]{AllPoints[7],AllPoints[4],AllPoints[5],AllPoints[6]}); _G.InteriorBackEndWall.Add(NumberOfInteriorWalls.ToString()+"_"+(NumberOfInteriorWalls-1).ToString() ) ; } else if (Name == "Right") { FacePoints = GetFacePoints(3, 2, 6, 7); WallWide = GetWide(3, 7); _G.WallsWidth.Add(WallWide); _G.WallsPointStart.Add(FirstPoint(3)); _G.WallsPointCenter.Add(GetCenter(3, 7)); centerFace = GetCenterFace(3, 2, 6, 7); _G.WallsAngle.Add(GetWallRotation(3, 7)); _G.InteriorWallsPoints.Add(new Vector3[]{AllPoints[7],AllPoints[4],AllPoints[5],AllPoints[6]}); _G.InteriorBackEndWall.Add(NumberOfInteriorWalls.ToString()+"_"+(NumberOfInteriorWalls-1).ToString() ) ; } Vector3 CENTER = new(0, 0, 0); // Adjust points to align to the mesh's center for (int j = 0; j < FacePoints.Length; j++) { FacePoints[j] += CENTER - centerFace; } GameObject meshHolder = new GameObject("s1"); Vector3[] worldVertices = { FacePoints[0], FacePoints[1], FacePoints[2], FacePoints[3] }; //if (Name == "Front"){_G.InteriorWallsPoints.Add(new Vector3[]{FacePoints[0],FacePoints[3],FacePoints[2],FacePoints[1]});} //Vector3[] localVertices = new Vector3[worldVertices.Length]; //for (int k = 0; k < worldVertices.Length; k++) //{ // // Transform world position to local space of the child object // localVertices[k] = meshHolder.transform.InverseTransformPoint(worldVertices[k]); //} // Create the mesh Mesh m = new() { vertices = worldVertices, 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(); Vector3 normal = m.normals[0]; // Assuming a flat plane, use the first normal Face.transform.rotation = Quaternion.LookRotation(-normal); meshHolder.AddComponent().mesh = m; meshHolder.AddComponent().material = Mat; meshHolder.AddComponent().sharedMesh = m; DOIT.SetSizeTex(meshHolder, 48, 48, 0, 0, 0, 0, 90, 90); meshHolder.transform.SetParent(Face.transform); Face.transform.position = centerFace + _G.RoomOffset; Vector2 offset = new Vector2(_G.RoomOffset.x, _G.RoomOffset.z); int wallIndex = NumberOfInteriorWalls - 1; _G.WallsPointCenter[wallIndex] += offset; _G.WallsPointStart[wallIndex] += offset; float WallHeight = Mathf.Max(GetWide(0, 1), GetWide(3, 2)); AddSelectedMesh(meshHolder, Face.transform.forward, WallWide, WallHeight); _G.WALL[i] = Face; _G.NW += 1; } static bool ArePointsCollinear(Vector3 a, Vector3 b, Vector3 c) { // If the cross-product of vectors (b - a) and (c - a) is zero, points are collinear return Vector3.Cross(b - a, c - a).magnitude < 0.0001f; } // Helper function to check if points are coincident private static bool ArePointsCoincident(Vector3 p1, Vector3 p2, Vector3 p3) { return (p1 == p2 || p2 == p3 || p1 == p3); } private static void AddProjectionTriangles(WallLineInfo wallInfo, Material material, Transform parentTransform) { int triangleIndex = 1; // Define start height and end height float startHeight = -_G.HEIGHT * 0.5f + StartHeight; float endHeight = -_G.HEIGHT * 0.5f + EndHeight; // First triangle (Start Projections) if (!ArePointsCollinear(wallInfo.frontProjectionStart, wallInfo.startPosition, wallInfo.backProjectionStart)) { AddUpwardFacingTriangle( new Vector3(wallInfo.frontProjectionStart.x, startHeight, wallInfo.frontProjectionStart.z), new Vector3(wallInfo.startPosition.x, startHeight, wallInfo.startPosition.z), new Vector3(wallInfo.backProjectionStart.x, startHeight, wallInfo.backProjectionStart.z), material, parentTransform, triangleIndex++ ); } // Second triangle (End Projections) if (!ArePointsCollinear(wallInfo.frontProjectionEnd, wallInfo.endPosition, wallInfo.backProjectionEnd)) { AddUpwardFacingTriangle( new Vector3(wallInfo.frontProjectionEnd.x, endHeight, wallInfo.frontProjectionEnd.z), new Vector3(wallInfo.endPosition.x, endHeight, wallInfo.endPosition.z), new Vector3(wallInfo.backProjectionEnd.x, endHeight, wallInfo.backProjectionEnd.z), material, parentTransform, triangleIndex++ ); } } private static void AddTriangleToMesh(Vector3 p1, Vector3 p2, Vector3 p3, Material material, Transform parent, int triangleIndex) { // Check for degenerate triangles if (ArePointsCoincident(p1, p2, p3)) { Debug.LogWarning("Skipping degenerate triangle: " + p1 + ", " + p2 + ", " + p3); return; } // Check for zero-area triangles float triangleArea = Vector3.Cross(p2 - p1, p3 - p1).magnitude * 0.5f; if (triangleArea <= Mathf.Epsilon) { Debug.LogWarning("Skipping zero-area triangle: " + p1 + ", " + p2 + ", " + p3); return; } // Create a new GameObject to hold the triangle mesh GameObject triangleMeshHolder = new GameObject($"s{triangleIndex + 1}"); triangleMeshHolder.transform.SetParent(parent, true); Vector3[] worldVertices = { p1, p2, p3 }; Vector3[] localVertices = new Vector3[worldVertices.Length]; for (int i = 0; i < worldVertices.Length; i++) { // Transform world position to local space of the child object localVertices[i] = triangleMeshHolder.transform.InverseTransformPoint(worldVertices[i]); } // Create the mesh for the triangle Mesh m = new Mesh { vertices = localVertices, uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 0) }, triangles = new int[] { 0, 1, 2 } }; m.RecalculateNormals(); m.RecalculateTangents(); // Add the necessary components triangleMeshHolder.AddComponent().mesh = m; triangleMeshHolder.AddComponent().material = material; triangleMeshHolder.AddComponent().sharedMesh = m; //// Set the local positions //m.vertices = new Vector3[] { localP1, localP2, localP3 }; m.RecalculateNormals(); m.RecalculateTangents(); } public static void AddSelectedMesh(GameObject wallMeshHolder, Vector3 forward, float WallWide, float WallHeight) { GameObject SelectorMesh = Instantiate(wallMeshHolder); SelectorMesh.SetActive(true); SelectorMesh.transform.rotation = Quaternion.Euler(Vector3.zero); SelectorMesh.transform.position = wallMeshHolder.transform.position - forward * 0.25f; //SelectorMesh.GetComponent().sharedMesh = null;//CreateMeshWall(WallWide,48); SelectorMesh.GetComponent().material = _G.INV;//_G.MESH; SelectorMesh.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; SelectorMesh.GetComponent().receiveShadows = false; //SelectorMesh.GetComponent().material.mainTextureScale = new Vector2(WallWide / 12f, _G.HEIGHT / 12f); DOIT.SetSizeTex(SelectorMesh, WallWide, WallHeight, 0, 0, 0, 0, 90, 90); SelectorMesh.name = "m" + NumberOfInteriorWalls.ToString(); SelectorMesh.tag = "mesh"; _G.NWInterior += 1; NumberOfInteriorWalls += 1; SelectorMesh.transform.SetParent(SceneModeManager.Room); } //----------GET VALUES----------------------------------------------- public static List GetInteriorWalls() { List WallSeries = new(); foreach (RectTransform Wall in wallContainer.transform) { if (Wall.TryGetComponent(out WallLine wallLine)) { if (wallLine._category == "Interior") { WallSeries.Add(Wall); } } } return WallSeries; } public static Vector3[] GetPointsFromLine(int i) { return GetPointsFromLine(InteriorWallContainer[i].GetComponent()); } public static Vector3[] GetPointsFromLine(WallLine wallLine) { PointStart = wallLine._pointStart.GetWorldPosition(); PointEnd = wallLine._pointEnd.GetWorldPosition(); PointStart = GetWorldPositionFlat(PointStart); PointEnd = GetWorldPositionFlat(PointEnd); return new Vector3[2] { PointStart, PointEnd }; } private static Vector3 GetWorldPositionFlat(Vector3 position) { return new(position.x, 0, position.y); } static Vector3 FindRightNormal(Vector3 direction) { Vector3 up = Vector3.up; if (Vector3.Dot(direction, up) > 0.99f) { up = Vector3.forward; } Vector3 right = Vector3.Cross(direction, up); return right.normalized; } public static Vector3[] GetFacePoints(int int1, int int2, int int3, int int4) { return new Vector3[] { AllPoints[int1], AllPoints[int2], AllPoints[int3], AllPoints[int4] }; } public static float GetWide(int int1, int int2) { return Vector3.Distance(AllPoints[int1], AllPoints[int2]); } public static Vector2 GetCenter(int int1, int int2) { Vector2 start = new(AllPoints[int1].x, AllPoints[int1].z); Vector2 end = new(AllPoints[int2].x, AllPoints[int2].z); return Vector2.Lerp(start, end, 0.5f); } public static Vector2 FirstPoint(int int1) { return new(AllPoints[int1].x, AllPoints[int1].z); } public static Vector3 GetCenterFace(int int1, int int2, int int3, int int4) { Vector3 Center1 = Vector3.Lerp(AllPoints[int1], AllPoints[int3], 0.5f); Vector3 Center2 = Vector3.Lerp(AllPoints[int2], AllPoints[int4], 0.5f); return Vector3.Lerp(Center1, Center2, 0.5f); } public static float GetWallRotation(int int1, int int2) { Vector3 DirCurrent = (AllPoints[int1] - AllPoints[int2]).normalized; DirCurrent = FindRightNormal(DirCurrent); // print("DirCurrent==" + DirCurrent); Vector3 AxeZ = new(0, 0, -1); float signedAngle = Vector3.SignedAngle(AxeZ, DirCurrent, Vector3.up); float newAngle = (signedAngle + 360) % 360; //print("ANGLE==" + newAngle); //print("DirCurrent = " + DirCurrent); return newAngle; //Vector3.Angle(DirCurrent, AxeZ); } }