Motion Matching

输入: 预期轨迹和其他特征的 feature

输出: 最匹配的 pose


具体来说一个传统的motion matching分为以下几步:

  1. Projection: 当用户输入的轨迹和查找到的目标 Frame 的轨迹不一致(或是出路很大),则需要重新搜索,搜索的过程主要是通过用户模拟的轨迹和当前 pose 的状态来去 database 中进行 match,然后作为修正的 Frame
  2. Decompression: 要把当前的目标 Frame 重新映射回目标 Pose
  3. Stepping: index++ 逐步推出下一个的 Frame

在MM的三个步骤中,Decompression 和 Stepping 的难度都不是很大,因为表示 feature 的 x 和 对应的 pose y 都被储存在database 中,所以MM中玩家与角色之间的交互可以表示为:

使用的时候直接读取就OK了,在这个算法中耗时间空间的主要是 Projection ,育碧同样给出了他们的解决思路:

  1. LOD
  2. KD-Tree

先来看看MM 的代码思路,其实很简单

  • 每一帧都是在database 中对index++
  • 在需要搜索的时候,在database 中搜索,如果 best_index 可用则切换
// 判断是否为最后一帧
bool end_of_anim = database_trajectory_index_clamp(db, frame_index, 1) == frame_index;
if (force_search || search_timer <= 0.0f || end_of_anim){// 在数据库中寻找最匹配帧database_search();// 更新 pose 数据if (best_index != frame_index){trns_bone_positions = db.bone_positions(best_index);trns_bone_velocities = db.bone_velocities(best_index);trns_bone_rotations = db.bone_rotations(best_index);trns_bone_angular_velocities = db.bone_angular_velocities(best_index);inertialize_pose_transition();frame_index = best_index;}// Reset search timersearch_timer = search_time;
}
// Tick frame
frame_index++; // Assumes dt is fixed to 60fps// 查询下一 frame_index 对应的 Pose
curr_bone_positions = db.bone_positions(frame_index);
curr_bone_velocities = db.bone_velocities(frame_index);
curr_bone_rotations = db.bone_rotations(frame_index);
curr_bone_angular_velocities = db.bone_angular_velocities(frame_index);
curr_bone_contacts = db.contact_states(frame_index);

具体搜索是怎么算的呢

best_cost = 0.0;
for (int i = 0; i < nfeatures; i++){best_cost += squaref(query_normalized(i) - features(best_index, i));
}

在 database_search() 中用的是欧氏距离,再看看维数,MM 总的特征对比按照如下计算
D i s s i m i l a r i t y ( e i , e c ) = w v × D i s t v ( v i , v c ) + w p × D i s t p ( p i , p c ) + w t × D i s t t ( t i , t c ) Dissimilarity(ei,ec)=w_v×Dist_v(v_i,v_c)+w_p×Dist_p(p_i,p_c)+w_t×Dist_t(t_i,t_c) Dissimilarity(ei,ec)=wv​×Distv​(vi​,vc​)+wp​×Distp​(pi​,pc​)+wt​×Distt​(ti​,tc​)
总的特征对比由 velocity、position 和 trajectory,三个变量得到,其中velocity、position为三维变量,trajectory是二维变量,假设取两个关节的velocity、position,三个未来trajectory,此时的维度:
d i m ( D i s s i m i l a r i t y ) = ( 3 + 3 ) ∗ 2 + 2 ∗ 3 = 18 dim(Dissimilarity) = (3+3)*2+2*3=18 dim(Dissimilarity)=(3+3)∗2+2∗3=18
按照KD-tree的定义有:
2 18 = 262 , 144 ≪ d a t a b a s e f r a m e n u m b e r 2^{18}=262,144 \ll database\ frame\ number 218=262,144≪database frame number
结论:方案可行

以下给出kd-tree 的 python 代码,参考资料:

k-d tree算法的研究

class KDNode(object):def __init__(self, value, split, left, right):# value=[x,y]self.value = valueself.split = splitself.right = rightself.left = leftclass KDTree(object):def __init__(self, data):# data=[[x1,y1,...],[x2,y2,...],...]# 维度k = len(data[0])def CreateNode(split, data_set):if not data_set:return None# 排序data_set.sort(key=lambda x: x[split])# 取中位数split_pos = len(data_set) // 2median = data_set[split_pos]# 计算下一维度split_next = (split + 1) % kreturn KDNode(median, split, CreateNode(split_next, data_set[: split_pos]),CreateNode(split_next, data_set[split_pos + 1:]))self.root = CreateNode(0, data)def search(self, root, x, count=1):nearest = []for i in range(count):nearest.append([-1, None])self.nearest = np.array(nearest)def recurve(node):if node is not None:axis = node.splitdaxis = x[axis] - node.value[axis]if daxis < 0:recurve(node.left)else:recurve(node.right)dist = sqrt(sum((p1 - p2) ** 2 for p1, p2 in zip(x, node.value)))for i, d in enumerate(self.nearest):# 如果当前nearest内i处未标记(-1),或者新点与x距离更近if d[0] < 0 or dist < d[0]:  # 插入比i处距离更小的self.nearest = np.insert(self.nearest, i, [dist, node.value], axis=0)  self.nearest = self.nearest[:-1]break# 找到nearest集合里距离最大值的位置,为-1值的个数n = list(self.nearest[:, 0]).count(-1)# 切分轴的距离比nearest中最大的小(存在相交)if self.nearest[-n - 1, 0] > abs(daxis):if daxis < 0:  # 相交,x[axis]< node.data[axis]时,去右边(左边已经遍历了)recurve(node.right)else:  # x[axis]> node.data[axis]时,去左边,(右边已经遍历了)recurve(node.left)recurve(root)return self.nearest# 最近坐标点、最近距离和访问过的节点数
result = namedtuple("Result_tuple", "nearest_point nearest_dist nodes_visited")data = [[2, 3], [5, 4], [9, 6], [4, 7], [8, 1], [7, 2]]
# 创建KD-tree
kd = KDTree(data)#[3, 4.5]最近的3个点
n = kd.search(kd.root, [3, 4.5], 3)
print(n)#[[1.8027756377319946 list([2, 3])][2.0615528128088303 list([5, 4])][2.692582403567252 list([4, 7])]]

