首页 > 其他分享 >UE4之StaticMesh和SkeletalMesh类关系图

UE4之StaticMesh和SkeletalMesh类关系图

时间:2024-04-27 22:12:54浏览次数:23  
标签:SkelMeshRenderData int32 MeshObject LOD SceneFeatureLevel StaticMesh UE4 Skeleta

StaticMesh类关系图

StaticMesh渲染数据结构

 

SkeletalMesh类关系图

 

USkinnedMeshComponent::CreateRenderState_Concurrent函数

void USkinnedMeshComponent::CreateRenderState_Concurrent(FRegisterComponentContext* Context)
{
    LLM_SCOPE(ELLMTag::SkeletalMesh);

    if( SkeletalMesh )
    {
        // Attempting to track down UE-45505, where it looks as if somehow a skeletal mesh component's mesh has only been partially loaded, causing a mismatch in the LOD arrays
        checkf(!SkeletalMesh->HasAnyFlags(RF_NeedLoad | RF_NeedPostLoad | RF_NeedPostLoadSubobjects | RF_WillBeLoaded), TEXT("Attempting to create render state for a skeletal mesh that is is not fully loaded. Mesh: %s"), *SkeletalMesh->GetName());

        // Initialize the alternate weight tracks if present BEFORE creating the new mesh object
        InitLODInfos();

        // No need to create the mesh object if we aren't actually rendering anything (see UPrimitiveComponent::Attach)
        if ( FApp::CanEverRender() && ShouldComponentAddToScene() )
        {
            ERHIFeatureLevel::Type SceneFeatureLevel = GetWorld()->FeatureLevel;
            FSkeletalMeshRenderData* SkelMeshRenderData = SkeletalMesh->GetResourceForRendering();
            int32 MinLODIndex = ComputeMinLOD();
            
#if DO_CHECK
            for (int LODIndex = MinLODIndex; LODIndex < SkelMeshRenderData->LODRenderData.Num(); LODIndex++)
            {
                FSkeletalMeshLODRenderData& LODData = SkelMeshRenderData->LODRenderData[LODIndex];
                const FPositionVertexBuffer* PositionVertexBufferPtr = &LODData.StaticVertexBuffers.PositionVertexBuffer;
                if (!PositionVertexBufferPtr || (PositionVertexBufferPtr->GetNumVertices() <= 0))
                {
                    UE_LOG(LogSkinnedMeshComp, Warning, TEXT("Invalid Lod %i for Rendering Asset: %s"), LODIndex, *SkeletalMesh->GetFullName());
                }
            }
#endif
    
            // Also check if skeletal mesh has too many bones/chunk for GPU skinning.
            if (bRenderStatic)
            {
                // GPU skin vertex buffer + LocalVertexFactory
                MeshObject = ::new FSkeletalMeshObjectStatic(this, SkelMeshRenderData, SceneFeatureLevel); 
            }
            else if(ShouldCPUSkin())
            {
                MeshObject = ::new FSkeletalMeshObjectCPUSkin(this, SkelMeshRenderData, SceneFeatureLevel);
            }
            // don't silently enable CPU skinning for unsupported meshes, just do not render them, so their absence can be noticed and fixed
            else if (!SkelMeshRenderData->RequiresCPUSkinning(SceneFeatureLevel, MinLODIndex)) 
            {
                MeshObject = ::new FSkeletalMeshObjectGPUSkin(this, SkelMeshRenderData, SceneFeatureLevel);
            }
            else
            {
                int32 MaxBonesPerChunk = SkelMeshRenderData->GetMaxBonesPerSection(MinLODIndex);
                int32 MaxSupportedGPUSkinBones = FMath::Min(GetFeatureLevelMaxNumberOfBones(SceneFeatureLevel), FGPUBaseSkinVertexFactory::GetMaxGPUSkinBones());
                int32 NumBoneInfluences = SkelMeshRenderData->GetNumBoneInfluences(MinLODIndex);
                FString FeatureLevelName; GetFeatureLevelName(SceneFeatureLevel, FeatureLevelName);

                UE_LOG(LogSkinnedMeshComp, Warning, TEXT("SkeletalMesh %s, is not supported for current feature level (%s) and will not be rendered. MinLOD %d, NumBones %d (supported %d), NumBoneInfluences: %d"), 
                    *GetNameSafe(SkeletalMesh), *FeatureLevelName, MinLODIndex, MaxBonesPerChunk, MaxSupportedGPUSkinBones, NumBoneInfluences);
            }

            //Allow the editor a chance to manipulate it before its added to the scene
            PostInitMeshObject(MeshObject);
        }
    }

    Super::CreateRenderState_Concurrent(Context);

    if (SkeletalMesh)
    {
        // Update dynamic data

        if(MeshObject)
        {
            // Clamp LOD within the VALID range
            // This is just to re-verify if LOD is WITHIN the valid range
            // Do not replace this with UpdateLODStatus, which could change the LOD 
            //    without animated, causing random skinning issues
            // This can happen if your MinLOD is not valid anymore after loading
            // which causes meshes to be invisible
            {
                int32 MinLodIndex = ComputeMinLOD();
                int32 MaxLODIndex = MeshObject->GetSkeletalMeshRenderData().LODRenderData.Num() - 1;
                PredictedLODLevel = FMath::Clamp(PredictedLODLevel, MinLodIndex, MaxLODIndex);
            }

            // If we have a valid LOD, set up required data, during reimport we may try to create data before we have all the LODs
            // imported, in that case we skip until we have all the LODs
            if(SkeletalMesh->IsValidLODIndex(PredictedLODLevel))
            {
                const bool bMorphTargetsAllowed = CVarEnableMorphTargets.GetValueOnAnyThread(true) != 0;

                // Are morph targets disabled for this LOD?
                if (bDisableMorphTarget || !bMorphTargetsAllowed)
                {
                    ActiveMorphTargets.Empty();
                }

                MeshObject->Update(PredictedLODLevel, this, ActiveMorphTargets, MorphTargetWeights, EPreviousBoneTransformUpdateMode::UpdatePrevious);  // send to rendering thread
            }
        }

        // scene proxy update of material usage based on active morphs
        UpdateMorphMaterialUsageOnProxy();
    }
}

 

