【3D游戏基础】蒙皮骨骼动画与骨架

2023-10-27

效果

目标!画出蒙皮动画的骨架。
e9a6eceb1b848d67ed52b272a25518db.gif

视频

https://www.bilibili.com/video/BV1pM411m7Yw

PPT

https://zfxdvouj61.feishu.cn/file/boxcnwgESO6zdQetO7oNhKboNsd
以下为PPT文字稿,建议还是看视频

讲讲自己对蒙皮骨骼动画的理解,并在 Cocos Creator 3.6 中绘制出骨架~希望对大家有帮助~

917774a7dd4dc5621689d9c7c931f3b4.png

这是我们今天实现效果,在 Cocos Creator 中把骨架画出来,图中绿色的线就是绘制的骨架

e56cb73a7b2a86eea0bf849fdd0dceda.gif

在开始之前,我们介绍一下如何导入模型?长按3d资源拖入到资源管理器中.

3239e265fd9e9402f295dfbde7292a8b.png

让我们看看gltf资源包括什么(介绍最下方),mesh 网格,texture 贴图,material 材质,animation 动画 ,skeleton 骨架数据。根节点有个动画组件,cips是动画列表,default clip 是默认动画, play on load 是加载后自动播放。Sockets 是挂点系统。启用 useBakedAnimation 时会使用预烘焙骨骼动画系统(所有动画数据都会按照指定帧率提前预采样、烘焙到全局复用的骨骼动画贴图合集上),禁用 useBakedAnimation 后会使用实时计算骨骼动画系统(动画数据会输出到场景的骨骼节点树中)。

ca707008c5cd549a36973264d8b29e0b.png

mesh 就是网格,由三角形拼成的网格,可以看到这个网格有7325个顶点,和11186个三角形,minpos 就是包围盒最小值, maxpos 就是包围盒最大的值

5842f5d70503c8439e3d15405e3e3fdb.png

关于网格,这张图会看的清楚一点,由多个三角形构成。

6b0c57e8196eaadc7431f6e4a2b951dc.jpeg

材质就像是给刚才的网格穿上的衣服,贴图就像是衣服上好看的图案

284f11be6199e72ae57dd1544e99f154.png

可以在这个模型上看到贴图的部件,是通过纹理映射的方式显示这张图片。例如手套映射到贴图的右下角。

c134807ed053c57cbe6e381861689b75.png

还有一种常见的贴图叫法线贴图,简单来说这张贴图可以让模型更有凹凸感

b6a97462dfc8d34638893ee763579cfe.jpeg

骨架,就像是人体的骨骼一样。蒙皮,蒙的就是网格相对于骨架的位置

e5e97fbdbae56e3472480041d8fd8dd4.jpeg

事实上,在实现中并没有骨架,并不是一条一条的线,而是一个一个的点。叫做关节或者说骨骼点。蒙皮就是根据根据这个点,计算网格点的位置。

39ab4f246fe7a15a064281ad876cf365.jpeg

选中场景中的3d模型,点击动画编辑器,进入动画编辑模式。可以预览动画效果。

7180682665d56bdc694fa4aa74614510.png

点击播放按钮就可以播放了。可以看到右上角的属性面板并没有变化,那么这个动画是移动的是什么呢?

879ef2c77d288227ce1bc6925c64967f.gif

前面几个点的 postion rotation 并没有发生变化

0bafefe5144d13b6db1055eb77c48b4d.gif

可以看到后面几个点位移旋转发生了变化,这些点就是骨骼(关节)。蒙皮动画的本质是改变骨骼的节点信息,网格再根据骨骼点实时计算网格的形状。

fe8ff0417190695e2d4322a42633ff71.gif

材质,网格,骨架是由蒙皮网格渲染器(skinmeshrenderer) 组织在一起。

d73a57ac7ddc82a2944e4dada8c0e6f2.png

总结一下,一个3d资源拖入到场景中的结构是怎么样的。根节点有一个骨骼动画组件。他的儿子中包含了骨骼蒙皮渲染组件(将材质,网格,骨骼组织在一起)。还有种儿子是骨骼(关节),蒙皮动画实际上是对这些骨骼点进去移动旋转,然后网格再根据这个点的信息,再计算网格的形状(蒙皮)。

6b7e9e3db019a68c00c7a6fb4a7c5ab3.png

