#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 Heights; private JobHandle _splatMapHandle; private NativeArray _heightMapSamples; private NativeArray _currentSplatmapArray; private readonly List> _nativeArrayFloatList = new List>(); 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(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(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 polygonBiomeMaskList, List 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 blendMask = new NativeArray(blendMaskLength, Allocator.TempJob); NativeArray splatmapArray = new NativeArray(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 lockedTextureArray = new NativeArray(terrainTextureSettingsList.Count, Allocator.TempJob); NativeArray automaticGenerationArray = new NativeArray(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(_heightmapWidth * _heightmapHeight, Allocator.Persistent); Heights.CopyFromFast(hs); } } } #endif