Beispiel #1
0
        private void CreateCornerFacades(ISubdivisionGeometry geometry, Footprint footprint, int topIndex, IReadOnlyList <IReadOnlyList <Vector2> > corners, string material)
        {
            Contract.Requires(geometry != null);
            Contract.Requires(corners != null);
            Contract.Requires(_floors != null);

            //Calculate altitude of bottom and top of this facade
            var bot = _floors[footprint.BottomIndex].FloorAltitude;
            var top = _floors[topIndex].FloorAltitude + _floors[topIndex].Bounds.Height;
            var mid = (bot + top) * 0.5f;

            //Fill in corner sections (solid)
            foreach (var corner in corners)
            {
                try
                {
                    geometry.Union(geometry
                                   .CreatePrism(material, corner, top - bot)
                                   .Translate(new Vector3(0, mid, 0))
                                   );
                }
                catch (ArgumentException)
                {
                    //Suppress the argument exception, why?
                    //If we try to create a degenerate prism (negative height, only 2 points) we get an arg exception
                    //Corner sections can be very slim, sometimes *so slim* that the four points merge together
                    //In this case we don't care, the section is so small we'll just skip it!
                }
            }
        }
        /// <summary>
        /// Create the base block for this facade (which embossing stamps will be applied to)
        /// </summary>
        /// <param name="bounds"></param>
        /// <param name="geometry"></param>
        /// <param name="hierarchicalParameters"></param>
        /// <returns></returns>
        protected virtual ICsgShape CreateFacade(Prism bounds, ISubdivisionGeometry geometry, INamedDataCollection hierarchicalParameters)
        {
            Contract.Requires(geometry != null);
            Contract.Requires(hierarchicalParameters != null);

            return(geometry.CreatePrism(hierarchicalParameters.DefaultMaterial(Random), bounds.Footprint, bounds.Height));
        }
        public override void Subdivide(Prism bounds, ISubdivisionGeometry geometry, INamedDataCollection hierarchicalParameters)
        {
            var height   = (float)Math.Min(bounds.Height, Math.Sqrt(Math.Abs(bounds.Footprint.Area())) * (Random() + 0.5));
            var material = hierarchicalParameters.DefaultMaterial(Random);

            var prism = geometry.CreatePrism(material, bounds.Footprint, height).Transform(Matrix4x4.CreateTranslation(0, height / 2f - bounds.Height / 2f + GroundHeight, 0));

            geometry.Union(prism);
        }
        private void CreateCeilings(Prism bounds, ISubdivisionGeometry geometry, IEnumerable <KeyValuePair <VerticalSelection, IRoomPlan> > verticalSubsections, string material)
        {
            Contract.Requires(geometry != null);
            Contract.Requires(verticalSubsections != null);

            var ceiling = geometry.CreatePrism(material, bounds.Footprint, _ceilingThickness).Translate(new Vector3(0, bounds.Height / 2 - _ceilingThickness / 2, 0));

            ceiling = CutVerticalHoles(ceiling, geometry, material, verticalSubsections.Select(a => a.Value));

            geometry.Union(ceiling);
        }