Motion Matching相关推荐

  1. 对《Mode-Adaptive Neural Networks for Quadruped Motion Control》一文的理解(上)

    该篇文章发表于SIGGRAPH2018,作者HE ZHANG † , University of Edinburgh.SEBASTIAN STARKE , University of Edinburg ...

  2. Learned Motion Matching-动作生成算法

    Learned Motion Matching 来源: SigGraph2021 研究方向: 动作生成 链接: https://dl.acm.org/doi/pdf/10.1145/3386569.3 ...

  3. 做过《战神》《死亡搁浅》的光子动捕专家,怎么理解动捕?

    10月9日,在2021年腾讯游戏开发者大会上(TGDC),腾讯互动娱乐光子技术中心Lead Motion Technician Kevin Wang以<捕风捉影,让虚拟更现实>为主题,立足 ...

  4. 角色动作系统概述:战斗、3C相关

    *有一个很重要的点我忘记说了,就是游戏策略-实际上在制作动作系统的时候要考虑兼容各种策略,但是在调手感前,要先想清楚自己的战斗策略,所为战斗策略是指博弈方式,以及对玩家的操作进行约束,约束具体是指你需 ...

  5. 角色动画(Character Animation)的现状与趋势

    逆向运动学(Inverse Kinematics)求解 一.个人需求 需求: 靠游戏手柄(用户)以虚拟人物的根轨迹trajectory来控制用户朝向,同时通过控制输入来合成出人难以做到的动作. 若缺少 ...

  6. 汇编指令lmm_动画视频角色的LMM神经网络

    汇编指令lmm Researchers at Ubisoft have proposed an alternative to the Motion Matching algorithm for aut ...

  7. Unity的Package了解(2020.3)

    unity 更新很快,很多package如果不及时了解,很容易造很多轮子或走很多弯路. 一.已验证包 ------------------------------------------------- ...

  8. 【游戏开发阅读列表2】动画(Anima2D、粒子、物理等)

    游戏中动画的实现有很多不同方法,帧动画.骨骼动画.基于物理的动画.基于Shader的动画.粒子等. 在这篇文章中,列出了我最近读到过的不同种类动画入门级的文章.视频.关于Unity动画状态机这一类太常 ...

  9. 2022.5.12 腾讯魔方客户端暑期实习 一面凉经

    完全裸考,,,只能当作是长经验了,,,随便记录一下吧/(ㄒoㄒ)/~~太菜了 1.自我介绍 2.实习项目经历 2.1 你在项目中负责的工作 A:负责游戏角色手部的抓取和放下动作的开发,基于UE的C++ ...

最新文章

  1. 常用 Linux 命令
  2. Linux进程-命令行参数和环境列表
  3. python xlwt写入excel_python xlwt模块写入excel超过65536行报错问题解决方法
  4. 简单地发布EJB程序的过程
  5. c语言各类随机函数,怎样让c语言中的随机函数真正随机?
  6. ant 安装及基础教程 !
  7. camel 调用soap_使用Apache Camel通过soap添加WS-Security
  8. 敏捷开发中提高软件生产率的方法
  9. 这个机器人不学数据集,“纯玩”get各类家务技能,LeCun觉得很赞
  10. 金蝶k3服务器的操作系统,金蝶k3服务器配置工具
  11. java基础热门侠客养成_侠客养成手册攻略大全 新手攻略开局任务流程汇总[多图]...
  12. 鸿鹄功能架构图:实现一站式异构数据分析
  13. 网页音乐制作器(网页钢琴)-- MusicMaker
  14. python 日期运算_Python中关于日期的计算总结
  15. 微信卡死代码 java_能让微信卡死的代码是什么 微信整人代码大全
  16. unity steamworksdk简单接入
  17. python实现烤羊肉串(类)
  18. C语言实验——一元二次方程Ⅱ
  19. 解读Linux零拷贝之mmap
  20. LVM-HOWTO/学习笔记(五)

热门文章

  1. android 解决小米手机上选择照片路径为null情况
  2. 全球汽车巨头「无缘」智能汽车市场份额前十,背后的心酸和无奈
  3. 区块链读书笔记02 - 区块链进阶
  4. ArcGIS数字校园数据采集 |全国大学生GIS技能大赛试题(附练习数据)
  5. mapreduce程序案例4--查找QQ共同好友
  6. 淘宝刷钻为何屡禁不止 透过现象看本质
  7. 日记20201029精力管理
  8. chatgpt赋能python:Python中的s.len()方法介绍
  9. vue仿移动端音乐播放器
  10. 谁动了我的IP地址?