勾选Render Static,会走FSkeletalMeshObjectStatic逻辑:

 

SkeletalMesh渲染数据结构(SkeletalMesh)

 

SkeletalMesh渲染数据结构(FSkeletalMeshObject)

 

标签:SkelMeshRenderData,int32,MeshObject,LOD,SceneFeatureLevel,StaticMesh,UE4,Skeleta
From: https://www.cnblogs.com/kekec/p/18158948

相关文章

  • UE4 寻路
    寻路就是对图的遍历,目前主要处理对可转换为二维矩阵的方格图遍历DFS与BFS两种最基础的遍历方式,DFS采用回溯思想,将从起点开始沿着一个方向搜索,直到超出界限(回溯)或者到达目的地(返回结果)//只考虑上下左右四个方向vector<vector<pair{int,int}>>res;vector<pair{int,int}......
  • SkeletalMesh之MorphTargets技术
    利用变形目标(MorphTargets)可以将网格体从基础形状变为目标形状。通常它们将作为动画系统的一部分与SkeletalMesh一同使用。 导入含有MorphTargets数据的SkeletalMesh 预览SkeletalMesh的MorphTargets效果 在AnimationSequence中添加MorphTarges数值的控制  ......
  • UE4纯C++实现游戏中快捷栏之创建快捷栏UI
    作为一个在游戏界面中显示的快捷栏,我们需要在游戏运行时就显示出快捷栏UI,故我们创建两个Widget。1.SlAiGameHUDWidget:负责游戏中界面UI的整体显示2.SlAiShortcutWidget:负责快捷栏部件的显示与逻辑然后我们通过:1.将GameHUDWidget添加进视口:在GameHUD文件中添加Game......
  • "(UE4Editor.exe中)处有未经处理的异常:0xC0000005:读取位置0x0000000000000000时发生
    报错情况:使用ue4.27Slate编写Widget时想通过获取Worl(通过本地PlayerController获取)来实现“设置定时任务为在音乐结束后自动触发函数”的功能ps:定时执行函数代码 解决方法:使用GWorld替换掉通过第0号PlayerController获取世界 原因分析:(由于本人校验较少,暂做以下估计)在......
  • UE4 iOS打印出所有线程的调用栈
    在Xcode15.2中调试UE4游戏(Development包),执行btall打印出所有线程(共116个线程)的调用堆栈*thread#1,queue='com.apple.main-thread',stopreason=signalSIGSTOP*frame#0:0x00000001f9c7d178libsystem_kernel.dylib`mach_msg2_trap+8frame#1:0x00000001f......
  • UE4 c++ 通过枚举寻找DataTable中的数据
    DataTable中的数据DataTable中每一行数据是一个结构体在C++代码中定义结构体,然后可以在蓝图中可以创建以此结构体为单元的DataTable枚举变量定义一个头文件来存储枚举变量,然后可以在要使用的文件中利用MyEnumPtr=FindObject<UEnum>(ANY_PACKAGE,TEXT("EGridShapEnum"),tr......
  • UE4 C++ Widget的NativeConstruct 与 NativePreConstruct
    构造函数由于Widget是由UE的反射系统创建的,其生命周期由UE引擎管理,所以并不存在构造函数,UE为Widget类定义了两个虚函数NativeConstruct与NativePreConstruct来充当构造函数的作用。而这两个函数的调用都必须在Widget被实例化之后才能进行调用如何在Widget中获取角色在蓝图节......
  • UE4 存档
    基本目标:存档按键TAB保存P键显示读档界面读档后位置重置到读档内容存档界面关于每一条信息的变量和读取按钮点击事件存档存档主要的逻辑是存到内存中并存到本地显示的就是内存中的打开关卡时加载本地到内存其实整个保存的目前只是一个Location,应该封装成对象比较好,......
  • UE4.27, 代码实践, 资源加载 FSoftClassPath / FSoftObjectPath
    //以下的FSoftClassPath/FSoftObjectPath都公开在Editor里设定 //iteminTArray<FSoftClassPath>FSoftClassPathtemp=FSoftClassPath_UsedInBluePrint_BuildFunc(item);UClass*LoadedClass=temp.TryLoadClass<AActor>();FSoftClassPathFSoftClassPath_UsedInBlu......
  • UE4 UI
    2DUI点击后控制权切换制作2DUIDesignerGraph在关卡蓝图/控制器类中使用UI【一般是控制器类】效果暂停游戏制作UI暂停游戏点击事件增添UI动画3DUI全自动/半自动制作UI添加点击事件制作UI蓝图类并连接到UI上增加WidgetInteraction设置一个对外的......