public void GetTerrainHeightForPoint_AndLeftWeightGreaterThanZero_ReturnsLeftWeightTimesLeftHeight() { var point = new Vector2(1f, 2f); var left = BuildCell(); var orientationData = new PointOrientationData() { IsOnGrid = true, Left = left, LeftWeight = 12f, ElevationDuck = 5.5f }; var flatlandsNoise = new AsyncTextureUnsafe <Color32>(); var hillsNoise = new AsyncTextureUnsafe <Color32>(); MockCellHeightmapLogic.Setup( logic => logic.GetHeightForPointForCell(point, left, 5.5f, flatlandsNoise, hillsNoise) ).Returns(8f); var heightLogic = Container.Resolve <TerrainHeightLogic>(); Assert.AreEqual(96, heightLogic.GetHeightForPoint(point, orientationData, flatlandsNoise, hillsNoise)); }
public float GetHeightForPointForCell( Vector2 xzPoint, IHexCell cell, float elevationDuck, AsyncTextureUnsafe <Color32> flatlandNoise, AsyncTextureUnsafe <Color32> hillsNoise ) { if (cell.Terrain.IsWater()) { return(RenderConfig.SeaFloorElevation); } if (cell.Shape == CellShape.Flatlands) { return(FlatlandsHeightmapLogic.GetHeightForPoint(xzPoint, flatlandNoise)); } else if (cell.Shape == CellShape.Hills) { return(HillsHeightmapLogic.GetHeightForPoint(xzPoint, elevationDuck, flatlandNoise, hillsNoise)); } else if (cell.Shape == CellShape.Mountains) { return(MountainHeightmapLogic.GetHeightForPoint(xzPoint, cell, elevationDuck, flatlandNoise, hillsNoise)); } else { throw new NotImplementedException(); } }
public float GetHeightForPoint( Vector2 xzPoint, AsyncTextureUnsafe <Color32> noiseTexture ) { float noise = NoiseGenerator.SampleNoise( xzPoint, noiseTexture, RenderConfig.FlatlandsElevationNoiseStrength, NoiseType.ZeroToOne ).x; return(RenderConfig.FlatlandsBaseElevation + noise); }
public void GetHeightForPositionForCell_AndCellIsFlatlands_ReturnsHeightFromFlatlandsHeightmapLogic() { var position = new Vector3(1f, 2f, 3f); var cell = BuildCell(CellTerrain.Grassland, CellShape.Flatlands); var flatlandsNoise = new AsyncTextureUnsafe <Color32>(); MockFlatlandsHeightmapLogic.Setup(logic => logic.GetHeightForPoint(position, flatlandsNoise)).Returns(15.25f); var heightmapLogic = Container.Resolve <CellHeightmapLogic>(); Assert.AreEqual(15.25f, heightmapLogic.GetHeightForPointForCell(position, cell, 7.27f, flatlandsNoise, null)); }
public void GetTerrainHeightForPoint_AndPointNotOnGrid_ReturnsZero() { var point = new Vector2(1f, 2f); var orientationData = new PointOrientationData() { IsOnGrid = false }; var flatlandsNoise = new AsyncTextureUnsafe <Color32>(); var hillsNoise = new AsyncTextureUnsafe <Color32>(); var heightLogic = Container.Resolve <TerrainHeightLogic>(); Assert.AreEqual(0f, heightLogic.GetHeightForPoint(point, orientationData, flatlandsNoise, hillsNoise)); }
public float GetHeightForPoint( Vector2 xzPoint, PointOrientationData orientationData, AsyncTextureUnsafe <Color32> flatlandsNoise, AsyncTextureUnsafe <Color32> hillsNoise ) { float retval = 0f; if (!orientationData.IsOnGrid) { return(retval); } if (orientationData.Center != null && orientationData.CenterWeight > 0f) { retval += orientationData.CenterWeight * CellHeightmapLogic.GetHeightForPointForCell( xzPoint, orientationData.Center, orientationData.ElevationDuck, flatlandsNoise, hillsNoise ); } if (orientationData.Left != null && orientationData.LeftWeight > 0f) { retval += orientationData.LeftWeight * CellHeightmapLogic.GetHeightForPointForCell( xzPoint, orientationData.Left, orientationData.ElevationDuck, flatlandsNoise, hillsNoise ); } if (orientationData.Right != null && orientationData.RightWeight > 0f) { retval += orientationData.RightWeight * CellHeightmapLogic.GetHeightForPointForCell( xzPoint, orientationData.Right, orientationData.ElevationDuck, flatlandsNoise, hillsNoise ); } if (orientationData.NextRight != null && orientationData.NextRightWeight > 0f) { retval += orientationData.NextRightWeight * CellHeightmapLogic.GetHeightForPointForCell( xzPoint, orientationData.NextRight, orientationData.ElevationDuck, flatlandsNoise, hillsNoise ); } if (orientationData.RiverWeight > 0f) { retval += orientationData.RiverWeight * RenderConfig.RiverTroughElevation; } return(retval); }
public float GetHeightForPoint( Vector2 xzPoint, float elevationDuck, AsyncTextureUnsafe <Color32> flatlandsNoiseTexture, AsyncTextureUnsafe <Color32> hillsNoiseTexture ) { float hillNoise = NoiseGenerator.SampleNoise( xzPoint, hillsNoiseTexture, RenderConfig.HillsElevationNoiseStrength, NoiseType.ZeroToOne ).x; float hillsHeight = RenderConfig.HillsBaseElevation + hillNoise; float flatlandsHeight = FlatlandsHeightmapLogic.GetHeightForPoint(xzPoint, flatlandsNoiseTexture); var retval = Mathf.Lerp(hillsHeight, flatlandsHeight, elevationDuck); return(retval); }
public void GetTerrainHeightForPoint_AndRiverWeightGreaterThanZero_ReturnsRiverWeightTimesTroughElevation() { var point = new Vector2(1f, 2f); var orientationData = new PointOrientationData() { IsOnGrid = true, RiverWeight = 12f }; var flatlandsNoise = new AsyncTextureUnsafe <Color32>(); var hillsNoise = new AsyncTextureUnsafe <Color32>(); MockMapRenderConfig.Setup(config => config.RiverTroughElevation).Returns(8f); var heightLogic = Container.Resolve <TerrainHeightLogic>(); Assert.AreEqual(96, heightLogic.GetHeightForPoint(point, orientationData, flatlandsNoise, hillsNoise)); }
public void GetTerrainHeightForPoint_AndMultipleWeightsGreaterThanZero_SumsAllWeightContributions() { var point = new Vector2(1f, 2f); var center = BuildCell(); var left = BuildCell(); var right = BuildCell(); var nextRight = BuildCell(); var orientationData = new PointOrientationData() { IsOnGrid = true, Center = center, CenterWeight = 1f, Left = left, LeftWeight = 5f, Right = right, RightWeight = 1.5f, NextRight = nextRight, NextRightWeight = 0.6f, RiverWeight = 2f, ElevationDuck = 5.5f }; var flatlandsNoise = new AsyncTextureUnsafe <Color32>(); var hillsNoise = new AsyncTextureUnsafe <Color32>(); MockCellHeightmapLogic.Setup(logic => logic.GetHeightForPointForCell(point, center, 5.5f, flatlandsNoise, hillsNoise)).Returns(10f); MockCellHeightmapLogic.Setup(logic => logic.GetHeightForPointForCell(point, left, 5.5f, flatlandsNoise, hillsNoise)).Returns(11f); MockCellHeightmapLogic.Setup(logic => logic.GetHeightForPointForCell(point, right, 5.5f, flatlandsNoise, hillsNoise)).Returns(12f); MockCellHeightmapLogic.Setup(logic => logic.GetHeightForPointForCell(point, nextRight, 5.5f, flatlandsNoise, hillsNoise)).Returns(13f); MockMapRenderConfig.Setup(config => config.RiverTroughElevation).Returns(6.2f); var heightLogic = Container.Resolve <TerrainHeightLogic>(); float expectedValue = 10f + 55f + 1.5f * 12f + 0.6f * 13f + 2f * 6.2f; float pointHeight = heightLogic.GetHeightForPoint(point, orientationData, flatlandsNoise, hillsNoise); Assert.IsTrue( Mathf.Approximately(expectedValue, pointHeight), string.Format( "Resulting height not approximately equal to expected results (Expected {0}, got {1})", expectedValue, pointHeight ) ); }
public void GetHeightForPoint_SamplesFlatlandNoise_AndFlatlandBaseElevation() { var xzPoint = new Vector2(1f, 2f); var noiseTexture = new AsyncTextureUnsafe <Color32>(); MockRenderConfig.Setup(config => config.FlatlandsElevationNoiseStrength).Returns(-1f); MockRenderConfig.Setup(config => config.FlatlandsBaseElevation).Returns(100f); MockNoiseGenerator.Setup(generator => generator.SampleNoise(xzPoint, noiseTexture, -1f, NoiseType.ZeroToOne)) .Returns(new Vector4(10f, 20f, 30f, 40f)); MockRenderConfig.Setup(config => config.FlatlandsBaseElevation).Returns(100f); var cell = new Mock <IHexCell>().Object; var heightmapLogic = Container.Resolve <FlatlandsHeightmapLogic>(); Assert.AreEqual(110f, heightmapLogic.GetHeightForPoint(xzPoint, noiseTexture)); }
public Vector4 SampleNoise(Vector2 xzPosition, AsyncTextureUnsafe <Color32> source, float strength, NoiseType type) { Vector4 normalizedNoise = RawTextureSampler.SampleBilinear( xzPosition.x * RenderConfig.NoiseScale, xzPosition.y * RenderConfig.NoiseScale, source ); if (type == NoiseType.NegativeOneToOne) { normalizedNoise.Set( normalizedNoise.x * 2f - 1f, normalizedNoise.y * 2f - 1f, normalizedNoise.z * 2f - 1f, normalizedNoise.w * 2f - 1f ); } return(normalizedNoise * strength); }
public void GetTerrainHeightForPoint_AndNextRightNull_IgnoresNextRightContribution() { var point = new Vector2(1f, 2f); var orientationData = new PointOrientationData() { IsOnGrid = true, NextRight = null, NextRightWeight = 12f, ElevationDuck = 5.5f }; var flatlandsNoise = new AsyncTextureUnsafe <Color32>(); var hillsNoise = new AsyncTextureUnsafe <Color32>(); MockCellHeightmapLogic.Setup( logic => logic.GetHeightForPointForCell(point, It.IsAny <IHexCell>(), 5.5f, flatlandsNoise, hillsNoise) ).Returns(8f); var heightLogic = Container.Resolve <TerrainHeightLogic>(); Assert.AreEqual(0, heightLogic.GetHeightForPoint(point, orientationData, flatlandsNoise, hillsNoise)); }
private IEnumerator RefreshHeightmap(ChunkOrientationData chunkOrientation) { var terrainData = Terrain.terrainData; var unsafeOrientationTexture = new AsyncTextureUnsafe <Color32>(chunkOrientation.OrientationTexture); var unsafeWeightsTexture = new AsyncTextureUnsafe <Color32>(chunkOrientation.WeightsTexture); var unsafeDuckTexture = new AsyncTextureUnsafe <Color32>(chunkOrientation.DuckTexture); var unsafeFlatlandsNoise = new AsyncTextureUnsafe <Color32>(RenderConfig.FlatlandsElevationNoiseSource); var unsafeHillsNoise = new AsyncTextureUnsafe <Color32>(RenderConfig.HillsElevationNoiseSource); Vector3 terrainSize = terrainData.size; int mapWidth = terrainData.heightmapWidth; int mapHeight = terrainData.heightmapHeight; float[,] heights = terrainData.GetHeights(0, 0, mapWidth, mapHeight); float maxTextureNormalX = Width / RenderConfig.ChunkWidth; float maxTextureNormalZ = Height / RenderConfig.ChunkHeight; float indexToNormalX = 1f / (mapHeight - 1f); float indexToNormalZ = 1f / (mapWidth - 1f); Vector3 chunkPosition = transform.position; var columnTasks = new Task[mapHeight]; for (int height = 0; height < mapHeight; height++) { int cachedHeight = height; var indexBytes = new byte[2]; PointOrientationData pointOrientation = new PointOrientationData(); var columnTask = new Task(() => { for (int width = 0; width < mapWidth; width++) { float terrainNormalX, terrainNormalZ, textureNormalX, textureNormalZ, worldX, worldZ; Color32 orientationColor; Color weightsColor, duckColor; //For some reason, terrainData seems to index its points //as (y, x) rather than the more traditional (x, y), so //we need to sample our texture accordingly terrainNormalX = cachedHeight * indexToNormalX; terrainNormalZ = width * indexToNormalZ; worldX = chunkPosition.x + terrainNormalX * terrainSize.x; worldZ = chunkPosition.z + terrainNormalZ * terrainSize.z; textureNormalX = maxTextureNormalX * terrainNormalX; textureNormalZ = maxTextureNormalZ * terrainNormalZ; orientationColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeOrientationTexture)); weightsColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeWeightsTexture)); duckColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeDuckTexture)); PointOrientationLogic.GetOrientationDataFromColors( pointOrientation, indexBytes, orientationColor, weightsColor, duckColor ); heights[width, cachedHeight] = HeightLogic.GetHeightForPoint( new Vector2(worldX, worldZ), pointOrientation, unsafeFlatlandsNoise, unsafeHillsNoise ); } }); columnTask.Start(); columnTasks[cachedHeight] = columnTask; } while (columnTasks.Any(task => !task.IsCompleted)) { yield return(SkipFrame); } terrainData.SetHeights(0, 0, heights); }
private IEnumerator RefreshAlphamap(ChunkOrientationData orientationData) { var terrainData = Terrain.terrainData; var unsafeOrientationTexture = new AsyncTextureUnsafe <Color32>(orientationData.OrientationTexture); var unsafeWeightsTexture = new AsyncTextureUnsafe <Color32>(orientationData.WeightsTexture); var unsafeDuckTexture = new AsyncTextureUnsafe <Color32>(orientationData.DuckTexture); Vector3 terrainSize = terrainData.size; int mapWidth = terrainData.alphamapWidth; int mapHeight = terrainData.alphamapHeight; int alphamapLength = RenderConfig.MapTextures.Count(); float[,,] alphaMaps = terrainData.GetAlphamaps(0, 0, mapWidth, mapHeight); float maxTextureNormalX = Width / RenderConfig.ChunkWidth; float maxTextureNormalZ = Height / RenderConfig.ChunkHeight; float indexToNormalX = 1f / (mapHeight - 1f); float indexToNormalZ = 1f / (mapWidth - 1f); Vector3 chunkPosition = transform.position; var columnTasks = new Task[mapHeight]; for (int height = 0; height < mapHeight; height++) { int cachedHeight = height; var indexBytes = new byte[2]; PointOrientationData pointOrientation = new PointOrientationData(); float[] returnMap = new float[RenderConfig.MapTextures.Count()]; float[] intermediateMap = new float[RenderConfig.MapTextures.Count()]; var columnTask = new Task(() => { for (int width = 0; width < mapWidth; width++) { float terrainNormalX, terrainNormalZ, textureNormalX, textureNormalZ, worldX, worldZ; Color32 orientationColor; Color weightsColor, duckColor; //For some reason, terrainData seems to index its points //as (y, x) rather than the more traditional (x, y), so //we need to sample our texture accordingly terrainNormalX = cachedHeight * indexToNormalX; terrainNormalZ = width * indexToNormalZ; worldX = chunkPosition.x + terrainNormalX * terrainSize.x; worldZ = chunkPosition.z + terrainNormalZ * terrainSize.z; textureNormalX = maxTextureNormalX * terrainNormalX; textureNormalZ = maxTextureNormalZ * terrainNormalZ; orientationColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeOrientationTexture)); weightsColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeWeightsTexture)); duckColor = ColorCorrection.ARGB_To_RGBA(RawTextureSampler.SamplePoint(textureNormalX, textureNormalZ, unsafeDuckTexture)); PointOrientationLogic.GetOrientationDataFromColors( pointOrientation, indexBytes, orientationColor, weightsColor, duckColor ); AlphamapLogic.GetAlphamapFromOrientation(returnMap, intermediateMap, pointOrientation); for (int alphaIndex = 0; alphaIndex < alphamapLength; alphaIndex++) { alphaMaps[width, cachedHeight, alphaIndex] = returnMap[alphaIndex]; } } }); columnTask.Start(); columnTasks[cachedHeight] = columnTask; } while (columnTasks.Any(task => !task.IsCompleted)) { yield return(SkipFrame); } terrainData.SetAlphamaps(0, 0, alphaMaps); }