Greetings.
I’m trying to get heightmap data from a landscape (for a custom physics).
Currently my code is like the following:
void AMyPhysWorld::BeginPlay()
{
...
ULandscapeInfo * info = ULandscapeInfo::FindOrCreate(GetWorld(), landscape->GetLandscapeGuid());
info->ForAllLandscapeComponents([&](ULandscapeComponent * component)
{
UTexture2D * hm = component->GetHeightmap();
...
const FTexturePlatformData * platformData = hm->GetPlatformData();
FByteBulkData textureData = platformData->Mips[0].BulkData;
const auto pixelData = static_cast<const FColor *>(textureData.LockReadOnly());
if (pixelData == nullptr)
{
UKismetSystemLibrary::PrintString(this, "pixelData == nullptr");
textureData.Unlock();
return;
}
...
});
...
}
Having 2 problems:
- ‘ForAllLandscapeComponents’ iterates over visible/loaded components of the landscape only. Is there any way to make it iterate over the whole set?
- ‘pixelData’ locked from Mips[0] is null, though for Mips[1] Mips[1] and so on it’s not null. How can I load it / nudge somehow unreal to load it?
Thanks.
1 Like
Finally I was able to get to the heights data:
void GatherCollidersLandscape(ALandscape * landscape)
{
ULandscapeInfo * info = landscape->CreateLandscapeInfo();
info->ForAllLandscapeComponents([&](ULandscapeComponent * component)
{
ULandscapeHeightfieldCollisionComponent * collisionComponent = component->GetCollisionComponent();
Chaos::FHeightField * heightField = collisionComponent->HeightfieldRef->Heightfield.Get();
FVector positionChunk = collisionComponent->GetComponentTransform().GetLocation();
float zScale = float(heightField->GeomData.Scale.Z);
float unitHeight = heightField->GeomData.HeightPerUnit;
float minValue = heightField->GeomData.MinValue;
float cellWidth = heightField->GeomData.GetCellWidth();
int32 verticesY = heightField->GetNumRows();
float sizeY = cellWidth * float(verticesY - 1);
int32 verticesX = heightField->GetNumCols();
float sizeX = cellWidth * float(verticesX - 1);
TArray<float> heights;
for (int i = 0; i < verticesX * verticesY; i++)
{
float h = minValue + float(heightField->GeomData.Heights[i]) * unitHeight;
h *= zScale;
h += positionChunk.Z;
heights.Emplace(h);
// ...
}
});
}
But the number of components is still less than expected.
How to make ue load them all?
I really need it at the very beginning of the level because otherwise all dynamic bodies located at the non-loaded chunks would fall below the terrain.