1

I would like to create a landscape from scratch in unreal engine 4.27 using C++ only. I have only a simple notion of the process, which revolves around GetWorld()->SpawnActor<ALandscape>, ALandscapeProxy::Import(...) and importing a height/weight map.


I used the LandscapeEditorDetailCustomization_NewLandscape::OnCreateButtonClicked() method as a learning ground, but unfortunately I am at an impasse.


From what I have gathered from my searches there not a lot of examples on the matter. Does anyone have a suggestion or an example?

Spiros
  • 53
  • 6
  • Have you used the Landscape Tool in the editor first? https://docs.unrealengine.com/4.27/en-US/BuildingWorlds/Landscape/Creation/ It might be helpful to get familiar with that first, and might provide more clarity on the C++ interface: https://docs.unrealengine.com/4.27/en-US/API/Runtime/Landscape/ALandscape/ – Andrew Tomazos Mar 10 '22 at 20:28
  • 1
    @AndrewTomazos I have. In fact the `OnCreateButtonClicked()` I mentioned is the Landscape Editor Tool. Specifically the one that is invoked when the Create/Import button is pressed. I also mentioned that I was unsuccessful on making a prototype; that was due to it being dependent on modules like the UI parser, or protected class fields etc. That's why I asked for a more streamlined and to the point example. – Spiros Mar 11 '22 at 07:18
  • What is your actual question? – Crasher Mar 23 '22 at 19:36
  • For an example explaining the key variables and functions in creating an environment, since pre existing modules are not clear on the matter. – Spiros Apr 06 '22 at 07:43

1 Answers1

2

This is the solution I came up with, with many thanks to ChenHP (or chpsemail) who gave me a solution to this. Firstly, declare the following variables. A better understanding can be found here.

FQuat InRotation
FVector InTranslation
FVector InScale
FTransform LandscapeTransform{InRotation, InTranslation, InScale}
int32 QuadsPerSection
int32 SectionsPerComponent
int32 ComponentCountX
int32 ComponentCountY
int32 QuadsPerComponent
int32 SizeX
int32 SizeY

Create containers for the heights and materials of the landscape:

TArray<FLandscapeImportLayerInfo> MaterialImportLayers
TMap<FGuid, TArray<uint16>> HeightDataPerLayers
TMap<FGuid, TArray<FLandscapeImportLayerInfo>> MaterialLayerDataPerLayers

It is important to note that heights in UE4 are of uint16 type, with 0 the deepest and 65'534 the highest. So for a flat map all height entries should be 32768. The number of heights is the resolution of the map which is dependent on SizeX and SizeY.

TArray<uint16> HeightData;
HeightData.SetNum(SizeX * SizeY);
for (int32 i = 0; i < HeightData.Num(); i++)
{
    HeightData[i] = 32768;
}

Height and material information should then be placed in the corresponding containers and be given a valid FGuid.

HeightDataPerLayers.Add(FGuid(), MoveTemp(HeightData))
MaterialLayerDataPerLayers.Add(FGuid(), MoveTemp(MaterialImportLayers))

At this point the base parameters for the landscape have been set. The ALandscape* Landscape = SpawnActor<ALandscape>() could be called at either point since it just spawns an object that doesn't actually have any information about it. This also applies for setting landscape's fields. Fields that need to be set are presented bellow:

Landscape->bCanHaveLayersContent
Landscape->LandscapeMaterial
Landscape->SetActorTransform
Landscape->StaticLightingLOD
ULandscapeInfo* LandscapeInfo = Landscape->GetLandscapeInfo()
LandscapeInfo->UpdateLayerInfoMap(Landscape)
Landscape->RegisterAllComponents()
Landscape->GetClass()
Landscape->PostEditChangeProperty(MaterialPropertyChangedEvent)
Landscape->PostEditChange()

The actual part where landscape is given form, happens with the invocation of Landscape->Import(...).


A detailed explanation about what the script could look like can be found here with more information on landscape (check the answer for the cpp code).

Spiros
  • 53
  • 6
  • related (on python) https://stackoverflow.com/questions/71394649/landscape-creation-in-ue4-27-using-python?rq=1 – Nande Dec 01 '22 at 03:00