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());
 }
Example #2
0
        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);
        }
Example #8
0
        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);
        }