private static Hole2DProjection[] OpeningsToHole2DProjections( WallData wall, UnfoldedCurve mainCurve, UnfoldedCurve sideCurve, Func <OpeningData, bool> predicate, Func <WallPointNormals, Vector2> normalGetter) { return(wall .Openings ?.Where(predicate) .Select( x => new Hole2DProjection( x .Points .Select( y => ProjectOpeningPoint( y, wall, mainCurve, sideCurve, normalGetter)) .ToArray(), x)) .ToArray()); }
public static Mesh Triangulate( List <Vector2> sourceVertices, List <List <Vector2> > holes, UnfoldedCurve unfoldedCurve, string name = null) { List <int> trianles; List <Vector3> vertices; MeshGenerator.Triangulate( sourceVertices, holes, false, out vertices, out trianles); for (int count = vertices.Count, i = 0; i < count; i++) { var vertex = vertices[i]; var point = unfoldedCurve.Unfold(new SystemVector2(vertex.x, vertex.y)); vertices[i] = new Vector3(point.X, vertex.z, point.Y); } return(MeshGenerator.CreateMesh(vertices.ToArray(), trianles.ToArray(), false, name)); }
private static OpeningPoint3D GetHole3DPoint(UnfoldedCurve curve, OpeningPoint2D point2D) { var unwrapped = curve.Unfold(new Vector2(point2D.Position.x, 0f)); var result = new Vector3(unwrapped.X, point2D.Position.y, unwrapped.Y); return(new OpeningPoint3D( result, new Vector3(point2D.Normal.x, 0f, point2D.Normal.y))); }
private static OpeningPoint2D ProjectOpeningPoint( Vector2 openingPoint, WallData wall, UnfoldedCurve unfoldedWall, UnfoldedCurve unfoldedWallSide, Func <WallPointNormals, Vector2> normalGetter) { /* Debug.Log ( * $"unwrappedWall {string.Join (",", Array.ConvertAll (unwrappedWall.UnwrappedPoints, x => x.ToString ()))}"); * * Debug.Log ( * $"unwrappedWallSide {string.Join (",", Array.ConvertAll (unwrappedWallSide.UnwrappedPoints, x => x.ToString ()))}");*/ var wallPoints = wall.Points; for (int i = 1; i < wallPoints.Length; i++) { if (openingPoint.x > unfoldedWall.UnfoldedPoints[i].X) { continue; } var normals = wall.Normals.Value; var normal = normalGetter(normals[i]); var prevNormal = normalGetter(normals[i - 1]); var averageNormal = normal + prevNormal; var unwrapped = unfoldedWall .Unfold(new Vector2(openingPoint.x, 0f)) .ToUnityVector2(); // var unwrappedDebug = new Vector3 (unwrapped.x, openingPoint.y, unwrapped.y); var unwrappedOnSide = unwrapped.TransposePoint(averageNormal, wall.Width / 2f); var wrappedOnSide = unfoldedWallSide.Fold(unwrappedOnSide); var result = new Vector2(wrappedOnSide.x, openingPoint.y); // var unwrappedOnSideDebug = new Vector3 (unwrappedOnSide.x, openingPoint.y, unwrappedOnSide.y); // Debug.DrawLine(unwrappedDebug, unwrappedOnSideDebug, color, float.MaxValue); // Debug.DrawLine(unwrappedDebug, unwrappedOnSideDebug + new Vector3(normal.x, 0f, normal.y), Color.yellow, float.MaxValue); /* * Debug.Log ( * $"openingPoint {openingPoint} unwrapped {unwrapped} unwrappedOnSide {unwrappedOnSide} wrappedOnSide {wrappedOnSide} result {result}"); */ return(new OpeningPoint2D(result, -averageNormal)); } throw new NotImplementedException(); }
private static Hole3DProjection[] Hole2DProjectionsTo3D( Hole2DProjection[] projections2D, UnfoldedCurve curve) { return(projections2D ?.Select( x => new Hole3DProjection( x .Points .Select(y => GetHole3DPoint(curve, y)) .ToArray(), x.Opening )) .ToArray()); }
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); }
public static Mesh GetMesh( UnfoldedCurve unfoldedCurve, SystemVector2[][] sourceHoles, float height, string name = null) { var unwrappedPoints = unfoldedCurve.UnfoldedPoints.ToList(); var sourceVerticesBottomLine = unwrappedPoints.ConvertAll(x => x.ToUnityVector2()); var width = unwrappedPoints.Last().X; var holes = sourceHoles ?.ToList() .ConvertAll( x => x .ToList() .ConvertAll(y => y.ToUnityVector2())); if (holes == null || holes.Count == 0) { var sourceVerticesTopLine = sourceVerticesBottomLine .Select(x => x + new Vector2(0f, height)) .Reverse() .ToList(); var sourceVertices = new List <Vector2> (sourceVerticesBottomLine); sourceVertices.AddRange(sourceVerticesTopLine); return(Triangulate(sourceVertices, null, unfoldedCurve, name)); } if (unwrappedPoints.Count == 2) { var sourceVertices = new List <Vector2> { Vector2.zero, new Vector2(0f, height), new Vector2(width, height), new Vector2(width, 0f) }; return(Triangulate(sourceVertices, holes, unfoldedCurve, name)); } var sortedHoles = holes .Select(GetHoleData) .OrderBy(x => x.Min) .ToArray(); var xs = new List <Point> ( sourceVerticesBottomLine.ConvertAll(x => new Point(PointType.Regular, x.x))); foreach (var hole in sortedHoles) { xs.Add(new Point(PointType.PointStart, hole.Min)); xs.Add(new Point(PointType.PointEnd, hole.Max)); } xs.Sort((x, y) => Comparer <float> .Default.Compare(x.X, y.X)); var chunks = new List <List <float> > { new List <float> () }; var startedCount = 0; foreach (var x in xs) { chunks .Last() .Add(x.X); switch (x.PointType) { case PointType.Regular: break; case PointType.PointStart: if (++startedCount == 1) { chunks.Add(new List <float> { x.X }); } break; case PointType.PointEnd: if (--startedCount == 0) { chunks.Add(new List <float> { x.X }); } break; default: throw new ArgumentOutOfRangeException(); } } var meshes = new List <Mesh> (); foreach (var chunk in chunks) { if (chunk.Count == 1) { continue; } var chunkBottomLine = new List <Vector2> (chunk.ConvertAll(x => new Vector2(x, 0f))); var chunkHoles = new List <List <Vector2> > (); foreach (var x in chunk) { var holesData = Array.FindAll(sortedHoles, y => Mathf.Approximately(x, y.Min)); if (holesData.Length > 0 && !Mathf.Approximately(x, chunk.Last())) { chunkHoles.AddRange(holesData.Select(y => y.Hole)); } } var chunkTopLine = chunkBottomLine .Select(x => new Vector2(x.x, height)) .Reverse() .ToArray(); var chunkVertices = new List <Vector2> (chunkBottomLine); chunkVertices.AddRange(chunkTopLine); var chunkMesh = Triangulate(chunkVertices, chunkHoles, unfoldedCurve); meshes.Add(chunkMesh); // MeshGenerator.CreateGameObject ("qqq", chunkMesh); } // throw new NotImplementedException (); var mesh = new Mesh(); mesh.name = name ?? ""; mesh.Clear(); mesh.CombineMeshes( meshes.ConvertAll(x => new CombineInstance { mesh = x }).ToArray(), true, false); return(mesh); }