UE 5.3 heightmap data from landscape

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.