5.1 KiB
Raw Blame History

相关类

  • TsArkitDataReceiver(ArkitDataReceiver)
  • TsChingmuMocapReceiverActor(ChingmuMocapReceiverActor)
  • TsMotionReceiverActor(MotionReceiverActor) => BP_MotionReceiver定义了MotionNetConfig.ini。
  • TsMotionSenderActor(MotionSenderActor)

TsChingmuMocapReceiverActor

  1. Init()在Server才会Spawn TsChingmuMocapReceiverActor。
  2. ConnectChingMu()ChingmuComp.StartConnectServer()
  3. Multicast_AligmMotionTime()寻找场景中的BP_MotionReceiver并且调用Receiver.AlignTimeStamp()。

ChingmuMocapReceiverActor

void AChingmuMocapReceiverActor::BeginPlay()
{
	Super::BeginPlay();
	MaxHumanCount = 10;
	MaxRigidBodyCount = 10;
	CacheLimit = 240;
	SampledHumanData = NewObject<UMocapFrameData>();
	ThreadInterval = 0.002;
	BackIndexCount = int64(UMotionUtils::BackSampleTime / (1000.0 / CHINGMU_SERVER_FPS));//BackSampleTime = 100ms  CHINGMU_SERVER_FPS =120ms
	ChingmuComp = Cast<UChingMUComponent>(GetComponentByClass(UChingMUComponent::StaticClass()));
	if (ChingmuComp == nullptr)
	{
		UE_LOG(LogTemp, Error, TEXT("Chingmu Component is missing!!"));
	}
	Thread = new FChingmuThread("Chingmu Data Thread", this);
	Sender = GetMotionSender();
}

ChingMUComponent

FChingmuThread

用途为:

uint32 FChingmuThread::Run()
{
	FTransform Tmp;
	while (bRun)
	{
		if (OwnerActor && OwnerActor->UseThread && OwnerActor->ChingmuComp && OwnerActor->ChingmuComp->IsConnected())
		{
			CurTime = ULiveDirectorStatics::GetUnixTime();
			// Human
			for (auto HumanIndex = 0; HumanIndex < OwnerActor->MaxHumanCount; HumanIndex++)
			{
				const auto bRes = OwnerActor->ChingmuComp->FullBodyMotionCapBaseBonesLocalSpaceRotation(
					OwnerActor->ChingmuFullAddress, HumanIndex, TmpTimeCode);
				if (bRes)
				{
					if (!HumanToLastReceiveTime.Contains(HumanIndex))//空数据处理。
					{
						HumanToLastReceiveTime.Add(HumanIndex, 0);
					}
					if (HumanToLastReceiveTime[HumanIndex] != TmpTimeCode.Frames)//接收端时间与
					{
						HumanToLastReceiveTime[HumanIndex] = TmpTimeCode.Frames;
						OwnerActor->OnGetHumanData_NotInGameThread(HumanIndex, CurTime, TmpTimeCode.Frames);
					}
					else
					{
						// get same frame, skip
						break;
					}
				}
			}

			// Rigidbody

			for (auto RigidBodyIndex = OwnerActor->RigidBodyStartIndex; RigidBodyIndex < OwnerActor->RigidBodyStartIndex
			     + OwnerActor->MaxRigidBodyCount; RigidBodyIndex++)
			{
				OwnerActor->ChingmuComp->GetTrackerPoseTC(OwnerActor->ChingmuFullAddress, RigidBodyIndex, Tmp,
				                                          TmpTimeCode);

				if (!RigidBodyToLastReceiveTransform.Contains(RigidBodyIndex))
				{
					RigidBodyToLastReceiveTransform.Add(RigidBodyIndex, FTransform::Identity);
				}
				// 道具的TmpTimeCode.Frames永远为0所以无法用帧数判断
				// 改为transform判断
				if (!RigidBodyToLastReceiveTransform[RigidBodyIndex].Equals(Tmp))
				{
					RigidBodyToLastReceiveTransform[RigidBodyIndex] = Tmp;
					OwnerActor->OnGetRigidBodyData_NotInGameThread(RigidBodyIndex, Tmp, CurTime, TmpTimeCode.Frames);
				}
			}
		}
		if (bRun)
		{
			FPlatformProcess::Sleep(OwnerActor ? OwnerActor->ThreadInterval : 0.004);
		}
		else
		{
			break;
		}
	}
	UE_LOG(LogTemp, Warning, TEXT("%s finish work."), *ThreadName)
	return 0;
}

MocapData

#define MOCAP_BONE_COUNT 23  
  
enum E_MotionType  
{  
    Human,  
    RigidBody  
};  
  
enum E_SourceType  
{  
    Mocap,  
    CMR,  
    Replay  
};

struct ST_MocapFrameData  
{  
    int ID;  
    int64 TimeStamp;  
    int FrameIndex;  
    E_MotionType MotionType;  
    E_SourceType SourceType;  
    FVector BonesWorldPos[MOCAP_BONE_COUNT];  
    FQuat BonesLocalRot[MOCAP_BONE_COUNT];
};

class LIVEDIRECTOR_API UMocapFrameData : public UObject
{
	GENERATED_BODY()

public:
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	int ID;
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	TArray<FVector> BonesWorldPos;
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	TArray<FQuat> BonesLocalRot;
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	int64 TimeStamp;
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	int FrameIndex;
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	int MotionType; // 0 human; 1 rigidbody
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	int SourceType; // 0 mocap, 1 cmr
public:
	void CopyFrom(const ST_MocapFrameData* Other)
	{
		ID = Other->ID;
		TimeStamp = Other->TimeStamp;
		FrameIndex = Other->FrameIndex;
		MotionType = Other->MotionType;
		SourceType = Other->SourceType;
		for (auto Index = 0; Index < 23; Index++)
		{
			BonesWorldPos[Index] = Other->BonesWorldPos[Index];
			BonesLocalRot[Index] = Other->BonesLocalRot[Index];
		}
	}
};

class MocapFrames
{
public:
	int ID;
	std::vector<ST_MocapFrameData*> Frames = {};
	
	void CalculatePackageAverageInterval(float& Res)
	{
		if(Frames.size() > 0)
		{
			auto First = Frames[0];
			auto Last = Frames[Frames.size() - 1];
			if(Last->FrameIndex > First->FrameIndex)
			{
				Res = 1.0 * (Last->TimeStamp - First->TimeStamp) / (Last->FrameIndex - First->FrameIndex);
			}
		}
	}
};

TsMotionReceiverActor

只在BeginPlay()中调用了this.MarkAsClientSeamlessTravel(); 具体逻辑在AMotionReceiverActor

MotionReceiverActor