I created a Icosahedron with DynamicLOD. This works greate. Now i wanted to use a Heightmap to add Terrain. First i tried with GrayScale HeightMap. But the Result was just random displacement. Than i tried with the B/W Image below and got this:
For testing i use a B/W Image.
As you can see there is no Data that shows Gaps. First i thought i had some Error in reading the Image. But when i write the Data from Memory back into a File i have the same Image.
This is how i read the Image:
TArray<uint8> TempData;
if (!FFileHelper::LoadFileToArray(TempData, TEXT("../../../../../UnrealProjects/LODTest/Content/Materials/nocompression.png") , FILEREAD_Silent))
{
UE_LOG(LogTemp, Warning, TEXT("Could not load File"));
}
else
{
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>("ImageWrapper");
TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
if (!ImageWrapper->SetCompressed(TempData.GetData(), TempData.Num()))
{
UE_LOG(LogTemp, Warning, TEXT("Compress Error"));
}
if (ImageWrapper->GetFormat() != ERGBFormat::Gray)
{
UE_LOG(LogTemp, Warning, TEXT("Not GrayScale"));
}
if (ImageWrapper->GetBitDepth() != 16)
{
UE_LOG(LogTemp, Warning, TEXT("Not 16Bit"));
}
const TArray<uint8>* RawData = nullptr;
if (!ImageWrapper->GetRaw(ERGBFormat::Gray, 16, RawData))
{
UE_LOG(LogTemp, Warning, TEXT("Could not get Raw Data"));
}
else
{
heightValues.SetNum(ImageWrapper->GetWidth() * ImageWrapper->GetHeight());
FMemory::Memcpy(heightValues.GetData(), RawData->GetData(), ImageWrapper->GetWidth() * ImageWrapper->GetHeight() * 2);
UE_LOG(LogTemp, Warning, TEXT("Success"));
}
}
And here how i read the Values: (point is a UV coordinate)
uint16 heightValue = heightMap[(point.X * imageWidth) * (point.Y * imageHeight)];
float value = heightValue / 65535.f;
return value;
I exported the Mesh into Blender and used the HeightMap there with no Issues. Now i am out of Ideas :(
EDIT: As Azarus said the way i get the height value was wrong. Now i use this:
int32 locX = UKismetMathLibrary::MapRangeClamped(point.X, 0.f, 1.f, 0.f, imageWidth);
int32 locY = UKismetMathLibrary::MapRangeClamped(point.Y, 0.f, 1.f, 0.f, imageHeight);
uint16 heightValue = heightMap[imageWidth * locY + locX];
Your height sampling seems to be wrong:
heightMap[(point.X * imageWidth) * (point.Y * imageHeight)]
It's basic math really.
The answer is the same and that's the problem
1*0=0
and so does 0*1=0
While you clearly wanted different input.
Assuming you have read the image correctly then just compressing the 2D coordinate into 1D the following formula should work:
Compressing 2D Array Coordinates to 1D:
Index=(X*RowSize)+Y
Applying this to your code:
heightMap[(point.X * imageWidth) + point.Y]