From c8f78d712a152d8fb10682b2d57a7181ad14d1ee Mon Sep 17 00:00:00 2001 From: BlueRose <378100977@qq.com> Date: Wed, 30 Oct 2024 19:11:55 +0800 Subject: [PATCH] vault backup: 2024-10-30 19:11:55 --- .../various-complements/histories.json | 2 +- 01-Diary/周小结/2024.10.md | 3 +- 02-Note/DAWA/ASoul/动画相关/动捕逻辑.md | 134 ++++++++++++++++-- 3 files changed, 129 insertions(+), 10 deletions(-) diff --git a/.obsidian/plugins/various-complements/histories.json b/.obsidian/plugins/various-complements/histories.json index 30df8a2..1d31b03 100644 --- a/.obsidian/plugins/various-complements/histories.json +++ b/.obsidian/plugins/various-complements/histories.json @@ -1 +1 @@ -{"582020846":{"582020846":{"currentFile":{"count":1,"lastUpdated":1727792069567}}},"根据bComputeExport,分别使用RDG的ComputeShader与PixelShader输出DepthStencil。":{"根据bComputeExport,分别使用RDG的ComputeShader与PixelShader输出DepthStencil。":{"currentFile":{"count":1,"lastUpdated":1727249472660}}},"MeshDraw":{"MeshDraw":{"internalLink":{"count":1,"lastUpdated":1727260163677}}},"实现了一个在屏幕空间宽度恒定的":{"实现了一个在屏幕空间宽度恒定的":{"currentFile":{"count":1,"lastUpdated":1728700795488}}},"TsDirectorCamManagerActor":{"TsDirectorCamManagerActor":{"currentFile":{"count":1,"lastUpdated":1729139925413}}},"Bloom":{"Bloom":{"currentFile":{"count":1,"lastUpdated":1729490733473}}},"FBloomFinalizeApplyConstantsCS":{"FBloomFinalizeApplyConstantsCS":{"currentFile":{"count":1,"lastUpdated":1729584275683}}},"解决NaiLin高跟":{"解决NaiLin高跟":{"currentFile":{"count":1,"lastUpdated":1729587089926}}},"优化项目举例,参与多个项目。":{"优化项目举例,参与多个项目。":{"currentFile":{"count":1,"lastUpdated":1729696025968}}},"制作各种编辑器工具":{"制作各种编辑器工具":{"currentFile":{"count":1,"lastUpdated":1729696038138}}}} \ No newline at end of file +{"582020846":{"582020846":{"currentFile":{"count":1,"lastUpdated":1727792069567}}},"实现了一个在屏幕空间宽度恒定的":{"实现了一个在屏幕空间宽度恒定的":{"currentFile":{"count":1,"lastUpdated":1728700795488}}},"TsDirectorCamManagerActor":{"TsDirectorCamManagerActor":{"currentFile":{"count":1,"lastUpdated":1729139925413}}},"Bloom":{"Bloom":{"currentFile":{"count":1,"lastUpdated":1729490733473}}},"FBloomFinalizeApplyConstantsCS":{"FBloomFinalizeApplyConstantsCS":{"currentFile":{"count":1,"lastUpdated":1729584275683}}},"解决NaiLin高跟":{"解决NaiLin高跟":{"currentFile":{"count":1,"lastUpdated":1729587089926}}},"优化项目举例,参与多个项目。":{"优化项目举例,参与多个项目。":{"currentFile":{"count":1,"lastUpdated":1729696025968}}},"制作各种编辑器工具":{"制作各种编辑器工具":{"currentFile":{"count":1,"lastUpdated":1729696038138}}},"RigidBodyIndex":{"RigidBodyIndex":{"currentFile":{"count":1,"lastUpdated":1730280351906}}}} \ No newline at end of file diff --git a/01-Diary/周小结/2024.10.md b/01-Diary/周小结/2024.10.md index 00eb56c..3c404e9 100644 --- a/01-Diary/周小结/2024.10.md +++ b/01-Diary/周小结/2024.10.md @@ -19,4 +19,5 @@ 2. 2024心仪生日会 1. 添加心仪呆毛以及物理效果。 3. 解决新棚手柄输入反应慢的问题。 -4. 解决 道具新投影仪播放节目会有拖影的问题。 \ No newline at end of file +4. 解决 道具新投影仪播放节目会有拖影的问题。 +5. 解决 2套嘉然衣服无法接收到动捕数据的问题。 \ No newline at end of file diff --git a/02-Note/DAWA/ASoul/动画相关/动捕逻辑.md b/02-Note/DAWA/ASoul/动画相关/动捕逻辑.md index 72e7be8..a5df94c 100644 --- a/02-Note/DAWA/ASoul/动画相关/动捕逻辑.md +++ b/02-Note/DAWA/ASoul/动画相关/动捕逻辑.md @@ -36,6 +36,16 @@ void AChingmuMocapReceiverActor::BeginPlay() } ``` + FChingmuThread::Run()中处理完[[#ST_MocapFrameData]]之后,将几个演员动补数据存入FrameQueue之后。在Tick()出队,之后数据存入AllHumanFrames/AllRigidBodyFrames。 + +- AllHumanFrames + - ID + - std::vector Frames + - ID + - TimeStamp + - FrameIndex + - BonesWorldPos + - BonesLocalRot ```c++ void AChingmuMocapReceiverActor::Tick(float DeltaTime) @@ -46,17 +56,17 @@ void AChingmuMocapReceiverActor::Tick(float DeltaTime) { Sender = GetMotionSender(); } - const auto CurTime = ULiveDirectorStatics::GetUnixTime(); + const auto CurTime = ULiveDirectorStatics::GetUnixTime();//获取当前系统时间 if(UseThread) { // 线程方式 // 在数据队列中获取青瞳数据 - while (!FrameQueue.IsEmpty()) + while (!FrameQueue.IsEmpty())//处理完所有 { ST_MocapFrameData* Frame; - if (FrameQueue.Dequeue(Frame)) + if (FrameQueue.Dequeue(Frame))//出队 { - PutMocapDataIntoFrameList(Frame); + PutMocapDataIntoFrameList(Frame);//将帧数数据塞入对应HuamnID/RigidBodyID的AllHumanFrames/AllRigidBodyFrames中。 } } } @@ -76,19 +86,125 @@ void AChingmuMocapReceiverActor::Tick(float DeltaTime) } ``` +### 采样相关逻辑 +- ***SampleByTimeStamp***() ```c++ void AChingmuMocapReceiverActor::DoSample(TArray& Frames) { for (auto i = 0; i < Frames.Num(); i++) { - Frames[i]->CheckSize(CacheLimit); - if (SampleByTimeStamp(Frames[i]->Frames)) + Frames[i]->CheckSize(CacheLimit);//判断当前帧数据是否超过指定长度(240帧,2~4秒数据),移除超出长度的数据。 + if (SampleByTimeStamp(Frames[i]->Frames))//对数据进行插值,当前插值数据存在SampledHumanData。 { - SendFrameToCharacter(); + SendFrameToCharacter();//执行对应的TsChingmuMocapReceiverActor.ts中的逻辑,主要是触发一个事件,讲数据传递给TsMotionRetargetComponent.ts 或者 TsSceneLiveLinkPropActor.ts(动捕道具) } } } + +class MocapFrames +{ +public: + int ID; + std::vector Frames = {}; + +public: + MocapFrames(): ID(0) + { + } + + bool CheckSize(const int Limit) + { + if (Frames.size() > Limit) + { + const int DeletedCount = Frames.size() / 2; + for (auto i = 0; i < DeletedCount; i++) + { + auto Data = Frames[i]; + if (Data) + { + delete Data; + } + Data = nullptr; + } + Frames.erase(Frames.cbegin(), Frames.cbegin() + DeletedCount); + return true; + } + return false; + } +}; ``` + +对数据进行插值,当前插值数据存在**SampledHumanData**。 +```c++ +bool AChingmuMocapReceiverActor::SampleByTimeStamp(std::vector& DataList) +{ + const int64 SampleTime = ULiveDirectorStatics::GetUnixTime() - UMotionUtils::BackSampleTime;//UMotionUtils::BackSampleTime = 100ms,采样100ms的数据。 + int Previous = -1; + int Next = -1; + for (int Index = DataList.size() - 1; Index > 0; Index--)//从Last => First遍历所有数据,确定插值的2个数据Index。 + { + const ST_MocapFrameData* Data = DataList[Index]; + if (Data == nullptr) + { + continue; + } + if (Data->TimeStamp - SampleTime > 0) + { + Next = Index; + } + else + { + Previous = Index; + break; + } + } + + if (bShowSampleLog) + { + UE_LOG(LogTemp, Warning, TEXT("prev: %d, next: %d, total: %llu"), Previous, Next, DataList.size()); + } + if (Previous != -1 && Next != -1) + { + const auto p = DataList[Previous]; + const auto n = DataList[Next]; + const float Factor = (n->TimeStamp - p->TimeStamp) > 0 + ? (1.0 * (SampleTime - p->TimeStamp) / (n->TimeStamp - p->TimeStamp)) + : 1.0; + // Bone world pos cannot lerp like this + // It will cause bone length changes all the time + SampledHumanData->ID = p->ID; + SampledHumanData->TimeStamp = SampleTime; + SampledHumanData->FrameIndex = p->FrameIndex; + for (auto Index = 0; Index < 23; Index++)//对23个骨骼进行差值。 + { + SampledHumanData->BonesWorldPos[Index] = UKismetMathLibrary::VLerp( + p->BonesWorldPos[Index], n->BonesWorldPos[Index], Factor); + SampledHumanData->BonesLocalRot[Index] = UKismetMathLibrary::RLerp(p->BonesLocalRot[Index].Rotator(), + n->BonesLocalRot[Index].Rotator(), + Factor, true).Quaternion(); + } + return true; + } + if (Previous != -1)//容错处理,全都是Previous,数据太旧直接清空。 + { + SampledHumanData->CopyFrom(DataList[Previous]); + + if(SampleTime - DataList[Previous]->TimeStamp > UMotionUtils::MotionTimeout) + { + // data is too old, clear the data list. + DataList.clear(); + } + return true; + } + if (Next != -1)//没有Previous,直接复制Next的数据。 + { + SampledHumanData->CopyFrom(DataList[Next]); + return true; + } + return false; +} +``` + ### FChingmuThread 用途为: - 获取当前系统时间。 @@ -98,7 +214,7 @@ void AChingmuMocapReceiverActor::DoSample(TArray& Frames) - 根据当前时间与当前Frames,从UChingMUComponent中将数据复制到[[#ST_MocapFrameData]]中。 - 将[[#ST_MocapFrameData]]转换成JSON后,使用AMotionSenderActor::OnGetRawMocapData_NotInGameThread()发送。 - 将当前帧数据加入FrameQueue队列。 -- 线程睡眠0.001s。 +- 线程睡眠0.001s。以此保证AChingmuMocapReceiverActor::Tick()中可以把数据都处理完。 ```c++ uint32 FChingmuThread::Run() @@ -169,6 +285,8 @@ uint32 FChingmuThread::Run() ``` ## ST_MocapFrameData +- ST_MocapFrameData为动捕数据的原始帧数据。 + ```c++ #define MOCAP_BONE_COUNT 23