了解了上面的知识,我们现在开始实战吧。我们的目标是画出这个骨骼!

1e2b37159690a9552fef36a23ceea602.gif

我们该如何绘制骨架呢?只要在这些骨骼点和其父节点画一条线就行了。

4131ad1a5520e4169719b7a171bc35ee.gif

我们要画的是这些骨骼,这些骨骼的数据应该在哪里获取呢?是的,就在骨架数据中获取,骨架数据就是在蒙皮网格渲染器中。

7c4823de585afd63ab43de3f94043576.png

model 就是对应这初始节点。先拿到蒙皮网格渲染器的组件,找到骨架数据,再找到骨骼点,并做上标记。最后再递归按深度优先的顺序把所有骨骼点保存起来。这个bones就是所有的关节点了。

e5251098297954ac53753701cc7b7269.png

那么我们应该用什么组件画骨架呢?这里用了 Cocos Creator 的线段组件。对有爸爸的骨骼们创建线段组件。把每个骨骼和他爸爸的世界坐标告诉线段组件,就能画出骨架了。

4b7d2c3b3bf92d53e0187141d7abc445.png

还需要注意的是,要想把这东西画到最前!需做到 透 深 优!透是指透明渲染队列。在 Cocos Creator 默认的前向渲染管线中,是先渲染不透明队列再渲染透明队列。选择透明队列就可以再更后的阶段绘制。深 指的是 深度读写都关闭,深度写是影响之后东西的绘画,深度读是只被之前绘画的深度影响,当然我们都不想影响就都关了。优 是只 优先级,要在最后画!

82a858227f9b8fcb51d8ef04461ccca0.png

最后,介绍一下这个脚本怎么使用。将这个脚本拖入到场景中,再挂上场景中的3D模型就可以了。

3728f7cf6f77c73cf9194ffeff8339e5.png

小结~ 1.动画驱动骨骼 2.骨骼决定网格 3.画最前,透深优

b7683129c281f48730a950efeb269f3d.png

代码

import { _decorator, Component, Node, SkinnedMeshRenderer, Line, SkeletalAnimation, Color, gfx, GradientRange, log } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('SkeletonHelper')
export class SkeletonHelper extends Component {

    @property(Node)
    model: Node = null!

    private bones: Node[] = []
    private lines: Line[] = []

    start() {
        log('欢迎关注微信公众号【白玉无冰】 https://mp.weixin.qq.com/s/-I6I6nG2Hnk6d1zqR-Gu2g')
        const skeletalAnimation = this.model.getComponent(SkeletalAnimation)
        skeletalAnimation.useBakedAnimation = false; // maybe todo
        const skinMeshRds = this.model.getComponentsInChildren(SkinnedMeshRenderer)
        skinMeshRds.forEach(element => {
            const skinningRoot = element.skinningRoot
            element.skeleton.joints.forEach((v) => {
                const node = skinningRoot.getChildByPath(v)
                node['isBone'] = true;
            })
        });

        const bones = this.getBoneList(this.model);
        this.bones = bones;

        for (let i = 0; i < bones.length; i++) {
            const bone = bones[i];
            if (bone.parent && bone.parent['isBone']) {
                const line = this.addComponent(Line);
                const state = { priority: 255, depthStencilState: new gfx.DepthStencilState(false, false) }
                // @ts-ignore
                line._materialInstance.overridePipelineStates(state)
                line.worldSpace = true;
                line.width.constant = 0.01;
                line.color.mode = GradientRange.Mode.TwoColors //there are some bugs in cocos creator // engine\cocos\particle\models\line-model.ts   // engine\cocos\particle\animator\gradient.ts
                line.color.colorMin = Color.BLUE
                line.color.colorMax = Color.GREEN
                line.positions = [bone.worldPosition, bone.parent.worldPosition] as never[]
                this.lines.push(line)
            }
        }
    }

    showSkeleton(show: boolean) {
        this.lines.forEach(l => l.enabled = show)
    }

    private getBoneList(object: Node) {
        const boneList: Node[] = [];

        if (object['isBone']) {
            boneList.push(object);
        }

        for (let i = 0; i < object.children.length; i++) {
            boneList.push.apply(boneList, this.getBoneList(object.children[i]));
        }
        return boneList;
    }

