如何在虚幻引擎4中逐行获取材质

时间:2016-10-31 03:50:20

标签: graphics game-engine material unreal-engine4

我想使用线迹来获取静态网格物体的材质,因为静态网格物体包含多种材质。我通过chaanel设置了复杂的线条跟踪,但是FHitResult没有返回渲染matrial,所以我想使用FHitResult.FaceIndx来获取三角形的材质。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

首先做一个样本光线投射,它击中一个正确的物体,做一个复杂的光线投射并获得目标网格,在复杂的光线投射FHitResult中,我们得到FaceIndex,它意味着我们击中了哪个三角形。 然后我们可以使用FaceIndex查询网格,并获得Section ID(在UE4中,Section是网格单元,一个Scetion使用一种材质,一个Scetion可以使多个三角形存在)。 最后,按部分ID获取材料ID。

FHitResult simpleResult = GetRaycastHitResultSimple(pc, startPos, endPos);
if (simpleResult.bBlockingHit)
{
    UStaticMeshComponent* staticMeshComponent = Cast<UStaticMeshComponent>(simpleResult.GetComponent());
    if (staticMeshComponent)
    {
        UStaticMesh* mesh = staticMeshComponent->StaticMesh;        
        if (mesh)
        {
            FHitResult complexResult = GetRaycastHitResultComplex(pc, startPos, endPos);

            return GetMaterialByFaceIndex(mesh, complexResult.FaceIndex);
        }
        else
        {
            UE_LOG(LogTemp, Warning, TEXT("Get mesh from static mesh component faild"));
        }
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("Cast FHitResul.GetComponent to static mesh component faild"));
    }
}
else
{
    UE_LOG(LogTemp, Warning, TEXT("Simple raycast faild"));
}


int32 UChangeMaterials::GetMaterialByFaceIndex(const UStaticMesh* mesh, const int32& faceIndex)
{
    const FStaticMeshLODResources& lodRes = mesh->GetLODForExport(0);
    int32 totalSection =  lodRes.Sections.Num();

    int32 totalFace = lodRes.GetNumTriangles();
    if (faceIndex > totalFace)
    {
        ///Wrong faceIndex.
        UE_LOG(LogTemp, Warning, TEXT("GetMaterialbyFaceIndex Faild, Wrong faceIndex!"));
        return -1;
    }

    int32 totalTriangleIndex = 0;
    for (int32 sectionIndex = 0; sectionIndex < totalSection; ++sectionIndex)
    {
        FStaticMeshSection currentSection = lodRes.Sections[sectionIndex];
        /*Check for each triangle, so we can know which section our faceIndex in. For Low Performance, do not use it.
        for (int32 triangleIndex = totalTriangleIndex; triangleIndex < (int32)currentSection.NumTriangles + totalTriangleIndex; ++triangleIndex)
        {

            if (faceIndex == triangleIndex)
            {
                //return sectionIndex;
                return currentSection.MaterialIndex;
            }
        }
        totalTriangleIndex += lodRes.Sections[sectionIndex].NumTriangles;
        */

        ///the triangle index is sorted by section, the larger sectionIndex contains larger triangle index, so we can easily calculate which section the faceIndex in.Performance Well.
        int32 triangleIndex = totalTriangleIndex;
        if (faceIndex >= triangleIndex && faceIndex < triangleIndex + (int32)lodRes.Sections[sectionIndex].NumTriangles)
        {
            //return sectionIndex;
            return currentSection.MaterialIndex;
        }
        totalTriangleIndex += lodRes.Sections[sectionIndex].NumTriangles;
    }

    /// did not find the face in the mesh.
    UE_LOG(LogTemp, Warning, TEXT("GetMaterialByFaceIndex, did not find it!"));
    return -2;
}