Ejemplo n.º 1
0
        public void GetMixForNextCornerAtPoint_WeightsHeightsFromAllThreeCells_WithBarycentricCoordinatesInCornerTriangle()
        {
            var center    = BuildCell(new Vector3(10f, 0f, 0f));
            var right     = BuildCell(new Vector3(0f, 20f, 0f));
            var nextRight = BuildCell(new Vector3(0f, 0f, 30f));

            MockRenderConfig.Setup(config => config.GetSecondSolidCornerXZ(HexDirection.E)).Returns(new Vector2(1.5f, 0f));
            MockRenderConfig.Setup(config => config.GetSecondSolidCornerXZ(HexDirection.SW)).Returns(new Vector2(0f, 2.5f));
            MockRenderConfig.Setup(config => config.GetSecondSolidCornerXZ(HexDirection.NW)).Returns(new Vector2(3.5f, 3.5f));

            var point = new Vector3(100f, 200f, 300f);

            float expectedCenterWeight = 0.5f, expectedRightWeight = 0.3f, expectedNextRightWeight = 0.2f;

            MockGeometry2D.Setup(geometry => geometry.GetBarycentric2D(
                                     new Vector2(100f, 300f), new Vector2(11.5f, 0f), new Vector2(0f, 2.5f), new Vector2(3.5f, 33.5f),
                                     out expectedCenterWeight, out expectedRightWeight, out expectedNextRightWeight
                                     ));

            DataSelectorCallback <float> dataSelector = delegate(Vector3 pos, IHexCell cell, HexDirection sextant, float weight) {
                if (point != pos)
                {
                    Assert.Fail("Unexpected point passed into selector");
                }

                if (cell == center && sextant == HexDirection.E)
                {
                    return(10f * weight);
                }
                else if (cell == right && sextant == HexDirection.SW)
                {
                    return(100f * weight);
                }
                else if (cell == nextRight && sextant == HexDirection.NW)
                {
                    return(1000f * weight);
                }
                else
                {
                    return(0f);
                }
            };

            var mixingLogic = Container.Resolve <TerrainMixingLogic>();

            Assert.AreEqual(
                10f * 0.5f + 100f * 0.3f + 1000f * 0.2f,
                mixingLogic.GetMixForNextCornerAtPoint(center, right, nextRight, HexDirection.E, point, dataSelector, (a, b) => a + b)
                );
        }
        public T GetMixForNextCornerAtPoint <T>(
            IHexCell center, IHexCell right, IHexCell nextRight, HexDirection direction, Vector3 point,
            DataSelectorCallback <T> dataSelector, Func <T, T, T> aggregator
            )
        {
            Vector2 centerCorner    = center.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction);
            Vector2 rightCorner     = right.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction.Next2());
            Vector2 nextRightCorner = nextRight.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction.Previous2());

            float percentCenter, percentRight, percentNextRight;

            Geometry2D.GetBarycentric2D(
                new Vector2(point.x, point.z), centerCorner, rightCorner, nextRightCorner,
                out percentCenter, out percentRight, out percentNextRight
                );

            T centerContribution    = dataSelector(point, center, direction, percentCenter);
            T rightContribution     = dataSelector(point, right, direction.Next2(), percentRight);
            T nextRightContribution = dataSelector(point, nextRight, direction.Previous2(), percentNextRight);

            return(aggregator(aggregator(centerContribution, rightContribution), nextRightContribution));
        }
        //We take CenterSolidMidpoint as the origin and use that to figure out how
        //close to Center's solid edge our Point is. Once we have that, we use that
        //to linearly interpolate between the height for Center and the height for
        //Right.
        //Local here means points defined in terms of CenterSolidMidpoint
        public T GetMixForEdgeAtPoint <T>(
            IHexCell center, IHexCell right, HexDirection direction, Vector3 point,
            DataSelectorCallback <T> dataSelector, Func <T, T, T> aggregator
            )
        {
            Vector3 world_CenterSolidMidpoint = center.AbsolutePosition + RenderConfig.GetSolidEdgeMidpoint(direction);

            //A line going from CenterSolidMidpoint to the corresponding solid midpoint on Right
            Vector3 local_RightSolidMidpoint = right.AbsolutePosition - world_CenterSolidMidpoint + RenderConfig.GetSolidEdgeMidpoint(direction.Opposite());

            Vector3 local_Point = point - world_CenterSolidMidpoint;

            Vector3 local_PointOntoMidline = Vector3.Project(local_Point, local_RightSolidMidpoint);

            float percentRight  = local_PointOntoMidline.magnitude / local_RightSolidMidpoint.magnitude;
            float percentCenter = 1f - percentRight;

            T centerContribution = dataSelector(point, center, direction, percentCenter);
            T rightContribution  = dataSelector(point, right, direction.Opposite(), percentRight);

            return(aggregator(centerContribution, rightContribution));
        }
Ejemplo n.º 4
0
        public void GetMixForEdgeAtPoint_AndPointAtRightSolidEdge_ReturnsExclusivelyHeightFromRight()
        {
            var center = BuildCell(new Vector3(10f, 0f, 0f));
            var right  = BuildCell(new Vector3(40f, 0f, 0f));

            MockRenderConfig.Setup(config => config.GetSolidEdgeMidpoint(HexDirection.E)).Returns(new Vector3(10f, 0f, 0f));
            MockRenderConfig.Setup(config => config.GetSolidEdgeMidpoint(HexDirection.W)).Returns(new Vector3(-10f, 0f, 0f));

            var point = new Vector3(30f, 15f, 60.5f);

            DataSelectorCallback <float> dataSelector = delegate(Vector3 pos, IHexCell cell, HexDirection sextant, float weight) {
                if (point != pos)
                {
                    Assert.Fail("Unexpected point passed into selector");
                }

                if (cell == center && sextant == HexDirection.E)
                {
                    return(20f * weight);
                }
                else if (cell == right && sextant == HexDirection.W)
                {
                    return(100f * weight);
                }
                else
                {
                    return(0f);
                }
            };

            var mixingLogic = Container.Resolve <TerrainMixingLogic>();

            Assert.AreEqual(
                100f, mixingLogic.GetMixForEdgeAtPoint(center, right, HexDirection.E, point, dataSelector, (a, b) => a + b)
                );
        }