植被策略
星球算法吧
全部回复
仅看楼主
level 5
KnIfER 楼主
有两类植被体系,实时生成的和实现画好的。
The Procedural Foliage Volumes and the Foliage Paint tool are identical at runtime. The Procedural Foliage Volumes just place foliage instances as if it had been placed by the foliage tool, and you can even add or remove instances with the foliage tool after the simulation has been run. The instances are rendered using a HierarchicalInstancedStaticMeshComponent for each foliage type. The instance buffer is always around while the levels are loaded so the instance data contributes to runtime memory, size on disk and load time. Each instance has 48 bytes of GPU data and 80 bytes of system memory. Unlike Landscape Grass, the Foliage Paint and Procedural Foliage types can have collision.
The Landscape Grass feature renders instances the same way as the Foliage Paint tool (by populating instances in HierarchicalInstancedStaticMeshComponents) but the instance data is generated at runtime and only around the camera. This generation has some minor cost, but it done in a background thread, and it allows you to have what would be many millions of instances placed by the foliage tool and only have the 100,000 or so near the player in memory. Landscape grass does have its own memory cost, which the density map that is generated in the editor for areas with grass that the runtime system uses to know where to place instances. The cost is 2 bytes per landscape vertex for components which have grass (to store the height data) plus 1 byte per vertex for each grass type. This cost is typically much lower than it would be if they were painted or procedural instances.
(Procedural Procedural Foliage Volumes and Foliage Instances peformance --ue4 answerhub)
2019年01月30日 15点01分 1
level 5
KnIfER 楼主
“……
UWorld* World = GEditor->GetEditorWorldContext().World();
ULevel* TargetLevel = World->GetCurrentLevel();
AInstancedFoliageActor* IFA = AInstancedFoliageActor::GetInstancedFoliageActorForLevel(TargetLevel, true);
FFoliageMeshInfo* MeshInfo;
UFoliageType* FoliageSettings = IFA->AddFoliageType(FoliageType, &MeshInfo);
GLevelEditorModeTools().ActivateMode(FBuiltinEditorModes::EM_Foliage);
FEdModeFoliage* FoliageEditMode = (FEdModeFoliage*)GLevelEditorModeTools().GetActiveMode(FBuiltinEditorModes::EM_Foliage);
for (int32 InstanceIdx = 0; InstanceIdx < InstancerPartTransforms.Num(); ++InstanceIdx)
{
FTransform InstanceTransform;
FHoudiniEngineUtils::TranslateHapiTransform(InstancerPartTransforms[InstanceIdx], InstanceTransform);
FFoliageInstance Inst;
Inst.Location = InstanceTransform.GetLocation();
Inst.Rotation = InstanceTransform.GetRotation().Rotator();
MeshInfo->AddInstance(IFA, FoliageSettings, Inst, nullptr, true);
}
……
……
InstancedStaticMesh并不支持LOD模式,用来批量放置的植被实体原有的LOD信息也丢失了。这里应该是创建HierarchicalInstancedStaticMeshComponent才能支持LOD。
如何生成HierarchicalInstancedStaticMeshComponent的Actor或BP,可以参考 void UHoudiniAssetInstanceInputField::AddInstanceComponent( int32 VariationIdx )的函数。当Static Mesh有多个LOD时,Houdini Engine会用HierarchicalInstancedStaticMeshComponent替换Instanced Static Mesh
UInstancedStaticMeshComponent * InstancedStaticMeshComponent = nullptr;
if ( StaticMesh->GetNumLODs() > 1 )
{
// If the mesh has LODs, use Hierarchical ISMC
InstancedStaticMeshComponent = NewObject< UHierarchicalInstancedStaticMeshComponent >(
RootComp->GetOwner(), UHierarchicalInstancedStaticMeshComponent::StaticClass(), NAME_None, RF_Transactional);
}
else
{
// If the mesh doesnt have LOD, we can use a regular ISMC
InstancedStaticMeshComponent = NewObject< UInstancedStaticMeshComponent >(
RootComp->GetOwner(),UInstancedStaticMeshComponent::StaticClass(), NAME_None, RF_Transactional );
}
……
……
UE4的Foliage System,其实就是每个Level里有一个AInstancedFoliageActor,每种Foliage Type对应的Instanc Mesh实例都保存在AInstancedFoliageActor的FFoliageMeshInfo里。
(Houdini驱动的UE4植被系统 -- 知乎)
2019年01月30日 15点01分 2
level 5
KnIfER 楼主
i. this is my code that i use to do that
TActorIterator<AInstancedFoliageActor> foliageIterator(GetWorld());
AInstancedFoliageActor* foliageActor = *foliageIterator;
//if you already have foliage in your level, you just need to get the right component, one is created for each type
TArray<UInstancedStaticMeshComponent*> components;
foliageActor->GetComponents<UInstancedStaticMeshComponent>(components);
UInstancedStaticMeshComponent* meshComponent = components[0];
//Now you just need to add instances to component, this example crate 400 instances
FTransform transform = FTransform();
for (int32 x = 1; x < 20; x++)
{
for (int32 y = 1; y < 20; y++)
{
transform.SetLocation(FVector(1000.f * x, 1000.f * y, 0.f));
meshComponent->AddInstance(transform);
}
}
Also, If you need to create the instanced static mesh component too, this is my code that i use
UInstancedStaticMeshComponent* meshComponent = NewObject<UInstancedStaticMeshComponent>(foliageActor, UInstancedStaticMeshComponent::StaticClass(), NAME_None, RF_Transactional);
meshComponent->AttachTo(foliageActor->GetRootComponent());
meshComponent->SetStaticMesh(MyStaticMesh);
meshComponent->RegisterComponent();
Note: you need to inlcude "Runtime/Foliage/Public/InstancedFoliageActor.h"
Note2: one also needs to add Foliage to the PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Foliage"});
(Manually Create Foliage C++ --ue4 answerhub)
2019年01月30日 15点01分 3
1