    lateUpdate(deltaTime: number) {
        let lineIndex = 0;
        for (let i = 0; i < this.bones.length; i++) {
            const bone = this.bones[i];
            if (bone.parent && bone.parent['isBone']) {
                const line = this.lines[lineIndex++];
                line.positions = [bone.worldPosition, bone.parent.worldPosition] as never[]
            }
        }
    }
}

视频

2fd730477563a8c40cfc047c064b0d8c.jpeg

“点赞“ ”在看” 鼓励一下392048b3bf09888566afd6c2f328e199.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【3D游戏基础】蒙皮骨骼动画与骨架 的相关文章

  • Python 中的标量场可视化

    我需要在 Python 中可视化几个重叠的标量场 我发现mayavi图书馆做这种情节 问题是我不明白如何为标量字段自定义颜色图 我的想法是为每个字段设置一种颜色的阴影 我尝试采用一个例子 http docs enthought com ma
  • 从 NumPy 数组中的数据绘制 3D 图像

    我有一个 NumPy 数组中的数据文件 我想查看 3D 图像 我正在分享一个示例 我可以在其中查看大小为 100 100 的 2D 图像 这是 xy 平面上 z 0 处的切片 import numpy as np from matplotl
  • OpenGL Z 偏置(多边形偏移)限制

    我有两个共面的多边形 我尝试做 glEnable GL POLYGON OFFSET FILL glPolygonOffset 0 1 并期望其中一个明显 位于 另一个之上 这种情况直到大约 70 75 个单位之外 近剪裁平面为 1 远剪裁
  • 在 Three.js 中将贝塞尔曲线转换为平面道路

    我试图根据之前计算得到的一些贝塞尔曲线在 Three js 中绘制一条弯曲的道路 问题是我找不到转换曲线序列的方法 一条从上一条曲线的末尾开始 到一个曲面 我有一个 3D 场景 其中有一些汽车 一条用飞机创建的道路 并且绘制了即将到来的道路
  • 自动适合衣服的算法?

    想象一下 客户要求您设计一款软件 以满足一些相当粗略的规格 如下所示 1 它将面向时尚行业营销 2 用户将是 设计衣服和东西 的人 可能有一个特定的术语 但我没有想到 3 由于各种原因 能够快速制作原型设计并查看它们在模型上的外观会很有用
  • 3D 数学:根据“向上”和“向上”正交向量计算倾斜(滚动)角度

    我希望这是提出这个问题的正确位置和这个一样 https stackoverflow com questions 3035590 bank angle from up vector and look at vector 但表示为纯数学而不是图
  • 在球体边缘绘制点

    因此 来自 Flash 背景的我对一些简单的 2D 三角函数有很好的理解 在带有 I 圆的二维中 我知道使用给定角度和半径将项目放置在边缘上的数学 x cos a r y sin a r 现在 如果我在 3d 空间中有一个点 我知道球体的半
  • CSS3DObject 始终位于 WebGL Mesh 前面

    我正在混合CSS3D Renderer with WebGL Renderer to add HTML3D 空间中的元素WebGL场景 这CSS3DObject在前面WebGL网格即使WebGL Renderer具有较高的 z index
  • 如何仅剪切剪切平面的交集(而不是并集)?

    在 OpenGL JOGL 中 当使用多个剪切平面时 似乎会应用所有剪切平面的并集 我想要的是路口要应用的所有剪裁平面 这可能吗 请参阅下面的简化二维示例 Edit An example of clipping by vertex shad
  • 如何在 React Native 中渲染自定义 3D 对象

    我已经成功使用 Three js expo Three 和 expo gl 在 React Native 中配置了红色立方体的 3D 渲染 但我想让用户渲染他们自己可能拥有的自定义 3D 对象 obj 或 mtl 扩展名 但我不确定如何让他
  • XNA中窗口系统的渲染策略(RenderTarget性能)

    我目前正在从头开始为 XNA 游戏创建一个窗口系统 我主要针对 Windows 进行开发 但谁知道我将来可能支持哪些平台 如果您知道本机 Direct3D 的这一点 请随意回答 因为性能语义应该类似 如果可能 请考虑如果目标平台是 X Bo
  • 将 3D 场景导入babylonJS

    所以我今天读到巴比伦JS http blogs msdn com b eternalcoding archive 2013 06 27 babylon js a complete javascript framework for build
  • 如何从横滚、俯仰和偏航获取相机向上矢量?

    我需要从滚动角 俯仰角和偏航角 以度为单位 获取相机的向上矢量 以获得正确的外观 我已经尝试了几个小时不同的事情 但没有运气 这里的任何帮助将不胜感激 横滚 俯仰和偏航定义 3 轴旋转 从这些角度 您可以构建一个 3x3 变换矩阵来表达该旋
  • 如何向 3D 表面添加文本

    我使用plot surface 创建了具有平行四边形底座的矩形棱柱 我需要向其中一个表面添加一些文本 我试过ax text 3 0 5 1 red 1 1 0 color red 但文本在表面上不可见 import matplotlib p
  • 无法使用 vcglib 简化 3D 模型,断言“0”失败

    I used vcglib https github com cnr isti vclab vcglib简化 3D 模型文件 我使用了 master a8e87662 git 存储库 我运行示例 trimesh clustering htt
  • 如何使用 matplotlib 将 3d 数据单位转换为显示单位?

    这可能有点疯狂 但我正在尝试使用 matplotlib v1 1 0 创建 3d 散点图的可点击图像图 我已经阅读了如何对二维图进行操作 参见这个博客 http hackmap blogspot com 2008 06 pylab matp
  • 在 iOS 上的 SceneKit 中导入 3d 模型

    从 URL 导入 obj 文件并将其转换为 SCNNode 时遇到问题 这是代码 swift3 let url URL init string https cloud box com shared static ock9d81kakj91d
  • 为什么我的 3D 绘图没有显示在 R Studio 绘图查看器中?

    我通常在 RStudio 版本 1 0 44 中查看绘图时没有问题 但是当我尝试查看使用 rgl 包创建的 3D 绘图时 我的 RStudio 绘图查看器中什么也没有出现 我能够毫无问题地绘制图 汽车 散点图 这是我正在使用的代码 inst
  • 加速球之间的碰撞检测

    我正在编写一个物理引擎 模拟器 其中包含 3D 太空飞行 行星 恒星引力 船舶推力和相对论效应 到目前为止 一切进展顺利 但是 我需要帮助的一件事是碰撞检测算法的数学 我使用的运动迭代模拟基本上如下 注意 3D 矢量全部大写 For eac
  • 3D 图形批处理

    很多网站 文章都说 批量 批 批 有人可以解释一下着色器中的 批处理 代表什么吗 即 是否 改变纹理 更改任意着色器变量 意味着某些东西不能 批处理 最简单的总结方法就是尝试尽可能少地调用 API 来绘制您需要绘制的内容 使用顶点数组或 V

