public static Mesh[] GetWallMeshes( WallData prevInnerWall, WallData prevOuterWall, WallData wall, WallData nextInnerWall, WallData nextOuterWall) { /* Debug.Log ( * $"pi: {prevInnerWall}; po: {prevOuterWall}; w: {wall}; ni: {nextInnerWall}; no: {nextOuterWall}");*/ var prevInnerLine = prevInnerWall ?.Lines .Value .Last() .Inner; var prevOuterLine = prevOuterWall ?.Lines .Value .Last() .Outer; var nextInnerLine = nextInnerWall ?.Lines .Value .First() .Inner; var nextOuterLine = nextOuterWall ?.Lines .Value .First() .Outer; var startLines = wall .Lines .Value .First(); var endLines = wall .Lines .Value .Last(); Vector2 innerStart, innerEnd, outerStart, outerEnd; var innerPoints = wall.InnerPoints.Value; var outerPoints = wall.OuterPoints.Value; if (!(prevInnerLine.HasValue && startLines.Inner.Cross(prevInnerLine.Value, out innerStart))) { innerStart = innerPoints.First(); } if (!(prevOuterLine.HasValue && startLines.Outer.Cross(prevOuterLine.Value, out outerStart))) { outerStart = outerPoints.First(); } if (!(nextInnerLine.HasValue && endLines.Inner.Cross(nextInnerLine.Value, out innerEnd))) { switch (wall.WidthChangeType) { case WidthChangeType.Type1: innerEnd = innerPoints.Last(); break; case WidthChangeType.Type2: Assert.IsNotNull(nextInnerWall); innerEnd = nextInnerWall .InnerPoints .Value .First(); break; default: throw new ArgumentOutOfRangeException(); } } if (!(nextOuterLine.HasValue && endLines.Outer.Cross(nextOuterLine.Value, out outerEnd))) { switch (wall.WidthChangeType) { case WidthChangeType.Type1: outerEnd = outerPoints.Last(); break; case WidthChangeType.Type2: Assert.IsNotNull(nextOuterWall); outerEnd = nextOuterWall .OuterPoints .Value .First(); break; default: throw new ArgumentOutOfRangeException(); } } /* if (nextLines != null && nextLines.Inner.Cross (endLines.Inner, out innerEnd)) { * nextLines.Outer.Cross (endLines.Outer, out outerEnd); * } else { * switch (wall.WidthChangeType) { * case WidthChangeType.Type1: * innerEnd = innerPoints.Last (); * outerEnd = outerPoints.Last (); * break; * case WidthChangeType.Type2: * innerEnd = nextWall * .InnerPoints * .Value * .First (); * * outerEnd = nextWall * .OuterPoints * .Value * .First (); * * break; * default: * throw new ArgumentOutOfRangeException (); * } * }*/ var finalInnerPointsList = new List <Vector2> (); finalInnerPointsList.Add(innerStart); finalInnerPointsList.AddRange(innerPoints.Where((_, i) => i > 0 && i < innerPoints.Length - 1)); finalInnerPointsList.Add(innerEnd); var finalOuterPointsList = new List <Vector2> (); finalOuterPointsList.Add(outerStart); finalOuterPointsList.AddRange(outerPoints.Where((_, i) => i > 0 && i < outerPoints.Length - 1)); finalOuterPointsList.Add(outerEnd); var finalInnerPoints = finalInnerPointsList.ToArray(); var finalOuterPoints = finalOuterPointsList.ToArray(); var unwrappedWall = new UnfoldedCurve(wall.Points); var outerUnwrappedWall = new UnfoldedCurve(finalOuterPoints); var innerUnwrappedWall = new UnfoldedCurve(finalInnerPoints); var outer2DHoles = OpeningsToHole2DProjections( wall, unwrappedWall, outerUnwrappedWall, x => x.Type.HasFlag(OpeningType.Outer), x => x.Outer); var inner2DHoles = OpeningsToHole2DProjections( wall, unwrappedWall, innerUnwrappedWall, x => x.Type.HasFlag(OpeningType.Inner), x => x.Inner); var outer3DHoles = Hole2DProjectionsTo3D(outer2DHoles, outerUnwrappedWall); var inner3DHoles = Hole2DProjectionsTo3D(inner2DHoles, innerUnwrappedWall); bool flipInnerJambs = wall.StartAngle.Value < Mathf.PI / 2f; List <Mesh> jambMeshes = null; if (outer3DHoles != null) { jambMeshes = new List <Mesh> (); jambMeshes.AddRange( ProcessJambs( outer3DHoles, inner3DHoles, x => x.Type.HasFlag(OpeningType.Through), "Outer Jamb", !flipInnerJambs)); } if (inner3DHoles != null) { jambMeshes = jambMeshes ?? new List <Mesh> (); jambMeshes.AddRange( ProcessJambs( inner3DHoles .Where(x => !x.Opening.Type.HasFlag(OpeningType.Through)) .ToArray(), null, x => false, "Inner Jamb", flipInnerJambs)); } Mesh innerMesh = PlaneMeshMaker.GetMesh( finalInnerPoints.ToArray(), inner2DHoles?.Select(x => x.Points.Select(y => y.Position).ToArray()).ToArray(), wall.Height, "inner"); Mesh outerMesh = PlaneMeshMaker.GetMesh( finalOuterPoints.ToArray(), outer2DHoles?.Select(x => x.Points.Select(y => y.Position).ToArray()).ToArray(), wall.Height, "outer"); outerMesh.FlipFaces(); float height = wall.Height; Mesh sideAMesh = PlaneMeshMaker.GetMesh( "leftside", finalInnerPoints.First().ToVector3(0, true), wall.Start.ToVector3(0, true), finalOuterPoints.First().ToVector3(0, true), finalOuterPoints.First().ToVector3(height, true), wall.Start.ToVector3(height, true), finalInnerPoints.First().ToVector3(height, true)); Mesh sideBMesh = PlaneMeshMaker.GetMesh( "rightside", finalOuterPoints.Last().ToVector3(0, true), wall.End.ToVector3(0, true), finalInnerPoints.Last().ToVector3(0, true), finalInnerPoints.Last().ToVector3(height, true), wall.End.ToVector3(height, true), finalOuterPoints.Last().ToVector3(height, true)); var topVertices = new List <Vector2> (finalInnerPoints); topVertices.Reverse(); topVertices.Add(wall.Start); topVertices.AddRange(finalOuterPoints); topVertices.Add(wall.End); List <Vector3> vertices; List <int> triangles; MeshGenerator.Triangulate( topVertices, dummyHolesList, false, out vertices, out triangles); var topMesh = MeshGenerator.CreateMesh( vertices.ConvertAll(x => new Vector3(x.x, height, x.z)).ToArray(), triangles.ToArray(), false, "top"); var result = new List <Mesh> { innerMesh, outerMesh, sideAMesh, sideBMesh, topMesh }; if (jambMeshes != null) { result.AddRange(jambMeshes); } return(result.ToArray()); }
private static IEnumerable <Mesh> ProcessJambs( Hole3DProjection[] hole3DProjections, Hole3DProjection[] oppositeHole3DProjections, Predicate <OpeningData> isThroughPredicate, string name, bool flipFaces = false) { var jambMeshes = new List <Mesh> (); for (int i = 0; i < hole3DProjections.Length; i++) { var main3DHole = hole3DProjections[i]; var opening = main3DHole.Opening; var jambVertices = new List <Vector3> (); if (isThroughPredicate(opening)) { var opposite3DHole = oppositeHole3DProjections .First(x => x.Opening == main3DHole.Opening); jambVertices .AddRange( opposite3DHole .Points .Select(x => x.Position) .ToArray()); } else { var jambBackPoints = main3DHole .Points .Select(x => x.Position.TransposePoint(x.Normal, opening.Depth)) .ToArray(); jambVertices.AddRange(jambBackPoints); var jambCurvePoints = jambBackPoints .Select(x => new Vector2(x.x, x.z)) .OrderBy(x => x.x) .ToArray(); var jambCurve = new UnfoldedCurve(jambCurvePoints); var jamb2DVertices = jambBackPoints .Select(x => new Vector2(jambCurve.Fold(new Vector2(x.x, x.z)).x, x.y)) .ToList(); var mesh = PlaneMeshMaker.Triangulate(jamb2DVertices, null, jambCurve, $"{name} back {i}"); if (flipFaces) { mesh.FlipFaces(); } jambMeshes.Add(mesh); } jambVertices.AddRange( main3DHole .Points .Select(x => x.Position) .ToArray()); var jambTriangles = new List <int> (); var verticesHalfLength = main3DHole.Points.Length; for (int j = 0; j < verticesHalfLength; j++) { var inner = j; var outer = verticesHalfLength + inner; var nextInner = (j + 1) % verticesHalfLength; var nextOuter = verticesHalfLength + nextInner; jambTriangles.AddRange( new[] { inner, nextInner, outer, nextInner, nextOuter, outer }); } var jambMesh = MeshGenerator.CreateMesh( jambVertices.ToArray(), jambTriangles.ToArray(), flipFaces, $"{name} {i}"); jambMeshes.Add(jambMesh); } return(jambMeshes); }