转自:https://dawnarc.com/2018/05/ue4animationik-related/

Examples

工程1

在油管上看到一个UE4 IK动画的demo工程示例

该示例作者的主页:https://www.patreon.com/unrealcg

演示视频:Advanced foot IK for Unreal Engine 4 - (100% Free)
https://www.youtube.com/watch?v=XetC9ivIXFc

demo工程下载地址(4.19):
https://pan.baidu.com/s/1mlcM0cseKWpprnISVM0P5Q

工程2

该工程除了IK,还包括动画融合、物理等功能

演示视频:UE4 - Advanced Locomotion System V3 - Features
https://www.youtube.com/watch?v=yTniZCOCY7o

下载地址:Unreal商城,60刀
Advanced Locomotion System V3
https://www.unrealengine.com/marketplace/advanced-locomotion-system-v1

IK AnimNode

FABRIK (Forward And Backward Reaching Inverse Kinematics)

FABRIK
https://docs.unrealengine.com/en-us/Engine/Animation/NodeReference/Fabrik

Adding of a rifle and fabrik node to fix left hand
https://www.youtube.com/watch?v=49MJWjlSHcw

Look At

Look At
https://docs.unrealengine.com/en-us/Engine/Animation/NodeReference/SkeletalControls/LookAt

CCDIK (Cyclic Coordinate Descent Inverse Kinematics)

CCDIK
https://docs.unrealengine.com/en-us/Engine/Animation/NodeReference/SkeletalControls/CCDIK

Hand IK Retargeting

Hand IK Retargeting
https://docs.unrealengine.com/en-us/Engine/Animation/NodeReference/SkeletalControls/HandIKRetargeting

Two Bone IK

Two Bone IK
https://docs.unrealengine.com/en-us/Engine/Animation/NodeReference/SkeletalControls/TwoBoneIK

Spline IK

Spline IK
https://docs.unrealengine.com/en-us/Engine/Animation/NodeReference/SkeletalControls/SplineIK

IK Engine Source

CCDIK

Path:
Engine\Source\Runtime\AnimGraphRuntime\Private\BoneControllers\AnimNode_CCDIK.cpp