随机推荐

  • 【机器学习】样本方差和标准差

    S为样本方差 样本方差除以n 1而不是n 是因为样本可能没有全部反映总体 除以n 1 比除以n 的值大一些 从而更准确的接近总体方差 比如总体中有10个颜色的球 而取样本时可能只取了8种 如下图 果冻豆的例子
  • msvcp110.dll丢失的解决方法,大家最常用的三个解决方法【教程】

    win10是一款非常优秀的电脑系统 但有时候也会出现文件错误 比如msvcp110 dll丢失 这个问题可能会导致一些应用程序无法正常运行 甚至可能影响到系统的稳定性 那么 面对这样一个问题 我们应该如何解决呢 今天小编为大家带来的就是ms
  • 程序员如何优雅地转行?35岁老程序员告诉你

    在程序员的圈子里 网上经常热议的话题 比如 什么大龄IT公司职员被劝退 35岁程序员必须得转行 这些话题我觉得还是比较片面的 都是在一定的背景之下才有的个别情况 但是有一部分的程序员想转行这是可观存在的事实 我就是其中的一员 而且我已经通过
  • Pytorch入门教程

    作者简介 大数据专业硕士在读 CSDN人工智能领域博客专家 阿里云专家博主 专注大数据与人工智能知识分享 公众号 GoAI的学习小屋 免费分享书籍 简历 导图等资料 更有交流群分享AI和大数据 加群方式公众号回复 加群 或 点击链接 专栏推
  • 命令行打开TotoiseGit工具界面

    直接在左下角开始中打开它时 会提示 lortoiseGit is a shell extension That means it is integrated into the Windows explorer To use Tortoise
  • 【嵌入式】STM32利用arm-dsp库进行PID调节控制

    目录 一 实验简介 1 原理 2 所用外设 二 代码 1 PWM输出配置 2 定时器触发的DMA传输的ADC 3 主体代码 三 实验结果 在工程实际中 应用最为广泛的调节器控制规律为比例 积分 微分控制 简称 PID 控制 又称 PID调节
  • 重回csdn

    前段时间csdn帐号被盗 后来帐号被封 今刚找回来 所有博文付之一炬
  • Windows与Centos下的深度学习部署

    文章介绍2种深度学习部署思路 1 Windows下部署深度学习 确保只用本地机器也可以跑深度学习 GPU版本 2 Centos下部署深度学习 Windows作为可视化界面 利用Centos的CPU跑深度学习 CPU版本 一 Windows1
  • 程序设计综合实习(C语言):学生成绩文件管理

    一 目的 1 掌握文件指针的概念和运用 2 掌握文件的相关操作 打开 读 写 关闭 3 掌握文件的定位操作 二 实习环境 Visual Stdio 2022 三 实习内容与步骤 1 定义一个结构体数组 存放10个学生的学号 姓名 三门课的成
  • 转:人生比努力更重要的是选择,与时俱进是成功的源泉。

    如果有一天你隔壁开火锅店的张三 卖手机卖得比你好 你不用觉得惊讶 因为 这是一个跨界的时代 每一个行业都在整合 都在交叉 都在相互渗透 移动互联网改变生活 未来我们的生活会是什么样子呢 我们设想一下 晚上带着家人去吃饭 拿出手机点击附近餐厅
  • 汇编语言程序设计的实验环境及上机步骤

    汇编语言源程序编制完成后 在计算机上的操作过程分为四个阶段 编辑 汇编 连接 运行调试 如图1 一 实验环境 汇编语言程序设计的实验环境如下 硬件环境 微型计算机 Intel x86系列CPU 一台 软件环境 Windows98 2000
  • 类和对象

    一 类 每个类都定义了自己的作用域 每个类的成员函数和成员变量都在这个作用域内 成员函数可以任意访问所在类的其他函数和成员变量 C 的封装特性是对外的 在类内是可以任意调用和使用的 类似于C中的结构体 要访问类定义的对象的成员 类定义的对象
  • 通过css实现对勾(√)和叉号(×)

    通过css实现对勾 和叉号 第一种方式 HTML span class status correct span span class status incorrect span CSS correct display inline bloc
  • 字符编码和字符集

    编码和解码 按照某种规则 将字符存储到计算机中 称为 编码 那么 将计算机中的二进制数据按照某种规则解析显示出来 称为 解码 字符编码 就是一套自然语言的字符和二进制数据之间的对应规则 把这种对应规则 写成一张表 就是 编码表 也叫字符集
  • kv遍历

    var builder var builderKey var builderValue for var i 0 i lt message length i var c message charAt i var nextStr message
  • 互联网高可用架构探讨

    高可用指标与问题 高可用 英文单词High Availability 缩写HA 它是分布式系统架构设计中一个重要的度量 业界通常用多个9来衡量系统的可用性 如下表 既然有可用率 有一定会存在不可用的情况 系统宕机一般分为有计划的和无计划的
  • 数码管:3位6脚的数码管分析和编码

    基本简介 一个1位数码管共有8段 ABCDEFG 小数点 如下图 按照我们常规的设计方案一个 IO 口控制一个段 一个1位数码管那么就需要8个IO 当然我们也可以使用扩展 IO 芯片 例如 74HC164 74HC595 那么这种方案就占用
  • Linux 中卷组不真实存在情况下,强制删除卷组及其PV信息

    由于手误删除lVm顺序不对 导致真实pV 已经不存在 但是卷组信息及其PV信息还存在系统中 pvdisplay和vgdisplay都能看到信息 这时候可以到 dev 目录下手动rm 掉 pv 再查看卷组 就真的不存在了
  • Android取消点击效果,Android中如何取消listview的点击效果

    Android中如何取消listview的点击效果 在xml文件里面有listselecter的属性引用 android layout width match parent android layout height wrap conten
  • 【3D游戏基础】蒙皮骨骼动画与骨架

    效果 目标 画出蒙皮动画的骨架 视频 https www bilibili com video BV1pM411m7Yw PPT https zfxdvouj61 feishu cn file boxcnwgESO6zdQetO7oNhKb