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)); }
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) ); }