| 1035 | } |
| 1036 | |
| 1037 | bool TerrainPatch::SetupSplatMap(int32 index, int32 splatMapLength, const Color32* splatMap, bool forceUseVirtualStorage) |
| 1038 | { |
| 1039 | PROFILE_CPU_NAMED("Terrain.SetupSplatMap"); |
| 1040 | PROFILE_MEM(LevelTerrain); |
| 1041 | CHECK_RETURN(index >= 0 && index < TERRAIN_MAX_SPLATMAPS_COUNT, true); |
| 1042 | if (splatMap == nullptr) |
| 1043 | { |
| 1044 | LOG(Warning, "Cannot create terrain without any splatmap specified."); |
| 1045 | return true; |
| 1046 | } |
| 1047 | TerrainDataUpdateInfo info(this, _yOffset, _yHeight); |
| 1048 | if (splatMapLength != info.HeightmapLength) |
| 1049 | { |
| 1050 | LOG(Warning, "Invalid splatmap length. Terrain of chunk size equal {0} uses heightmap of size {1}x{1} (heightmap array length must be {2}). Input heightmap has length {3}.", info.ChunkSize, info.HeightmapSize, info.HeightmapLength, splatMapLength); |
| 1051 | return true; |
| 1052 | } |
| 1053 | const PixelFormat pixelFormat = PixelFormat::R8G8B8A8_UNorm; |
| 1054 | |
| 1055 | // Ensure that terrain has a valid heightmap |
| 1056 | if (Heightmap == nullptr) |
| 1057 | { |
| 1058 | if (InitializeHeightMap() || Heightmap == nullptr) |
| 1059 | { |
| 1060 | LOG(Warning, "Cannot modify splatmap without valid heightmap loaded."); |
| 1061 | return true; |
| 1062 | } |
| 1063 | } |
| 1064 | |
| 1065 | // Input splatmap data overlaps on chunk edges but it needs to be duplicated for chunks |
| 1066 | const int32 pixelStride = PixelFormatExtensions::SizeInBytes(pixelFormat); |
| 1067 | const int32 lodCount = Math::Min<int32>(_terrain->_lodCount, MipLevelsCount(info.VertexCountEdge) - 2); |
| 1068 | |
| 1069 | // Prepare |
| 1070 | #if USE_EDITOR |
| 1071 | const bool useVirtualStorage = Editor::IsPlayMode || forceUseVirtualStorage; |
| 1072 | #else |
| 1073 | const bool useVirtualStorage = true; |
| 1074 | #endif |
| 1075 | #if USE_EDITOR |
| 1076 | String splatMapPath; |
| 1077 | if (!useVirtualStorage) |
| 1078 | { |
| 1079 | if (!_terrain->GetScene()) |
| 1080 | { |
| 1081 | LOG(Error, "Cannot create non-virtual terrain. Add terrain actor to scene first (needs scene folder path for target assets location)."); |
| 1082 | return true; |
| 1083 | } |
| 1084 | const String cacheDir = _terrain->GetScene()->GetDataFolderPath() / TEXT("Terrain/") / _terrain->GetID().ToString(Guid::FormatType::N); |
| 1085 | |
| 1086 | // Prepare asset path for the non-virtual assets |
| 1087 | splatMapPath = cacheDir + String::Format(TEXT("_{0:2}_{1:2}_Splatmap{3}.{2}"), _x, _z, ASSET_FILES_EXTENSION, index); |
| 1088 | } |
| 1089 | #endif |
| 1090 | |
| 1091 | // Create heightmap texture data source container |
| 1092 | auto initData = New<TextureBase::InitData>(); |
| 1093 | initData->Format = pixelFormat; |
| 1094 | initData->Width = info.TextureSize; |
no test coverage detected