void FAnimNode_CCDIK::EvaluateSkeletalControl_AnyThread(FComponentSpacePoseContext& Output, TArray<FBoneTransform>& OutBoneTransforms)
{
const FBoneContainer& BoneContainer = Output.Pose.GetPose().GetBoneContainer(); // Update EffectorLocation if it is based off a bone position
FTransform CSEffectorTransform = GetTargetTransform(Output.AnimInstanceProxy->GetComponentTransform(), Output.Pose, EffectorTarget, EffectorLocationSpace, EffectorLocation);
FVector const CSEffectorLocation = CSEffectorTransform.GetLocation(); // Gather all bone indices between root and tip.
TArray<FCompactPoseBoneIndex> BoneIndices; {
const FCompactPoseBoneIndex RootIndex = RootBone.GetCompactPoseIndex(BoneContainer);
FCompactPoseBoneIndex BoneIndex = TipBone.GetCompactPoseIndex(BoneContainer);
do
{
BoneIndices.Insert(BoneIndex, );
BoneIndex = Output.Pose.GetPose().GetParentBoneIndex(BoneIndex);
} while (BoneIndex != RootIndex);
BoneIndices.Insert(BoneIndex, );
} // Gather transforms
int32 const NumTransforms = BoneIndices.Num();
OutBoneTransforms.AddUninitialized(NumTransforms); // Gather chain links. These are non zero length bones.
TArray<CCDIKChainLink> Chain;
Chain.Reserve(NumTransforms);
// Start with Root Bone
{
const FCompactPoseBoneIndex& RootBoneIndex = BoneIndices[];
const FTransform& LocalTransform = Output.Pose.GetLocalSpaceTransform(RootBoneIndex);
const FTransform& BoneCSTransform = Output.Pose.GetComponentSpaceTransform(RootBoneIndex); OutBoneTransforms[] = FBoneTransform(RootBoneIndex, BoneCSTransform);
Chain.Add(CCDIKChainLink(BoneCSTransform, LocalTransform, ));
} // Go through remaining transforms
for (int32 TransformIndex = ; TransformIndex < NumTransforms; TransformIndex++)
{
const FCompactPoseBoneIndex& BoneIndex = BoneIndices[TransformIndex]; const FTransform& LocalTransform = Output.Pose.GetLocalSpaceTransform(BoneIndex);
const FTransform& BoneCSTransform = Output.Pose.GetComponentSpaceTransform(BoneIndex);
FVector const BoneCSPosition = BoneCSTransform.GetLocation(); OutBoneTransforms[TransformIndex] = FBoneTransform(BoneIndex, BoneCSTransform); // Calculate the combined length of this segment of skeleton
float const BoneLength = FVector::Dist(BoneCSPosition, OutBoneTransforms[TransformIndex - ].Transform.GetLocation()); if (!FMath::IsNearlyZero(BoneLength))
{
Chain.Add(CCDIKChainLink(BoneCSTransform, LocalTransform, TransformIndex));
}
else
{
// Mark this transform as a zero length child of the last link.
// It will inherit position and delta rotation from parent link.
CCDIKChainLink & ParentLink = Chain[Chain.Num() - ];
ParentLink.ChildZeroLengthTransformIndices.Add(TransformIndex);
}
} // solve
bool bBoneLocationUpdated = AnimationCore::SolveCCDIK(Chain, CSEffectorLocation, Precision, MaxIterations, bStartFromTail, bEnableRotationLimit, RotationLimitPerJoints); // If we moved some bones, update bone transforms.
if (bBoneLocationUpdated)
{
int32 NumChainLinks = Chain.Num(); // First step: update bone transform positions from chain links.
for (int32 LinkIndex = ; LinkIndex < NumChainLinks; LinkIndex++)
{
CCDIKChainLink const & ChainLink = Chain[LinkIndex];
OutBoneTransforms[ChainLink.TransformIndex].Transform = ChainLink.Transform; // If there are any zero length children, update position of those
int32 const NumChildren = ChainLink.ChildZeroLengthTransformIndices.Num();
for (int32 ChildIndex = ; ChildIndex < NumChildren; ChildIndex++)
{
OutBoneTransforms[ChainLink.ChildZeroLengthTransformIndices[ChildIndex]].Transform = ChainLink.Transform;
}
} #if WITH_EDITOR
DebugLines.Reset(OutBoneTransforms.Num());
DebugLines.AddUninitialized(OutBoneTransforms.Num());
for (int32 Index = ; Index < OutBoneTransforms.Num(); ++Index)
{
DebugLines[Index] = OutBoneTransforms[Index].Transform.GetLocation();
}
#endif // WITH_EDITOR }
}

Path:
Engine\Source\Runtime\AnimationCore\Private\CCDIK.cpp

namespace AnimationCore
{ bool SolveCCDIK(TArray<CCDIKChainLink>& InOutChain, const FVector& TargetPosition, float Precision, int32 MaxIteration, bool bStartFromTail, bool bEnableRotationLimit, const TArray<float>& RotationLimitPerJoints)
{
struct Local
{
static bool UpdateChainLink(TArray<CCDIKChainLink>& Chain, int32 LinkIndex, const FVector& TargetPos, bool bInEnableRotationLimit, const TArray<float>& InRotationLimitPerJoints)
{
int32 const TipBoneLinkIndex = Chain.Num() - ; ensure(Chain.IsValidIndex(TipBoneLinkIndex));
CCDIKChainLink& CurrentLink = Chain[LinkIndex]; // update new tip pos
FVector TipPos = Chain[TipBoneLinkIndex].Transform.GetLocation(); FTransform& CurrentLinkTransform = CurrentLink.Transform;
FVector ToEnd = TipPos - CurrentLinkTransform.GetLocation();
FVector ToTarget = TargetPos - CurrentLinkTransform.GetLocation(); ToEnd.Normalize();
ToTarget.Normalize(); float RotationLimitPerJointInRadian = FMath::DegreesToRadians(InRotationLimitPerJoints[LinkIndex]);
float Angle = FMath::ClampAngle(FMath::Acos(FVector::DotProduct(ToEnd, ToTarget)), -RotationLimitPerJointInRadian, RotationLimitPerJointInRadian);
bool bCanRotate = (FMath::Abs(Angle) > KINDA_SMALL_NUMBER) && (!bInEnableRotationLimit || RotationLimitPerJointInRadian > CurrentLink.CurrentAngleDelta);
if (bCanRotate)
{
// check rotation limit first, if fails, just abort
if (bInEnableRotationLimit)
{
if (RotationLimitPerJointInRadian < CurrentLink.CurrentAngleDelta + Angle)
{
Angle = RotationLimitPerJointInRadian - CurrentLink.CurrentAngleDelta;
if (Angle <= KINDA_SMALL_NUMBER)
{
return false;
}
} CurrentLink.CurrentAngleDelta += Angle;
} // continue with rotating toward to target
FVector RotationAxis = FVector::CrossProduct(ToEnd, ToTarget);
if (RotationAxis.SizeSquared() > .f)
{
RotationAxis.Normalize();
// Delta Rotation is the rotation to target
FQuat DeltaRotation(RotationAxis, Angle); FQuat NewRotation = DeltaRotation * CurrentLinkTransform.GetRotation();
NewRotation.Normalize();
CurrentLinkTransform.SetRotation(NewRotation); // if I have parent, make sure to refresh local transform since my current transform has changed
if (LinkIndex > )
{
CCDIKChainLink const & Parent = Chain[LinkIndex - ];
CurrentLink.LocalTransform = CurrentLinkTransform.GetRelativeTransform(Parent.Transform);
CurrentLink.LocalTransform.NormalizeRotation();
} // now update all my children to have proper transform
FTransform CurrentParentTransform = CurrentLinkTransform; // now update all chain
for (int32 ChildLinkIndex = LinkIndex + ; ChildLinkIndex <= TipBoneLinkIndex; ++ChildLinkIndex)
{
CCDIKChainLink& ChildIterLink = Chain[ChildLinkIndex];
const FTransform LocalTransform = ChildIterLink.LocalTransform;
ChildIterLink.Transform = LocalTransform * CurrentParentTransform;
ChildIterLink.Transform.NormalizeRotation();
CurrentParentTransform = ChildIterLink.Transform;
} return true;
}
} return false;
}
}; bool bBoneLocationUpdated = false;
int32 const NumChainLinks = InOutChain.Num(); // iterate
{
int32 const TipBoneLinkIndex = NumChainLinks - ; // @todo optimize locally if no update, stop?
bool bLocalUpdated = false;
// check how far
const FVector TargetPos = TargetPosition;
FVector TipPos = InOutChain[TipBoneLinkIndex].Transform.GetLocation();
float Distance = FVector::Dist(TargetPos, TipPos);
int32 IterationCount = ;
while ((Distance > Precision) && (IterationCount++ < MaxIteration))
{
// iterate from tip to root
if (bStartFromTail)
{
for (int32 LinkIndex = TipBoneLinkIndex - ; LinkIndex > ; --LinkIndex)
{
bLocalUpdated |= Local::UpdateChainLink(InOutChain, LinkIndex, TargetPos, bEnableRotationLimit, RotationLimitPerJoints);
}
}
else
{
for (int32 LinkIndex = ; LinkIndex < TipBoneLinkIndex; ++LinkIndex)
{
bLocalUpdated |= Local::UpdateChainLink(InOutChain, LinkIndex, TargetPos, bEnableRotationLimit, RotationLimitPerJoints);
}
} Distance = FVector::Dist(InOutChain[TipBoneLinkIndex].Transform.GetLocation(), TargetPosition); bBoneLocationUpdated |= bLocalUpdated; // no more update in this iteration
if (!bLocalUpdated)
{
break;
}
}
} return bBoneLocationUpdated;
}
}

UE4 Animation]IK Related的更多相关文章

  1. [UE4]Animation Techniques used in Paragon部分翻译及索引

    视频地址:https://www.youtube.com/watch?v=1UOY-FMm-xo 主要内容:该视频由Paragon游戏制作者Laurent Delayen(Senior Program ...

  2. MOTION-MATCHING IN UBISOFT’S FOR HONOR翻译

    http://www.gameanim.com/2016/05/03/motion-matching-ubisofts-honor/ Introducing For Honor with a vide ...

  3. maya绝招(60---尾)

    第64招 置换新意 Displacement(置换)和Bump(凹凸)效果类似,但运行方式不同.将一个File结点用中间拖动到材质上有的shading Group属性中的置换属性上,这个时候可以看到o ...

  4. Community Stories: Cinemachine and Timeline——Community Stories: Cinemachine and Timeline

    Community Stories: Cinemachine and Timeline 社区故事:Cinemachine 和 Timeline Adam Myhill, 八月 25, 2017 原文: ...

  5. U3D MonoBehaviour

    一.简介 MonoBehaviour是每个脚本派生类的基类,它定义了一个脚本文件从最初被加载到最终被销毁的一个完整过程. 这个过程通过对应的方法体现出来,在不同的方法完成不同的功能,我们把这些方法称为 ...

  6. 关于Unity中Mecanim动画的动画状态代码控制与代码生成动画控制器

    对于多量的.复杂的.有规律的控制器使用代码生成 动画状态代码控制 1:每个动画状态,比如进入状态,离开状态, 等都有可能需要代码来参与和处理,比如,进入这个动画单元后做哪些事情,来开这个动画单元后做哪 ...

  7. unity3d API汇总

    using UnityEngine; using System.Collections; public class AllFunction : MonoBehaviour { /* API Versi ...

  8. 我所遭遇过的游戏中间件--Havok

    我所遭遇过的游戏中间件--Havok Havok是我接触的第一款游戏中间件,那是在五,六年前,我刚刚毕业,对游戏开发还是个菜鸟.我记得先是对游戏场景中的地形和其他静态物体生成刚体,然后做角色的Ragd ...

  9. 004-unity3d MonoBehaviour脚本方法简介

    一.MonoBehaviour 1.公共方法 CancelInvoke Cancels all Invoke calls on this MonoBehaviour. Invoke Invokes t ...

随机推荐

  1. 前端重定向,index.html文件被浏览器缓存,导致整个应用都是旧的

    解决方法:https://github.com/ant-design/ant-design-pro/issues/1365#issuecomment-384496088

  2. 学习:STL概念学习

    STL初识: 为了建立数据结构和算法的一套标准,诞生了STL STL基本概念: STL(Standard Template Library,标准模板库) STL 从广义上分为: 容器(containe ...

  3. MongoDB干货系列2-MongoDB执行计划分析详解(2)(转载)

    写在之前的话 作为近年最为火热的文档型数据库,MongoDB受到了越来越多人的关注,但是由于国内的MongoDB相关技术分享屈指可数,不少朋友向我抱怨无从下手. <MongoDB干货系列> ...

  4. python函数 | 三元运算

    三元运算符就是在赋值变量的时候,可以直接加判断,然后赋值 格式: [on_true] if [expression] else [on_false] 三元运算只适用于简单的if else判断,再多一层 ...

  5. WinDbg常用命令系列---sx, sxd, sxe, sxi, sxn, sxr, sx- (设置异常)

    简介 sx*命令控制调试器在正在调试的应用程序中发生异常或发生某些事件时采取的操作. 使用形式 sx sx{e|d|i|n} [-c "Cmd1"] [-c2 "Cmd2 ...

  6. ent 基本使用十九 事务处理

    ent 生成的代码中client 提供了比较全的事务处理 启动单个事务进行处理 // GenTx generates group of entities in a transaction. func ...

  7. haproxy2.0 dataplaneapi 简单说明

    haproxy2.0 支持基于dataplaneapi 的haproxy 动态配置修改以及服务生效,早期大家为了动态 可以会基于dsn 的服务发现模式,基于confd 结合consul 动态生成配置并 ...

  8. 中国大学生计算机系统与程序设计竞赛 CCF-CCSP-2017 串行调度(serial)

    串行调度(serial) 除等价条件, 根据题意设置限制条件,然后求字典序最小拓扑序. 简洁版 #include<bits/stdc++.h> using namespace std; ; ...

  9. [题解向] Luogu2146[NOI2015]软件包管理器

    #\(\mathcal{\color{red}{Description}}\) \(Link\) 一道\(zz\)的树剖题\(qwq\). #\(\mathcal{\color{red}{Soluti ...

  10. 关于golang-mod的使用方法

    简单粗暴仅需要三步即可 $ go mod download $ go mod tidy $ go build -v 这里保持默认什么都不用添加,项目无需在 gopath里面 Vendoring mod ...