2025年Foliage篇-笔刷工具源码分析拓展-允许亲疏关系

Foliage篇-笔刷工具源码分析拓展-允许亲疏关系目录 第九艺术 目录 Version UnrealEngine 4 22 3 做开放大世界的话 初始可以用 ProceduralFo 生成 由于都是随机生成的 之后一般都还会需要很多的细节调整 那就得用到默认的笔刷工具来生成植被了

大家好,我是讯享网,很高兴认识大家。

目录:第九艺术-目录

Version:UnrealEngine 4.22.3

做开放大世界的话,初始可以用ProceduralFoliageSpawner 生成,由于都是随机生成的,之后一般都还会需要很多的细节调整,那就得用到默认的笔刷工具来生成植被了。因此就有了也在笔刷中实现上一篇文章功能的需求,也要在笔刷中允许配置各种Foliage的远近亲疏关系,借同样的需求,熟悉一下默认笔刷的流程。


讯享网

在这里选择Foliage之后,点击要刷的表面。

  1. 调用到 FEdModeFoliage::StartFoliageBrushTrace,开始spawn 满足 UISettings和FoliageType里配置的Instances,这是和 Spawner 一个比较大的区别,用笔刷是可以获取到ActiveTool等Editor信息的,但spawner由于是在之外生成的,就得不到这些信息,之后做一些拓展的时候,会需要考虑到这些区别
  2. 之后调用到 FEdModeFoliage::ApplyBrush,这里会计算你操作工具的压力大小,作为最终生成Instance数量的系数,当然鼠标就是 1 了,然后判断如果是 Paint 工具,就开始生成
  3. 调用到 FEdModeFoliage::AddInstancesForBrush,根据Brush大小,构建这次生成的Buckets,主要用于LandscapeLayer的权重检查,会先查看一下已有的bucket里有多少
  4. 拿到之后,就走到 笔刷和Spawner工具类似的主流程了,调用FEdModeFoliage::AddInstancesImp,逐个生成Instance
  5. 相比Spawner会调用线程安全的 CalculatePotentialInstances_ThreadSafe,笔刷不会多线程,所以直接调用CalculatePotentialInstances
  6. FEdModeFoliage::CalculatePotentialInstances,和spawner类似
    1. FoliageTrace 找到地块
    2. VertexMaskCheck
    3. LandscapeLayerCheck
    4. 满足条件的Instance加到要Spawn的数组
  7. 逐个生成 Instance

如上流程可以看到,之前也说过,在笔刷工具做这个功能的时候,最大的优势就是刷的每种FoliageType都已经可以知道当前地块上有哪些已经放好的 Instance,所以可以直接做距离检查,那就很简单了,只要再最后做各种检查的地方加一个远近亲疏关系的检查就可以了

实现代码如下:

FoliageType里

添加配置结构体,模型和距离,这里可以新加一个,也可以用spawner的

USTRUCT() struct FRelatedFoliageTypeEntry { GENERATED_USTRUCT_BODY() ​ UPROPERTY(EditAnywhere,Category = RelatedFoliage) UStaticMesh* FoliageMesh; ​ UPROPERTY(EditAnywhere,Category = RelatedFoliage) float Radius; };

讯享网

添加属性配置

讯享网 UPROPERTY(EditAnywhere, Category = Custom) TArray<FRelatedFoliageTypeEntry> CloseToFoliages; ​ UPROPERTY(EditAnywhere, Category = Custom) TArray<FRelatedFoliageTypeEntry> FarFromFoliages;

添加 距离检查的方法 RelatedFoliageTypesCheck,逻辑很简单

static bool CheckForOverlappingSphere(AInstancedFoliageActor* IFA, const UStaticMesh* Mesh, const FSphere& Sphere) { if (IFA) { TArray<const UFoliageType*> MeshFoliageTypes; IFA->GetAllFoliageTypesForSource(Mesh, MeshFoliageTypes); for (int i = 0; i < MeshFoliageTypes.Num(); ++i) { if (CheckForOverlappingSphere(IFA, MeshFoliageTypes[i], Sphere)) return true; } } ​ return false; } ​ bool RelatedFoliageTypesCheck(const FHitResult& Hit, const UFoliageType* Settings) { if (!Settings) return false; ​ if (Settings->CloseToFoliages.Num() == 0 && Settings->FarFromFoliages.Num() == 0) return true; ​ AInstancedFoliageActor* IFA = AInstancedFoliageActor::GetInstancedFoliageActorForLevel(Hit.Component->GetComponentLevel(),false); if (!IFA) { if (Settings->CloseToFoliages.Num()) return false; ​ return true; } ​ for (int i = 0; i < Settings->CloseToFoliages.Num(); ++i) { if (Settings->CloseToFoliages[i].FoliageMesh && Settings->GetSource() != Settings->CloseToFoliages[i].FoliageMesh && Settings->CloseToFoliages[i].Radius > 0) { if (!CheckForOverlappingSphere(IFA, Settings->CloseToFoliages[i].FoliageMesh, FSphere(Hit.Location, Settings->CloseToFoliages[i].Radius))) return false; } } for (int i = 0; i < Settings->FarFromFoliages.Num(); ++i) { if (Settings->FarFromFoliages[i].FoliageMesh && Settings->GetSource() != Settings->FarFromFoliages[i].FoliageMesh && Settings->FarFromFoliages[i].Radius > 0) { if (CheckForOverlappingSphere(IFA, Settings->FarFromFoliages[i].FoliageMesh, FSphere(Hit.Location, Settings->FarFromFoliages[i].Radius))) return false; } } return true; }

最后就是调用了,在最后 CalculatePotentialInstances 和 CalculatePotentialInstances_ThreadSafe 里面都加上这个判断

类似

讯享网const bool bValidInstance = CheckLocationForPotentialInstance_ThreadSafe(Settings, Hit.ImpactPoint, Hit.ImpactNormal) && VertexMaskCheck(Hit, Settings) && LandscapeLayerCheck(Hit, Settings, LocalCache, HitWeight) && RelatedFoliageTypesCheck(Hit, Settings)//多加了这一句
小讯
上一篇 2025-01-11 11:51
下一篇 2025-04-07 18:39

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/122015.html