I recently managed to write custom heightmap data to the Landscape using the helper class FHeightmapAccessor. I haven’t tried it in runtime yet though, but I think it might be possible.
- As a starting point, have a look at the following function, found in /Engine/Source/Editor/LandscapeEditor/Private/LandscapeEdMode.cpp
bool LandscapeEditorUtils::SetHeightmapData(ALandscapeProxy* Landscape, const TArray<uint16>& Data)
{
FIntRect ComponentsRect = Landscape->GetBoundingRect() + Landscape->LandscapeSectionOffset;
if (Data.Num() == (1 + ComponentsRect.Width())*(1 + ComponentsRect.Height()))
{
FHeightmapAccessor<false> HeightmapAccessor(Landscape->GetLandscapeInfo());
HeightmapAccessor.SetData(ComponentsRect.Min.X, ComponentsRect.Min.Y, ComponentsRect.Max.X, ComponentsRect.Max.Y, Data.GetData());
return true;
}
return false;
}
…and just replicate that code. You don’t want to use that function directly since it is in an Editor module. The FHeightmapAccessor will update the internal textures, includig mips, and recalculate the normals for you.
ComponentsRect corresponds to the number of quads, meaning that for example Width() + 1 is the number of vertices along the X-axis.
If you want to manually set normals etc, just look inside the implementation of SetData() and replicate what it does but pass also normal data etc to LandscapeEdit->SetHeightData(...)
.
- Though, you probably first need to convert your floating point heights to uint16 packed for the heightmaps. You can do it like this, per height in your array:
#include "LandscapeDataAccess.h"
...
float HeightCm = /* height in centimeter */
float HeightLocal = HeightCm / Landscape->GetTransform().GetScale3D().Z;
uint16 HeightTex = LandscapeDataAccess::GetTexHeight(HeightLocal);