BITFALL/Assets/Plugins/Polaris - Low Poly Ecosystem/Polaris - Low Poly Terrain .../Runtime/Scripts/Extensions/VSP Integration/GVSPPolarisTerrain.cs

300 lines
14 KiB
C#
Raw Normal View History

2023-12-30 17:37:48 +08:00
#if GRIFFIN && VEGETATION_STUDIO_PRO
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using AwesomeTechnologies.MeshTerrains;
using AwesomeTechnologies.VegetationSystem;
using AwesomeTechnologies.VegetationSystem.Biomes;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using AwesomeTechnologies.Utility;
using AwesomeTechnologies.Utility.Quadtree;
namespace Pinwheel.Griffin.VegetationStudioPro
{
public class GVSPPolarisTerrain : MeshTerrain
{
public new string TerrainType => "Polaris terrain";
public GStylizedTerrain Terrain;
private int _heightmapHeight;
private int _heightmapWidth;
private Vector3 _size;
private Vector3 _scale;
private Vector3 _heightmapScale;
private Rect _terrainRect;
public NativeArray<float> Heights;
private JobHandle _splatMapHandle;
private NativeArray<HeightMapSample> _heightMapSamples;
private NativeArray<float> _currentSplatmapArray;
private readonly List<NativeArray<float>> _nativeArrayFloatList = new List<NativeArray<float>>();
public override bool NeedsSplatMapUpdate(Bounds updateBounds)
{
return updateBounds.Intersects(TerrainBounds);
}
public override void PrepareSplatmapGeneration(bool clearLockedTextures)
{
LoadHeightData();
int width = Terrain.TerrainData.Shading.SplatControlResolution;
int height = Terrain.TerrainData.Shading.SplatControlResolution;
int layers = Terrain.TerrainData.Shading.Splats.Prototypes.Count;
int heightMapLength = width * height;
if (_heightMapSamples.IsCreated) _heightMapSamples.Dispose();
_heightMapSamples = new NativeArray<HeightMapSample>(heightMapLength, Allocator.TempJob);
SampleHeightMapJob sampleHeightMapJob = new SampleHeightMapJob
{
HeightMapSamples = _heightMapSamples,
InputHeights = Heights,
HeightMapScale = _heightmapScale,
HeightmapHeight = _heightmapHeight,
HeightmapWidth = _heightmapWidth,
Scale = _scale,
Size = _size,
Width = width,
Height = height
};
_splatMapHandle = sampleHeightMapJob.Schedule(heightMapLength, 32);
if (_currentSplatmapArray.IsCreated) _currentSplatmapArray.Dispose();
_currentSplatmapArray = new NativeArray<float>(width * height * layers, Allocator.TempJob);
if (!clearLockedTextures)
{
float[,,] spltmapArray = Terrain.TerrainData.Shading.GetAlphamaps();
_currentSplatmapArray.CopyFromFast(spltmapArray);
}
}
public override void GenerateSplatMapBiome(Bounds updateBounds, BiomeType biomeType, List<PolygonBiomeMask> polygonBiomeMaskList, List<TerrainTextureSettings> terrainTextureSettingsList, float heightCurveSampleHeight, float worldSpaceSeaLevel, bool clearLockedTextures)
{
int width = Terrain.TerrainData.Shading.SplatControlResolution;
int height = Terrain.TerrainData.Shading.SplatControlResolution;
int layers = Terrain.TerrainData.Shading.Splats.Prototypes.Count;
int blendMaskLength = width * height;
NativeArray<float> blendMask = new NativeArray<float>(blendMaskLength, Allocator.TempJob);
NativeArray<float> splatmapArray = new NativeArray<float>(width * height * layers, Allocator.TempJob);
if (biomeType == BiomeType.Default)
{
UnityTerrain.GenerateDefaultBiomeBlendMaskJob generateDefaultBiomeBlendMaskJob =
new UnityTerrain.GenerateDefaultBiomeBlendMaskJob { BlendMask = blendMask };
_splatMapHandle = generateDefaultBiomeBlendMaskJob.Schedule(blendMaskLength, 32, _splatMapHandle);
}
else
{
for (int i = 0; i <= polygonBiomeMaskList.Count - 1; i++)
{
UnityTerrain.GenerateBlendMaskJob generateBlendMaskJob = new UnityTerrain.GenerateBlendMaskJob
{
Width = width,
Height = height,
TerrainSize = _size,
TerrainPosition = Terrain.transform.position,
BlendMask = blendMask,
PolygonArray = polygonBiomeMaskList[i].PolygonArray,
SegmentArray = polygonBiomeMaskList[i].SegmentArray,
CurveArray = polygonBiomeMaskList[i].TextureCurveArray,
UseNoise = polygonBiomeMaskList[i].UseNoise,
NoiseScale = polygonBiomeMaskList[i].NoiseScale,
BlendDistance = polygonBiomeMaskList[i].BlendDistance,
PolygonRect = RectExtension.CreateRectFromBounds(polygonBiomeMaskList[i].MaskBounds),
Include = true
};
_splatMapHandle = generateBlendMaskJob.Schedule(blendMaskLength, 32, _splatMapHandle);
}
}
for (int i = 0; i <= terrainTextureSettingsList.Count - 1; i++)
{
if (i >= layers) continue;
if (terrainTextureSettingsList[i].Enabled)
{
UnityTerrain.ProcessSplatMapJob processSplatMap = new UnityTerrain.ProcessSplatMapJob
{
Height = height,
Width = width,
Layers = layers,
SplatMapArray = splatmapArray,
BlendMask = blendMask,
HeightMap = _heightMapSamples,
Heights = Heights,
TextureIndex = i,
TextureUseNoise = terrainTextureSettingsList[i].UseNoise,
TextureNoiseScale = terrainTextureSettingsList[i].NoiseScale,
TextureWeight = terrainTextureSettingsList[i].TextureWeight,
TextureNoiseOffset = terrainTextureSettingsList[i].NoiseOffset,
InverseTextureNoise = terrainTextureSettingsList[i].InverseNoise,
HeightCurve = terrainTextureSettingsList[i].HeightCurveArray,
SteepnessCurve = terrainTextureSettingsList[i].SteepnessCurveArray,
TerrainHeight = heightCurveSampleHeight,
TerrainYPosition = Terrain.transform.position.y,
WorldspaceSeaLevel = worldSpaceSeaLevel,
HeightMapScale = _heightmapScale,
HeightmapHeight = _heightmapHeight,
HeightmapWidth = _heightmapWidth,
ConcaveEnable = terrainTextureSettingsList[i].ConcaveEnable,
ConvexEnable = terrainTextureSettingsList[i].ConvexEnable,
ConcaveAverage = terrainTextureSettingsList[i].ConcaveAverage,
ConcaveMinHeightDifference = terrainTextureSettingsList[i].ConcaveMinHeightDifference,
ConcaveDistance = terrainTextureSettingsList[i].ConcaveDistance,
ConcaveMode = (int)terrainTextureSettingsList[i].ConcaveMode,
TerrainSize = _size,
TerrainPosition = Terrain.transform.position
};
_splatMapHandle = processSplatMap.Schedule(width * height * layers, 32, _splatMapHandle);
}
else
{
if (!clearLockedTextures && terrainTextureSettingsList[i].LockTexture)
{
UnityTerrain.CopyLockedDataJob copyLockedDataJobJob = new UnityTerrain.CopyLockedDataJob
{
Height = height,
Width = width,
Layers = layers,
SplatMapArray = splatmapArray,
CurrentSplatMapArray = _currentSplatmapArray,
TextureIndex = i,
};
_splatMapHandle = copyLockedDataJobJob.Schedule(width * height * layers, 32, _splatMapHandle);
}
}
}
int firstEnabledIndex = 0;
for (int i = 0; i <= terrainTextureSettingsList.Count - 1; i++)
{
if (terrainTextureSettingsList[i].Enabled)
{
firstEnabledIndex = i;
break;
}
}
if (!clearLockedTextures)
{
NativeArray<int> lockedTextureArray = new NativeArray<int>(terrainTextureSettingsList.Count, Allocator.TempJob);
NativeArray<int> automaticGenerationArray = new NativeArray<int>(terrainTextureSettingsList.Count, Allocator.TempJob);
for (int i = 0; i <= terrainTextureSettingsList.Count - 1; i++)
{
if (terrainTextureSettingsList[i].Enabled)
{
automaticGenerationArray[i] = 1;
}
else if (terrainTextureSettingsList[i].LockTexture)
{
lockedTextureArray[i] = 1;
}
}
UnityTerrain.NormalizeSplatMapKeepLockedDataJob normalizeSplatMapJob = new UnityTerrain.NormalizeSplatMapKeepLockedDataJob
{
SplatMapArray = splatmapArray,
FirstEnabledIndex = firstEnabledIndex,
AutomaticGenerationArray = automaticGenerationArray,
LockedTextureArray = lockedTextureArray
};
_splatMapHandle = normalizeSplatMapJob.ScheduleBatch(width * height * layers, layers, _splatMapHandle);
}
else
{
UnityTerrain.NormalizeSplatMapJob normalizeSplatMapJob = new UnityTerrain.NormalizeSplatMapJob
{
SplatMapArray = splatmapArray,
FirstEnabledIndex = firstEnabledIndex
};
_splatMapHandle = normalizeSplatMapJob.ScheduleBatch(width * height * layers, layers, _splatMapHandle);
}
//blend biome splatmap against current splatmap
UnityTerrain.BlendSplatMapJob blendSplatMapJob = new UnityTerrain.BlendSplatMapJob
{
CurrentSplatMapArray = _currentSplatmapArray,
SplatMapArray = splatmapArray,
BlendMask = blendMask,
Height = height,
Width = width,
Layers = layers
};
_splatMapHandle = blendSplatMapJob.Schedule(width * height * layers, 32, _splatMapHandle);
_nativeArrayFloatList.Add(splatmapArray);
_nativeArrayFloatList.Add(blendMask);
}
public override void CompleteSplatmapGeneration()
{
_splatMapHandle.Complete();
int width = Terrain.TerrainData.Shading.SplatControlResolution;
int height = Terrain.TerrainData.Shading.SplatControlResolution;
int layers = Terrain.TerrainData.Shading.Splats.Prototypes.Count;
//float[] splatmap1DArray = new float[width * height * layers];
//NativeToManagedCopyMemory(splatmap1DArray, _currentSplatmapArray);
//_terrain.terrainData.SetAlphamaps(0, 0, To3DArray(splatmap1DArray, width, height, layers));
float[,,] splatmapArray = new float[width, height, layers];
_currentSplatmapArray.CopyToFast(splatmapArray);
Terrain.TerrainData.Shading.SetAlphamaps(splatmapArray);
if (_heightMapSamples.IsCreated) _heightMapSamples.Dispose();
if (_currentSplatmapArray.IsCreated) _currentSplatmapArray.Dispose();
for (int i = 0; i <= _nativeArrayFloatList.Count - 1; i++)
{
if (_nativeArrayFloatList[i].IsCreated) _nativeArrayFloatList[i].Dispose();
}
//splatmapArray.CopyTo(splatmap1DArray);
_nativeArrayFloatList.Clear();
}
void LoadHeightData()
{
var terrainData = Terrain.TerrainData;
Vector2 _heightmapTexelSize = terrainData.Geometry.HeightMap.texelSize;
_heightmapScale = new Vector3(_heightmapTexelSize.x * terrainData.Geometry.Width, terrainData.Geometry.Height, _heightmapTexelSize.y * terrainData.Geometry.Length);
_heightmapHeight = terrainData.Geometry.HeightMapResolution;
_heightmapWidth = terrainData.Geometry.HeightMapResolution;
_size = terrainData.Geometry.Size;
_scale.x = _size.x / (_heightmapWidth - 1);
_scale.y = _size.y;
_scale.z = _size.z / (_heightmapHeight - 1);
Vector2 terrainCenter = new Vector2(Terrain.transform.position.x, Terrain.transform.position.z);
Vector2 terrainSize = new Vector2(_size.x, _size.z);
_terrainRect = new Rect(terrainCenter, terrainSize);
float[,] hs = Terrain.TerrainData.Geometry.GetHeights();
if (Heights.IsCreated) Heights.Dispose();
Heights = new NativeArray<float>(_heightmapWidth * _heightmapHeight, Allocator.Persistent);
Heights.CopyFromFast(hs);
}
}
}
#endif