介绍
在开发的过程中遇到了一个问题,如何快速且方便的通过点击模型的某一个位置,获得这个位置的 UV
。
一开始翻源码没看到,所以我本想自己造一个轮子的,大概想法就是,我点击的时候获取当前三角面索引。
此时可以获得三角面的三个顶点,那么我根据这三个顶点的位置与他们的 UV
,和我自己点击的位置进行重心坐标差值求出我点击位置的 UV
坐标。
由于我知道三角形索引,所以完全可以认为我点击的位置在三角形里面,既然每个顶点有UV坐标与其真正的坐标,那么就可以方便的计算出我点的点的 UV
坐标。
不过等我准备开始造轮子的时候,还是发现了原来 UE 有这玩意儿。
UFUNCTION(BlueprintPure, Category = "Collision")
static ENGINE_API bool FindCollisionUV(const struct FHitResult& Hit, int32 UVChannel, FVector2D& UV);
也就是你这位,他通过 FHitResult
返回的 FaceIndex
,也就是说 TriIndex
,来计算一个 UV 位置。
而且我发现我的想法和他几乎一致,那就可以直接复用了。
本来我很惊喜,结果发现 FHitResult
中 FaceIndex
返回的结果是 -1
,这肯定是不对的,如果点击空气的话是 0
(在复杂检测开启的情况下)。
所以我又去看源码了,首先我去项目设置面板中勾选了
这个东西,让 FindCollisionUV
函数可以正常的工作。
接下来我发现,FaceIndex
是 -1
的原因是,UE帮你封装的时候默认的 FCollisionQueryParams
对象中的 bool bReturnFaceIndex;
是关闭的!
/** Whether we want to return the triangle face index for complex static mesh traces */
bool bReturnFaceIndex;
这不对吧,你把这个封死了我怎么用啊,所以我找到了支持 FCollisionQueryParams 传入的最后一层函数,手动将 bReturnFaceIndex 勾选了。
bool TemplateClass::TemplateFunction(const UObject* WorldContextObject, const ECollisionChannel TraceChannel, FHitResult& OutResult)
{
// Get your controller and Mouse Pos.
// ...
FCollisionQueryParams CollisionQueryParams(SCENE_QUERY_STAT(ClickableTrace), true);
CollisionQueryParams.bReturnFaceIndex = true;
const bool Result = Controller->GetHitResultAtScreenPosition(FVector2d(MouseX, MouseY), TraceChannel, CollisionQueryParams, OutResult);
return Result;
}
如此一来,就可以非常合理的得到位置的 UV
坐标了,就和 SP
直接绘制一样。
接下来就是喜闻乐见的调库环节,你只需要用你自己修改过射线检测函数,就能正确的返回 FaceIndex
,并把 HitResult
交给 FindCollisionUV
,你就能获得正确的 UV 坐标了。