Beispiel #5
0
        public static void CreateFlatPlane(this IGrounded grounded, ISubdivisionGeometry geometry, string material, IReadOnlyList <Vector2> footprint, float height, float yOffset = 0)
        {
            Contract.Requires(grounded != null);
            Contract.Requires(geometry != null);
            Contract.Requires(footprint != null && footprint.Count >= 3);

            var offset = GroundOffset(grounded, height) + yOffset;

            var prism = geometry.CreatePrism(material, footprint, height).Transform(Matrix4x4.CreateTranslation(0, offset, 0));

            geometry.Union(prism);
        }
        private static ICsgShape CutVerticalHoles(ICsgShape shape, ISubdivisionGeometry geometry, string material, IEnumerable <IRoomPlan> verticalSubsections)
        {
            Contract.Requires(shape != null);
            Contract.Requires(geometry != null);
            Contract.Requires(verticalSubsections != null);
            Contract.Ensures(Contract.Result <ICsgShape>() != null);

            var shapeHeight = (shape.Bounds.Max.Y - shape.Bounds.Min.Y) * 2f;
            var shapeMid    = (shape.Bounds.Min.Y + shape.Bounds.Max.Y) * 0.5f;

            foreach (var verticalSubsection in verticalSubsections)
            {
                shape = shape.Subtract(
                    geometry.CreatePrism(material, verticalSubsection.OuterFootprint, shapeHeight).Translate(new Vector3(0, shapeMid, 0))
                    );
                Contract.Assume(shape != null);
            }

            return(shape);
        }
        private void CreateFootpath2Inner(ISubdivisionGeometry geometry, string material, float height, bool r1LeftInner, IHalfEdgeBuilder r1, IHalfEdgeBuilder r2)
        {
            Contract.Requires(r1 != null);
            Contract.Requires(r2 != null);
            Contract.Requires(geometry != null);

            var innerPoint = r1LeftInner ? r1.LeftEnd : r1.RightEnd;

            var points = new List <Vector2> {
                innerPoint
            };

            //Points where the footpath terminates at the end of the road
            var r1Across = r1LeftInner ? r1.Direction.Perpendicular() : -r1.Direction.Perpendicular();
            var r1Point  = innerPoint + r1Across * r1.SidewalkWidth;
            var r2Across = r1LeftInner ? -r2.Direction.Perpendicular() : r2.Direction.Perpendicular();
            var r2Point  = innerPoint + r2Across * r2.SidewalkWidth;

            //Point to turn the connect around
            var centerPoint = new Ray2(r1Point, r1.Direction.Perpendicular()).Intersects(new Ray2(r2Point, r2.Direction.Perpendicular()));

            //Sanity check!
            if (!centerPoint.HasValue)
            {
                return;
            }

            //Evaluate segment
            var curve = new CircleSegment {
                CenterPoint = centerPoint.Value.Position,
                StartPoint  = r1Point,
                EndPoint    = r2Point,
            };

            points.AddRange(curve.Evaluate(0.05f));

            //Helpers function for creating prisms
            Action <IEnumerable <Vector2>, bool> unionPrism = (footprint, check) => geometry.Union(geometry
                                                                                                   .CreatePrism(material, footprint.ConvexHull().ToArray(), height)
                                                                                                   .Translate(new Vector3(0, this.GroundOffset(height), 0))
                                                                                                   .Transform(InverseWorldTransformation),
                                                                                                   check
                                                                                                   );

            //Materialize result
            unionPrism(points, false);

            //Extend straight sections to edge of node
            //We only need to do this if we were turning precisely about the contact points of these two roads
            if (centerPoint.Value.Position.TolerantEquals(innerPoint, 0.1f))
            {
                unionPrism(new[] {
                    r1Point,
                    innerPoint,
                    innerPoint - r1.Direction * r1.SidewalkWidth,
                    r1Point - r1.Direction * r1.SidewalkWidth
                }, true);

                unionPrism(new[] {
                    r2Point,
                    innerPoint,
                    innerPoint - r2.Direction * r2.SidewalkWidth,
                    r2Point - r2.Direction * r2.SidewalkWidth
                }, true);
            }
        }
        private void CreateFootpath2Outer(ISubdivisionGeometry geometry, string material, float height, IHalfEdgeBuilder r1, IHalfEdgeBuilder r2)
        {
            Contract.Requires(geometry != null);
            Contract.Requires(r1 != null);
            Contract.Requires(r2 != null);

            //r1.LeftEnd and r2.RightEnd are the outsides of the roads
            //Trace a path along the boundary between these points, use the path which does *not* include the other points
            Vector2[] cwp, ccwp;
            bool      cw, ccw;

            Bounds.Footprint.TraceConnectingPath(
                Vector3.Transform(r1.LeftEnd.X_Y(0), InverseWorldTransformation).XZ(),
                Vector3.Transform(r2.RightEnd.X_Y(0), InverseWorldTransformation).XZ(),
                0.01f, out cwp, out cw, out ccwp, out ccw,
                Vector3.Transform(r1.RightEnd.X_Y(0), InverseWorldTransformation).XZ(),
                Vector3.Transform(r2.LeftEnd.X_Y(0), InverseWorldTransformation).XZ());

            //Sanity check (only 1 direction should be acceptable)
            if (!(cw ^ ccw))
            {
                return;
            }

            //Follow along edge, then back along edge (pushed inwards by footpath width)
            //todo: Offset width by angle at end of road
            var outerPoints = cw ? cwp : ccwp;
            var innerPoints = new Vector2[cw ? cwp.Length : ccwp.Length];

            Contract.Assert(innerPoints.Length == outerPoints.Length);

            var widthStart = cw ? r1.SidewalkWidth : r2.SidewalkWidth;
            var widthEnd   = cw ? r2.SidewalkWidth : r1.SidewalkWidth;

            for (var i = 0; i < outerPoints.Length && outerPoints.Length > 1; i++)
            {
                Vector2 dir;
                float   w;
                if (i == 0)
                {
                    dir = Vector2.Normalize(cw ? r1.RightEnd - r1.LeftEnd : r2.LeftEnd - r2.RightEnd);
                    w   = CalculateFootpathAngleScale(cw ? r1.Direction : r2.Direction, dir, widthStart);
                }
                else if (i == outerPoints.Length - 1)
                {
                    dir = Vector2.Normalize(cw ? r2.LeftEnd - r2.RightEnd : r1.RightEnd - r1.LeftEnd);
                    w   = CalculateFootpathAngleScale(cw ? r2.Direction : r1.Direction, -dir, widthEnd);
                }
                else
                {
                    //perpendicular to path direction
                    dir = Vector2.Normalize(outerPoints[i] - outerPoints[i - 1]).Perpendicular() * (cw ? 1 : -1);
                    //Interpolate widths along path
                    var t = i / (float)(outerPoints.Length - 1);
                    w = MathHelper.Lerp(widthStart, widthEnd, t);
                }

                innerPoints[i] = outerPoints[i] + dir * w;
            }

            //Create footprint from 2 halves
            var footprint = cw ? outerPoints.Concat(innerPoints.Reverse()) : outerPoints.Reverse().Concat(innerPoints);

            geometry.Union(geometry
                           .CreatePrism(material, footprint.ToArray(), height)
                           .Translate(new Vector3(0, this.GroundOffset(height), 0))
                           );
        }