Houdini技术体系 基础管线(四) :Houdini驱动的UE4植被系统 下篇
背景

- 开发效率方面,这个方案并不支持UE4的Foliage Mode Editor:
- 每个植被区域都被Bake成BP的形式,场景美术规划阶段就需要格外小心防止区域之间穿插造成植被之间的叠加
- 当出现比较大的改动需求时,一个BP的范围发生改动就会造成大量BP重新生成的连锁反映。
- 就像地形生成一样,完全的自动化并不现实,美术需要能通过UE4传统手绘方式来进行修改植被的方式。
- 一个区域的BP植被需要重新生成时,还要重新绘制一遍之前的生成区域,这个过程除非预先保存,否则很难完全重现上次绘制的区域。
- 运行效率优化方面,同一类的Instance并不能放到一个InstancedStaticMeshComponent 这样必定会造成一定程度的性能损耗

- Houdini Input要增加FoliageType的选项,生成实例的对象不再是用Statice Mesh,而是UE4的Foliage Type
- Houdini Output直接输出植被实例不再Bake到BP里,而是直接Add到UE4的Foliage System的Foliage Instance里
Houdini Input对FoliageType的选项支持

namespace EHoudiniAssetInputType
{
enum Enum
{
GeometryInput = 0,
AssetInput,
CurveInput,
LandscapeInput,
FoliageTypeInput, // Add foliage type input
WorldInput
};
}
InParam.ChoiceIndex == EHoudiniAssetInputType::GeometryInput
for ( int32 Ix = 0; Ix < NumInputs; Ix++ )
{
UObject* InputObject = InParam.GetInputObject( Ix );
//Helper_CreateGeometryWidget( InParam, Ix, InputObject, AssetThumbnailPool, VerticalBox );
Helper_CreateFoliageWidget(InParam, Ix, InputObject, AssetThumbnailPool, VerticalBox);
}
SNew( SAssetDropTarget )
.OnIsAssetAcceptableForDrop( SAssetDropTarget::FIsAssetAcceptableForDrop::CreateLambda(
[]( const UObject* InObject ) {
return InObject && InObject->IsA< /*UStaticMesh*/ UFoliageType >();

if (UFoliageType_InstancedStaticMesh * InputFoliageType = Cast<UFoliageType_InstancedStaticMesh>(InputObjects[InputIdx]))
{
UStaticMesh* InputStaticMesh = InputFoliageType->GetStaticMesh();
// Creating an Input Node for Static Mesh Data
if (!HapiCreateInputNodeForStaticMesh(InputStaticMesh, MeshAssetNodeId, OutCreatedNodeIds, nullptr, bExportAllLODs, bExportSockets))
{
HOUDINI_LOG_WARNING(TEXT("Error creating input index %d on %d"), InputIdx, ConnectedAssetId);
}
SelectInputFoliageTypeArray.Add(InputFoliageType);
}

Houdini Output与Foliage Editor的关联
- Houdini输出的Entity Point Cloud所对应的Instance可以直接Add到UE4的Foliage System里。
- 美术可以通过绘制区域来对已经生成部分再次做过程化生成,或者直接利用FoliageEdit手绘的方式来进行迭代调整。
- 手绘调整部分和Houdini自动化生成部分可以分Layer保存,可以根据情况选择自动生成部分是否影响到手工调整部分。
#if WITH_EDITOR
if ( FHoudiniEngineUtils::IsHoudiniNodeValid( AssetId ) )
{
// Create necessary instance inputs.
CreateInstanceInputs( FoundInstancers ); // Create necessary curves.
CreateCurves( FoundCurves ); // Create necessary landscapes
CreateAllLandscapes( FoundVolumes );
}
#endif
for ( const FHoudiniGeoPartObject& GeoPart : Instancers )
{
HoudiniAssetInstanceInput->CreateInstanceInput();
}
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);
}

ULandscapeComponent* SelectLandscapeComponent = FHoudiniLandscapeUtils::SelectLandscapeComponentArray[Index];
int32 MinX = MAX_int32;
int32 MinY = MAX_int32;
int32 MaxX = -MAX_int32;
SelectLandscapeComponent->GetComponentExtent(MinX, MinY, MaxX, MaxY); ULandscapeInfo* LandscapeInfo = SelectLandscapeComponent->GetLandscapeProxy()->GetLandscapeInfo();
for (int32 X = MinX; X <= MaxX; X++)
{
for (int32 Y = MinY; Y <= MaxY; Y++)
{
float RegionSelect = LandscapeInfo->SelectedRegion.FindRef(FIntPoint(X, Y));
if (RegionSelect > 0)
{
SelectRegionNum++;
FBoxSphereBounds ComponentBounds =
SelectLandscapeComponent->CalcBounds(SelectLandscapeComponent->GetComponentTransform()); FBox CachedLocalBox;
CachedLocalBox.Min = FVector(X, Y, 0);
CachedLocalBox.Max = FVector(X+1, Y+1, 0);
CachedLocalBox.IsValid = 1;
FBox MyBounds = CachedLocalBox.TransformBy(SelectLandscapeComponent->GetLandscapeProxy()->
GetLandscapeActor()->GetActorTransform());
MyBounds.Max.Z = ComponentBounds.GetBox().Max.Z ;
MyBounds.Min.Z = ComponentBounds.GetBox().Min.Z ;
FBoxSphereBounds RegionBounds = FBoxSphereBounds(MyBounds);
auto TempInstances = MeshInfo->InstanceHash->GetInstancesOverlappingBox(RegionBounds.GetBox());
for (int32 Idx : TempInstances)
{
if(InInstancesToRemove.Find(Idx) == INDEX_NONE)
InInstancesToRemove.Add(Idx);
}
}
}
}
MeshInfo->RemoveInstances(IFA, InInstancesToRemove, true);


TMap<UFoliageType*, FFoliageMeshInfo*> InstancesFoliageType = IFA->GetAllInstancesFoliageType(); for (auto& MeshPair : InstancesFoliageType)
{
FFoliageMeshInfo* MeshInfo = MeshPair.Value;
UFoliageType* FoliageSettings = MeshPair.Key;
}
GrassType的对应


总结


Houdini技术体系 基础管线(四) :Houdini驱动的UE4植被系统 下篇的更多相关文章
- Houdini技术体系 基础管线(三) :UE4 Landscape Component的多选支持 下篇
背景 上篇中,我们介绍了如何修改Houdini Enigne来设置单个Landscape Compnent的Height和Layer的数据,但原生Houdini Engine并不支持多选Compone ...
- Houdini技术体系 基础管线(三) :UE4以选择区域的方式对地形做生成和更新 上篇
背景 前一节里,解决了Houdini地形无缝导入到UE4的流程问题.但这种方法也有它的局限性,在实际游戏项目里,LA和LD还是偏向在游戏引擎编辑器里工作,他们的一些设计也会影响到地形的信息,那 ...
- Houdini技术体系 基础管线(四) :Houdini驱动的UE4植被系统 上篇
背景 之前在<Houdini技术体系 过程化地形系统(一):Far Cry5的植被系统分析>一文中已经对AAA游戏中过程化植被的需求有了一定的定义,后续工作就是如何用Houdini开发功能 ...
- Houdini技术体系 基础管线(一) : Houdini与Houdini Engine的安装
Houdini 下载与安装 在官网 https://www.sidefx.com/download/ 下载最新的Production Build 版本,当前是16.5版本,需要注册帐号 PS:公司内网 ...
- Houdini技术体系 基础管线(二) :Heightfiled与UE4的无缝导入以及对World Composition的支持
Authored by TraceYang 前言 传统的制作做比较真实大世界3D关卡地形时,通常的采用的方式是把HeightMap和SplatMap(Layer Mask)导入到引擎的地形系统里 ...
- Houdini技术体系 过程化地形系统(一):Far Cry5的植被系统分析
背景 在大世界游戏里,植被(biome)是自然环境非常重要的组成部分,虽然UE4里的也有比较不错的地形+植被系统,但相比国外AAA级游戏的效果,还是有不少的差距,简介如下: UE4的植被分为( ...
- 01-java技术体系基础
java体系基础 理论 编程语言: 系统级: C, C++, go, erlang ... 应用级: C#, Java, Python, Perl, Ruby, php 虚拟机: jvm(java虚拟 ...
- Houdini技术体系大纲
Houdini for UE4 Pipeline的系列教程,前言等想好再写吧
- 测试需要了解的技术之基础篇四__UI自动化测试体系
UI自动化测试体系 1.Andriod 自动化测试:Appium 环境安装与架构介绍.Appium Desktop用例录制.Appium测试用例流程.元素定位方法 IA/AID/XPATH/UISel ...
随机推荐
- Emgucv - 下载、安装、配置
工欲善其事,必先利其器. 一.下载 Emgucv学习之前,我们先要搭建好开发环-Emgucv库.VS开发平台. (1)VS开发平台,个人觉得VS2015挺好用的,比如:自定义窗口布局.更优的代码编辑器 ...
- BZOJ2670 : Almost
求出前缀和$s[]$,那么区间$[l,r]$的几乎平均数$=\frac{s[r]-s[l-1]}{r-l}$. 若只有一个询问,那么可以维护$(i,s[i-1])$的凸壳,在凸壳上二分点$(i,s[i ...
- itchat分析微信好友的个性签名
itchat分析微信好友的个性签名 itchat是一个开源的微信个人号python接口(公众号.企业号接口为itchatmp).使用它可以非常优雅地操纵个人微信号.文档链接 七夕到了,博主也要自娱自乐 ...
- CSS Flex布局整理
Flex布局 display: flex; 将对象作为弹性伸缩盒展示,用于块级元素 display: inline-flex; 将对象作为弹性伸缩盒展示,用于行内元素 注意兼容问题: webkit内核 ...
- Gird Layout代码解释
<div class="wrapper"> <!--定义一个类名为wrapper的div盒子--> <div class="one" ...
- python部分面试- 测试维度
2. 软件测试的维度 1. 正确性:功能 正确 2. 健壮性: 意外的输入,不会崩溃 3. 性能: 大压力, 依然能工作 4. 可靠性: 长时间,不会崩溃 5. 易用性: 目标客户,都易用 6. 安全 ...
- C#轻量级配置文件组件EasyJsonConfig
一.课程介绍 一.本次分享课程<C#轻量级配置文件EasyJsonConfig>适合人群如下: 1.有一定的NET开发基础. 2.喜欢阿笨的干货分享课程的童鞋们. 二.今天我们要如何优雅解 ...
- An entry point cannot be marked with the 'async' modifier
I copied below code from this link.But when I am compiling this code I am getting an entry point can ...
- Spring Boot中使用Swagger2自动构建API文档
由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这 ...
- windows10创建ftp服务器
1.创建用户 2.创建FTP服务 3.开通防火墙服务 建立端口21,20入站规则 4.访问测试