Пример #1
0
    // ignores the Y coordinate of position
    public void ApplyDamage(Vector3 position, TerrainDamageConfig config, float severity = 1.0f)
    {
        Vector3 terrainCell = position;

        terrainCell -= transform.position;

        terrainCell.x = (terrainCell.x * terrainData.heightmapResolution) / terrainData.size.x;
        terrainCell.z = (terrainCell.z * terrainData.heightmapResolution) / terrainData.size.z;

//		int iCenter = (int)terrainCell.x;
//		int jCenter = (int)terrainCell.z;

        // choose what this particular hole is going to look like
        float holeDepth  = Random.Range(config.MinDepth, config.MaxDepth);
        float holeRadius = Random.Range(config.MinRadius, config.MaxRadius);

        holeDepth  *= severity;
        holeRadius *= severity;

        if (config.RemoveEarth)
        {
            holeDepth = -holeDepth;
        }

        float baseAdjustment = holeDepth / TerrainVerticalScale;

        float maxHeightmapAdjustment = MaxDeformation / TerrainVerticalScale;

        int xMin = (int)(terrainCell.x - holeRadius);
        int xMax = (int)(terrainCell.x + holeRadius);
        int zMin = (int)(terrainCell.z - holeRadius);
        int zMax = (int)(terrainCell.z + holeRadius);

        int iHoleRadius = (int)holeRadius;

        if (iHoleRadius < 1)
        {
            iHoleRadius = 1;
        }

        int iHoleRadiusSquaredDivider = iHoleRadius * iHoleRadius * 2;

        // <WIP> future optimization: pull out just the sub-region that
        // gets modified and only update those heights rather than all.

        int dz = -iHoleRadius;

        for (int z = zMin; z <= zMax; z++, dz++)
        {
            int dx = -iHoleRadius;
            for (int x = xMin; x < xMax; x++, dx++)
            {
                if (z >= 0 && z < heightmap.GetLength(0))
                {
                    if (x >= 0 && x < heightmap.GetLength(1))
                    {
                        float fraction = 1.0f;

                        switch (config.HoleShape)
                        {
                        default:
                        case TerrainDamageConfig.ProceduralHoleShape.RECTANGULAR:
                            break;

                        case TerrainDamageConfig.ProceduralHoleShape.INVERTEDCONE:
                        {
                            int offCenter = dx * dx + dz * dz;
                            if (offCenter >= iHoleRadiusSquaredDivider)
                            {
                                offCenter = iHoleRadiusSquaredDivider;
                            }
                            fraction = (iHoleRadiusSquaredDivider - offCenter) / (float)iHoleRadiusSquaredDivider;
                        }
                        break;

                        case TerrainDamageConfig.ProceduralHoleShape.CIRCULAR:
                        {
                            int offCenter = dx * dx + dz * dz;
                            fraction = (offCenter <= iHoleRadiusSquaredDivider / 2) ? 1.0f : 0.0f;
                        }
                        break;
                        }

                        float adjustment = baseAdjustment * fraction;

                        var heightSample = heightmap[z, x] + adjustment;

                        if (heightSample < originalHeightmap[z, x] - maxHeightmapAdjustment)
                        {
                            heightSample = originalHeightmap[z, x] - maxHeightmapAdjustment;
                        }
                        if (heightSample > originalHeightmap[z, x] + maxHeightmapAdjustment)
                        {
                            heightSample = originalHeightmap[z, x] + maxHeightmapAdjustment;
                        }

                        heightmap[z, x] = heightSample;

                        if (z < splatMaps.GetLength(0))
                        {
                            if (x < splatMaps.GetLength(1))
                            {
                                for (int k = 0; k < splatMaps.GetLength(2); k++)
                                {
                                    if (fraction > 0.5f)
                                    {
                                        splatMaps[z, x, k] = (k == config.ColorForDamage) ? 1.0f : 0.0f;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        terrainData.SetHeights(0, 0, heightmap);
        terrainData.SetAlphamaps(0, 0, splatMaps);
    }
Пример #2
0
 void Start()
 {
     config = ScriptableObject.CreateInstance <TerrainDamageConfig>();
 }