算解器 (C++)
MediaPipe4U 使用 C++ 开发,在 C++ 项目中你将获得最大的自由度,你可以很容易的访问和修改你在动画蓝图设计器中看到参数。
使用蓝图函数库
你可以通过 UMediaPipeUtils 类方便的访问 MediaPipe4U 的组件,例如: MediaPipeAnimInstance,UMediaPipeHolisticComponent 等
访问 MediaPipe 算解器(solver)
if (MediaPipeCharacter)
{
UMediaPipeAnimInstance* animInstance;
if(UMediaPipeUtils::FindMediaPipeAnimationInstance(MediaPipeCharacter, animInstance))
{
UMediaPipeUtils::SetPoseSmooth(animInstance, Value);
auto& handSolver = animInstance->GetHandsSolver();
auto& locationSolver = animInstance->GetLocationSolver();
auto& poseSolver = animInstance->GetPoseSolver();
}
}
所有的算解器都具有一些公共行为,他们都继承自 IMediaPipeSolver.
需要注意的是,受限于 UE 多接口的问题,从上面代码中的 locationSolver 和 poseSolver 获取 IMediaPipeSolver 你需要多一层调用:
animInstance->GetLocationSolver()->GetSolver(); //GetSolver for getting IMediaPipeSolver
animInstance->GetPoseSolver()->GetSolver();
手指算计器实际上是包装了左手和右手算解器,所以它直接继承了 IMediaPipeSolver,无需再次调用 GetSolver
class MEDIAPIPE_API IMediaPipeSolver
{
public:
virtual ~IMediaPipeSolver() = default;
virtual bool IsInitialized() const = 0;
virtual void Initialize(const FAnimationInitializeContext& Context, const FHumanoidBoneSettings& BoneSettings) = 0;
virtual bool Solve(const FMediaPipeFrame& MediaPipeFrame, FComponentSpacePoseContext& Output, float Alpha = 1.0f) = 0;
virtual void SetFilterParams(float KalmanParamQ, float KalmanParamR, float Smooth) = 0;
virtual void GetFilterParams(float& KalmanParamQ, float& KalmanParamR, float& Smooth) = 0;
virtual void CacheBones(const FBoneContainer& RequiredBones) = 0;
virtual bool IsDisabled() const = 0;
virtual void SetDisabled(bool Disabled) = 0;
virtual void ResetState() = 0;
virtual float GetMediaPipeFPS() const = 0;
virtual float GetFPS() const = 0;
virtual float GetMinScoreThresh() const = 0;
virtual void SetMinScoreThresh(float Threshold) = 0;
};
控制身体平滑度
void SetPoseSmooth(float Value)
{
if (MediaPipeCharacter)
{
UMediaPipeAnimInstance* animInstance;
if(UMediaPipeUtils::FindMediaPipeAnimationInstance(MediaPipeCharacter, animInstance))
{
UMediaPipeUtils::SetPoseSmooth(animInstance, Value);
}
}
}
控制手指平滑度
void SetFingerSmooth(float Value)
{
if (MediaPipeCharacter)
{
UMediaPipeAnimInstance* animInstance;
if(UMediaPipeUtils::FindMediaPipeAnimationInstance(MediaPipeCharacter, animInstance))
{
UMediaPipeUtils::SetFingerSmooth(animInstance, Value);
}
}
}
控制关节锁定
锁定表示在驱动模型过程中是否锁定关节,
UMediaPipeAnimInstance* animInstance;
if(UMediaPipeUtils::FindMediaPipeAnimationInstance(MediaPipeCharacter, animInstance))
{
UMediaPipeUtils::SetPoseSmooth(animInstance, Value);
auto& solver = animInstance->GetPoseSolver();
auto& locks = solver->GetLocks();
locks.bIsLockHead = true;
locks.bIsLockFoot = true;
solver->ApplyLocks();
}
需要注意的是,为了避免每一帧都更新关节锁定信息,你在设置锁定信息后需要使用 ApplyLocks 函数使你的设置生效。