Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/StateStream/SkinnedMeshStateStreamImpl.cpp
2025-05-18 13:04:45 +08:00

213 lines
7.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SkinnedMeshStateStreamImpl.h"
#include "HAL/PlatformMisc.h"
#include "Rendering/RenderCommandPipes.h"
#include "ScenePrivate.h"
#include "SkeletalMeshSceneProxy.h"
#include "SkeletalRenderPublic.h"
#include "SkinnedMeshSceneProxyDesc.h"
#include "StateStreamCreator.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
FSkinnedMeshObject::~FSkinnedMeshObject()
{
FSceneInterface& Scene = PrimitiveSceneData.SceneProxy->GetScene();
Scene.RemovePrimitive(&PrimitiveSceneDesc);
if (TransformObject)
{
TransformObject->RemoveListener(this);
TransformObject = nullptr;
}
}
void FSkinnedMeshObject::OnTransformObjectDirty()
{
FPrimitiveSceneProxy& Proxy = *PrimitiveSceneData.SceneProxy;
FScene& Scene = static_cast<FScene&>(Proxy.GetScene());
FTransformObject::Info Info = TransformObject->GetInfo();
#if UE_DEBUG_OFFSET_SKINNED_MESH
FTransform Transform = Info.WorldTransform;
Transform.AddToTranslation(FVector(10.0f*DebugIndex, 10.0f*DebugIndex, 0));
#else
const FTransform& Transform = Info.WorldTransform;
#endif
FMatrix Mat = Transform.ToMatrixWithScale();
MeshObject->SetTransform(Mat, Scene.GetFrameNumber());
MeshObject->RefreshClothingTransforms(Mat, Scene.GetFrameNumber());
const FBoxSphereBounds& LocalBounds = Proxy.GetLocalBounds();
FBoxSphereBounds Bounds = LocalBounds.TransformBy(Transform);
FVector ActorPosForRendering(ForceInitToZero);// Proxy.GetActorPositionForRenderer(); TODO This need to be revisited
Scene.UpdatePrimitiveTransform_RenderThread(&Proxy, Bounds, LocalBounds, Mat, ActorPosForRendering, {});
int32 LODLevel = 0;
TArray<FExternalMorphSets> ExternalMorphSets;
ExternalMorphSets.Add({});
FSkinnedMeshSceneProxyDynamicData ProxyData;
ProxyData.ExternalMorphSets = ExternalMorphSets;
ProxyData.ComponentSpaceTransforms = Info.BoneTransforms;
ProxyData.PreviousComponentSpaceTransforms = PrevTransforms;
ProxyData.ComponentWorldTransform = Transform;
ProxyData.PreviousBoneTransformRevisionNumber = BoneTransformRevisionNumber;
ProxyData.CurrentBoneTransformFrame = BoneTransformRevisionNumber;
ProxyData.CurrentBoneTransformRevisionNumber = ++BoneTransformRevisionNumber;
ProxyData.NumLODs = 1;
//TArray<uint8> VisibilityStates;
//VisibilityStates.SetNumUninitialized(Info.BoneTransforms.Num());
//memset(VisibilityStates.GetData(), 1, Info.BoneTransforms.Num());
//ProxyData.BoneVisibilityStates = VisibilityStates;
//ProxyData.PreviousBoneVisibilityStates = VisibilityStates;
MeshObject->Update(LODLevel, ProxyData, &Proxy, SkinnedAsset, FMorphTargetWeightMap(), TArray<float>(), EPreviousBoneTransformUpdateMode::None, FExternalMorphWeightData());
MeshObject->bHasBeenUpdatedAtLeastOnce = true;
PrevTransforms = Info.BoneTransforms;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
FSkinnedMeshStateStreamImpl::FSkinnedMeshStateStreamImpl(FSceneInterface& InScene)
: Scene(InScene)
{
}
void FSkinnedMeshStateStreamImpl::SetTransformObject(FSkinnedMeshObject& Object, const FSkinnedMeshDynamicState& Ds)
{
if (Object.TransformObject)
{
Object.TransformObject->RemoveListener(&Object);
Object.TransformObject = nullptr;
}
const FTransformHandle& TransformHandle = Ds.GetTransform();
if (TransformHandle.IsValid())
{
FTransformObject* TransformObject = static_cast<FTransformObject*>(TransformHandle.Render_GetUserData());
check(TransformObject);
TransformObject->AddListener(&Object);
Object.TransformObject = TransformObject;
}
}
void FSkinnedMeshStateStreamImpl::Render_OnCreate(const FSkinnedMeshStaticState& Ss, const FSkinnedMeshDynamicState& Ds, FSkinnedMeshObject*& UserData, bool IsDestroyedInSameFrame)
{
check(!IsDestroyedInSameFrame);
check(!UserData);
USkinnedAsset* SkinnedAsset = Ds.GetSkinnedAsset();
if (!SkinnedAsset)
{
return;
}
FSkinnedMeshObject& Object = *new FSkinnedMeshObject();
Object.AddRef();
Object.SkinnedAsset = SkinnedAsset;
SetTransformObject(Object, Ds);
check(Object.TransformObject);
FTransformObject::Info Info = Object.TransformObject->GetInfo();
#if UE_DEBUG_OFFSET_SKINNED_MESH
FTransform Transform = Info.WorldTransform;
static uint32 DebugCounter = 0;
Object.DebugIndex = 5;
Transform.AddToTranslation(FVector(10.0f*Object.DebugIndex, 10.0f*Object.DebugIndex, 0));
#else
const FTransform& Transform = Info.WorldTransform;
#endif
FBoxSphereBounds LocalBounds(ForceInitToZero);
if (SkinnedAsset)
{
LocalBounds = SkinnedAsset->GetBounds();
}
Object.PrimitiveSceneDesc.RenderMatrix = Transform.ToMatrixWithScale();
Object.PrimitiveSceneDesc.PrimitiveSceneData = &Object.PrimitiveSceneData;
Object.PrimitiveSceneDesc.LocalBounds = LocalBounds;
Object.PrimitiveSceneDesc.Bounds = LocalBounds.TransformBy(Transform);
FSkinnedMeshSceneProxyDesc Desc;
Desc.SkinnedAsset = SkinnedAsset;
Desc.OverrideMaterials = const_cast<TArray<TObjectPtr<UMaterialInterface>>&>(Ds.GetOverrideMaterials());
Desc.CustomPrimitiveData = &Object.CustomPrimitiveData;
Desc.Scene = &Scene;
Desc.FeatureLevel = Scene.GetFeatureLevel();
Desc.bIsVisible = Info.bVisible;
Desc.bPerBoneMotionBlur = true;
Desc.VisibilityId = -1;
Desc.bReceivesDecals = false;
Desc.bCollisionEnabled = true;
Desc.MaterialRelevance.Raw = Ss.GetMaterialRelevance();
Desc.CastShadow = true;
Desc.bCastDynamicShadow = true;
Desc.bCastStaticShadow = true;
Desc.bCastContactShadow = true;
Desc.bUseAsOccluder = true;
FSkeletalMeshObject* MeshObject = FSkinnedMeshSceneProxyDesc::CreateMeshObject(Desc);
Desc.MeshObject = MeshObject;
Object.MeshObject = MeshObject;
#if WITH_EDITOR
//Desc.TextureStreamingTransformScale = Transform.GetMaximumAxisScale();
#endif
FPrimitiveSceneProxy* SceneProxy = FSkinnedMeshSceneProxyDesc::CreateSceneProxy(Desc, false, 0);
Object.PrimitiveSceneData.SceneProxy = SceneProxy;
SceneProxy->SetPrimitiveColor(FLinearColor::White);
int32 LODLevel = Desc.GetPredictedLODLevel();
TArray<FExternalMorphSets> ExternalMorphSets;
ExternalMorphSets.Add({});
FSkinnedMeshSceneProxyDynamicData ProxyData;
ProxyData.ExternalMorphSets = ExternalMorphSets;
ProxyData.ComponentSpaceTransforms = Info.BoneTransforms;
ProxyData.ComponentWorldTransform = Info.WorldTransform;
MeshObject->Update(LODLevel, ProxyData, SceneProxy, SkinnedAsset, FMorphTargetWeightMap(), TArray<float>(), EPreviousBoneTransformUpdateMode::None, FExternalMorphWeightData());
Scene.AddPrimitive(&Object.PrimitiveSceneDesc);
UserData = &Object;
}
void FSkinnedMeshStateStreamImpl::Render_OnUpdate(const FSkinnedMeshStaticState& Ss, const FSkinnedMeshDynamicState& Ds, FSkinnedMeshObject*& Object)
{
if (!Object)
{
return;
}
if (Ds.TransformModified())
{
SetTransformObject(*Object, Ds);
}
}
void FSkinnedMeshStateStreamImpl::Render_OnDestroy(const FSkinnedMeshStaticState& Ss, const FSkinnedMeshDynamicState& Ds, FSkinnedMeshObject*& Object)
{
if (Object)
{
Object->Release();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
STATESTREAM_CREATOR_INSTANCE_WITH_DEPENDENCY(FSkinnedMeshStateStreamImpl, TransformStateStreamId)
////////////////////////////////////////////////////////////////////////////////////////////////////