Making Heightmaps with c++?

After some searching I have given up on trying to find a way to set the heightmap using c++. It just is not worth it. I instead focused on making a heightmap using c++. This has worked a litle bit. Combining the info from redblobgames (Making maps with noise functions) and Isara Tech (UE4 - Save a procedurally generated texture as a new asset - Isara Tech.) I was able to create a 2 dimensonal array containing perlin noise values. I then used these values to set the gray colors of a texture (make shure u are using PF_G8 as pixel format). This texture is then saved to the /Game/ProceduralTextures/ folder. After that u have to export the texture out of the map, open the file using paint and the save the file as a png. The result I got from the code where les than optimal but it something. If you find this I hope you have better luck automating this then I did.

//my input is a landscape object
void ACPP_TestLevel::VeranderLandschap(ALandscape* landscape)
{
	// this is code from https://isaratech.com/save-a-procedurally-generated-texture-as-a-new-asset/
	// it is about saving textures to a local folder.
	// tested this code out to see if i actualy created the texture.
	int TextureWidth = 256;
	int TextureHeight = 256;

	FString TextureName = "testtexture5";
	FString PackageName = TEXT("/Game/ProceduralTextures/");
	PackageName += TextureName;
	UPackage* Package = CreatePackage(NULL, *PackageName);
	Package->FullyLoad();

	UTexture2D* NewTexture = NewObject<UTexture2D>(Package, *TextureName, RF_Public | RF_Standalone | RF_MarkAsRootSet);

	NewTexture->AddToRoot();				// This line prevents garbage collection of the texture
	NewTexture->PlatformData = new FTexturePlatformData();	// Then we initialize the PlatformData
	NewTexture->PlatformData->SizeX = TextureWidth;
	NewTexture->PlatformData->SizeY = TextureHeight;
	//NewTexture->PlatformData->NumSlices = 1;
	NewTexture->PlatformData->PixelFormat = EPixelFormat::PF_G8;


	int height = TextureHeight;
	int width = TextureWidth;

	double value[256][256];

	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			float nx = (x/(width-0.5));
			float ny = (y/(height-0.5));

			float e = 1*FMath::PerlinNoise2D(FVector2D((1*nx), (1*ny)));
			e = (e+0.5*FMath::PerlinNoise2D(FVector2D((2*nx), (2*ny))));
			e = (e+0.25 *FMath::PerlinNoise2D(FVector2D((4*nx),(4*ny))));
			e = (e /(1 + 0.5 + 0.25));
			value[y][x] = pow(e, 1.00);
			
		}
	}

	

	uint8* Pixels = new uint8[TextureWidth * TextureHeight];
	for (int32 y = 0; y < TextureHeight; y++)
	{
		for (int32 x = 0; x < TextureWidth; x++)
		{
			//int color = FMath::PerlinNoise1D(static_cast <float> (rand()) / static_cast <float> (RAND_MAX))*255;

			int32 curPixelIndex = ((y * TextureWidth) + x);
			Pixels[curPixelIndex] = (value[y][x])*255;
		}
	}
	// Allocate first mipmap.
	FTexture2DMipMap* Mip = new(NewTexture->PlatformData->Mips) FTexture2DMipMap();
	Mip->SizeX = TextureWidth;
	Mip->SizeY = TextureHeight;

	// Lock the texture so it can be modified
	Mip->BulkData.Lock(LOCK_READ_WRITE);
	uint8* TextureData = (uint8*)Mip->BulkData.Realloc(TextureWidth * TextureHeight * 4);
	FMemory::Memcpy(TextureData, Pixels, sizeof(uint8) * TextureHeight * TextureWidth * 4);
	Mip->BulkData.Unlock();

	NewTexture->Source.Init(TextureWidth, TextureHeight, 1, 1, ETextureSourceFormat::TSF_G8, Pixels);

	NewTexture->UpdateResource();
	Package->MarkPackageDirty();
	FAssetRegistryModule::AssetCreated(NewTexture);

	FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
	bool bSaved = UPackage::SavePackage(Package, NewTexture, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *PackageFileName, GError, nullptr, true, true, SAVE_NoError);

	delete[] Pixels;	// Don't forget to free the memory here
	
	int aantal = landscape->LandscapeComponents.Num();
	for (int i = 0; i < aantal; ++i)
	{
		landscape->LandscapeComponents[i]->SetHeightmap(NewTexture);
		landscape->LandscapeComponents[i]->RequestHeightmapUpdate();
		landscape->LandscapeComponents[i]->PostLoad();
	}
}
1 Like