/// <summary> /// Retrieves QPoints for interpolation. /// </summary> /// <param name="heatmap"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="alphaMapResolution"></param> /// <param name="incrementInterval"></param> /// <returns></returns> HeatmapDatum[,] GetQPoints(ref Heatmap heatmap, int x, int y, int alphaMapResolution, float incrementInterval) { HeatmapDatum[,] qPoints = new HeatmapDatum[2, 2]; int xGridSquare = Mathf.FloorToInt(((float)x / incrementInterval)); int yGridSquare = Mathf.FloorToInt(((float)y / incrementInterval)); qPoints[0, 0] = heatmap.heatmapDataPoints[xGridSquare, yGridSquare]; qPoints[0, 1] = heatmap.heatmapDataPoints[xGridSquare, yGridSquare + 1]; qPoints[1, 0] = heatmap.heatmapDataPoints[xGridSquare + 1, yGridSquare]; qPoints[1, 1] = heatmap.heatmapDataPoints[xGridSquare + 1, yGridSquare + 1]; return(qPoints); }
/// <summary> /// Generate heatmap data from the Terrain's height map. /// </summary> /// <param name="heatmap"></param> /// <param name="terrainObjectSize"></param> /// <param name="alphaMapResolution"></param> /// <param name="heightMap"></param> /// <param name="heightMapScale"></param> void TerrainHeightToHeatmapData(Heatmap heatmap, Vector3 terrainObjectSize, int alphaMapResolution, float[,] heightMap, Vector3 heightMapScale, int terrainHeightmapResolution) { HeatmapDatum[,] heatmapValues = new HeatmapDatum[heatmap.heatmapResolution + 1, heatmap.heatmapResolution + 1]; for (int x = 0; x <= heatmap.heatmapResolution; x++) { for (int y = 0; y <= heatmap.heatmapResolution; y++) { float resScaleFactorX = terrainObjectSize.x / heatmap.heatmapResolution; float resScaleFactorZ = terrainObjectSize.z / heatmap.heatmapResolution; Vector3 nodeLocation = new Vector3((int)(y * resScaleFactorZ / (terrainObjectSize.z / (terrainHeightmapResolution - 1))), 0.0f, (int)(x * resScaleFactorX / (terrainObjectSize.x / (terrainHeightmapResolution - 1)))); float nodeValue = heightMap[(int)nodeLocation.z, (int)nodeLocation.x] * heightMapScale.y; heatmapValues[x, y] = new HeatmapDatum(); heatmapValues[x, y].Init(nodeLocation, nodeValue, Coordinates.WorldToTerrainCoords(nodeLocation, terrainObjectSize, alphaMapResolution)); } } heatmap.heatmapDataPoints = heatmapValues; }
/// <summary> /// Generate Heatmap data from custom data provided. /// </summary> /// <param name="heatmap"></param> /// <param name="customData"></param> /// <param name="addValuesOfIntersectingPoints"></param> /// <param name="terrainSize"></param> /// <param name="alphaMapResolution"></param> /// <param name="positionOffset"></param> void CustomDataToHeatmapData(Heatmap heatmap, HeatmapNode[] customData, bool addValuesOfIntersectingPoints, Vector3 terrainSize, int alphaMapResolution, Vector3 positionOffset) { HeatmapDatum[,] heatmapDataArray = new HeatmapDatum[heatmap.heatmapResolution + 1, heatmap.heatmapResolution + 1]; // Assign the resulting value of the alphaMapResolution divided by the dataTextureResolution to a variable, as this is used a lot. int alphaMapDividedByHeatmapResolution = (alphaMapResolution / heatmap.heatmapResolution); // Populate the newly created returnVal array with default data. for (int x = 0; x <= heatmap.heatmapResolution; x++) { for (int y = 0; y <= heatmap.heatmapResolution; y++) { heatmapDataArray[x, y] = new HeatmapDatum(); heatmapDataArray[x, y].value = heatmap.baseValue; heatmapDataArray[x, y].nodePosition = new Vector3((int)(x * alphaMapDividedByHeatmapResolution), 0.0f, (int)(y * alphaMapDividedByHeatmapResolution)); heatmapDataArray[x, y].terrainCoords = new Pair <int>((int)(x * alphaMapDividedByHeatmapResolution), (int)(y * alphaMapDividedByHeatmapResolution)); } } float incrementInterval = (alphaMapResolution / heatmap.heatmapResolution); //Assign the values of all the points we know to the correct position in the array. foreach (HeatmapNode customDatum in customData) { int arrayPositionX, arrayPositionY; int brushSize = customDatum.brushSize; float brushHardness = customDatum.brushHardness; float brushOpacity = customDatum.brushOpacity; // Ensure that the data is valid. brushOpacity = Mathf.Clamp(brushOpacity, 0.0f, 100.0f) / 100; brushHardness = Mathf.Clamp(brushHardness, 0.0f, 100.0f) / 100; // Find the correct position in the array based on the object's transform. Vector3 closetMapPointPosition = GetClosestDataPointPosition((customDatum.position - positionOffset), terrainSize, heatmap.heatmapResolution, alphaMapResolution, incrementInterval); Vector2 textureCoordianates = Coordinates.WorldToTerrainCoords(closetMapPointPosition, terrainSize, alphaMapResolution); // Using the dataTexture Resolution and the Terrain coordiantes, calculate the correct position in the array. arrayPositionX = (int)textureCoordianates.x / alphaMapDividedByHeatmapResolution; arrayPositionY = (int)textureCoordianates.y / alphaMapDividedByHeatmapResolution; // Calculate the correct value when taking the opacity of the brush into account. float value = customDatum.value * brushOpacity; if (!customDatum.overwriteOtherNodeValues) { if (arrayPositionX >= 0 && arrayPositionY >= 0 && arrayPositionX < heatmap.heatmapResolution && arrayPositionY < heatmap.heatmapResolution) { value = customDatum.value * brushOpacity + heatmapDataArray[arrayPositionX, arrayPositionY].value; } } // Using the terrain Coordinates, create the Datum that we're going to store in the Array. HeatmapDatum textureDatum = new HeatmapDatum(); textureDatum.Init(closetMapPointPosition, value, new Pair <int>((int)textureCoordianates.x, (int)textureCoordianates.y)); // Assign the VisualisationTextureDatum to the correct Index in the Array. if (arrayPositionX < heatmap.heatmapResolution && arrayPositionY < heatmap.heatmapResolution && arrayPositionX > 0 && arrayPositionY > 0) { heatmapDataArray[arrayPositionX, arrayPositionY] = textureDatum; } // If the brushSize is less than zero then we won't attempt to update the values of the surrounding nodes. if (brushSize > 0) { // Calculate how many steps outwards we need to take (and thus how many other nodes we need to update). int diameter = (int)(brushSize / alphaMapDividedByHeatmapResolution); // We must have at least 2 steps outwards to be able to define a brush. if (diameter > 0) { int radius = diameter / 2; int radiusSquared = radius * radius; for (int x = -radius; x < +radius; x++) { for (int y = -radius; y < +radius; y++) { int arryPosX = arrayPositionX + x; int arryPosY = arrayPositionY + y; if (arryPosX == arrayPositionX && arryPosY == arrayPositionY) { continue; } if (arryPosX >= 0 && arryPosY >= 0 && arryPosX <= heatmap.heatmapResolution && arryPosY <= heatmap.heatmapResolution) { int dx = arryPosX - arrayPositionX; int dy = arryPosY - arrayPositionY; float distanceSquared = (dx * dx) + (dy * dy); if (distanceSquared <= radiusSquared) { float brushHardnessModifier = radiusSquared - (distanceSquared * (1.0f - brushHardness)); brushHardnessModifier /= radiusSquared; if (!customDatum.overwriteOtherNodeValues) { heatmapDataArray[arryPosX, arryPosY].value += (brushHardnessModifier * customDatum.value) * brushOpacity; } else { heatmapDataArray[arryPosX, arryPosY].value = (brushHardnessModifier * customDatum.value) * brushOpacity; } } } } } } } } heatmap.heatmapDataPoints = heatmapDataArray; }