vault backup: 2024-10-30 19:11:55
This commit is contained in:
@@ -36,6 +36,16 @@ void AChingmuMocapReceiverActor::BeginPlay()
|
||||
}
|
||||
```
|
||||
|
||||
FChingmuThread::Run()中处理完[[#ST_MocapFrameData]]之后,将几个演员动补数据存入FrameQueue之后。在Tick()出队,之后数据存入AllHumanFrames/AllRigidBodyFrames。
|
||||
|
||||
- AllHumanFrames
|
||||
- ID
|
||||
- std::vector<ST_MocapFrameData*> 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<MocapFrames*>& 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<ST_MocapFrameData*> 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<ST_MocapFrameData*>& 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<MocapFrames*>& 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
|
||||
|
||||
|
Reference in New Issue
Block a user