Unity | 从建模到蒙皮动画的整个过程

目录

一、顶点数组、索引数组及UV数组

二、Mesh、MeshFilter、MeshRenderer及SkinnedMeshRenderer

1. Mesh

2. MeshFilter

3. MeshRenderer

4. MeshRenderer与SkinnedMeshRenderer(蒙皮网格)

三、Unity中相关组件

1. mesh和material

2. sharedMesh和sharedMaterial

3. materials和sharedMaterials

四、蒙皮骨骼动画

1. 骨骼点

2. 制作蒙皮动画步骤

3. 关键帧

五、网格数据从制作到渲染的过程

六、动态实现从建模到蒙皮动画的整个过程

1. 代码

2. 相关数据

(1)Curve属性效果

(2)mesh数据

3. 整体效果

4. 注意细节


一、顶点数组、索引数组及UV数组

        顶点索引在程序中的表现为,把所有顶点放进一个数组里(顶点数组),再用另一个整数数组作为索引来表达三角形的组成(整数代表顶点数组里的index下标)。 

        有几个索引数据,就有几个UV坐标,它们由两个浮点数组成,这两个浮点数的范围是0到1,0表示贴图的左上角起始位置,1表示贴图的最大偏移位置,也就是右下角,一听UV两个字母我们就应该知道说的是图片上的坐标。

        在绘制3D模型时,除了顶点和索引数组外,还有个数组叫UV数组,这个UV数组是用于存储UV坐标而存在的。由于已经有了索引来表达三角形的三个顶点,所以UV数组不需要再用索引来表达了,只需要按照顶点索引形成的三角形来定制UV的顺序即可。

  • 4个顶点: [(0,0,0),(0,1,0),(1,1,0),(1,0,0)]
  • 顶点索引,表示2个三角形:[0,1,2,2,3,0]
  • UV数组,表示两个三角形上贴图的绘制范围:[(0,0),(0,1),(1,1),(1,1),(1,0),(0,0)]

二、Mesh、MeshFilter、MeshRenderer及SkinnedMeshRenderer

1. Mesh

        网格(Mesh)是数据资源,它可以有自己的资源文件,比如XXX.FBX。网格里存储了顶点、UV、顶点颜色、三角形、切线、法线、骨骼、骨骼权重等提供渲染所必要的数据。

2. MeshFilter

        MeshFilter是承载网格数据的类,网格被实例化后存储在MeshFilter类中。MeshFilter包含两种类型,即实例型和共享型的变量(mesh和sharedMesh),对mesh进行操作将生成新的mesh实例,而对sharedMesh进行操作将改变与其他模型共同拥有的那个指定的网格数据实例。

3. MeshRenderer

        MeshRenderer是绘制网格的类,具有渲染功能,它会提取MeshFilter中的网格数据,结合自身的materials或sharedMaterials进行渲染。

4. MeshRenderer与SkinnedMeshRenderer(蒙皮网格)

        MeshRenderer与SkinnedMeshRenderer这两个组件分别用于渲染3D模型和3D模型动画,它们的模型数据都存储在MeshFilter中,因此它们都依赖于MeshFilter组件。其中,MeshRenderer只负责渲染模型,我们也可以称它为普通网格渲染组件,它从MeshFilter中提取网格顶点数据。而SkinnedMeshRenderer(蒙皮网格)虽然也渲染模型,也从MeshFilter中提取模型网格顶点数据,但蒙皮网格主要用于渲染动画服务,所以蒙皮网格除了3D模型数据外,还有骨骼数据及顶点权重数据。

        如果蒙皮网格上没有存储任何骨骼数据,那么它与普通网格MeshRender的作用没有任何区别,渲染的都是没有动画的3D模型。

        总之,MeshRenderer适用于静态不变形的网格渲染,而SkinnedMeshRenderer适用于需要骨骼动画和变形的网格渲染。在游戏中,常见的角色模型通常会使用SkinnedMeshRenderer来实现骨骼动画,而环境模型和其他静态物体通常会使用MeshRenderer。

三、Unity中相关组件

1. mesh和material

        mesh(见上文)定义了模型的形状和顶点数据,而material定义了模型的外观属性,如颜色、纹理和光照效果。

        mesh和material都是实例型的变量,对mesh和material执行任何操作,都是额外复制一份后再重新赋值,即使只是get操作,也同样会执行复制操作。也就是说,对mesh和material进行操作后,就会变成另外一个实例,虽然看上去一样,但其实已是不同的实例了。

2. sharedMesh和sharedMaterial

        sharedMesh和sharedMaterial与前面两个变量不同,它们是共享型的。多个3D模型可以共用同一个指定的sharedMesh和sharedMaterial,当修改sharedMesh或sharedMaterial里面的参数时,指向同一个sharedMesh和sharedMaterial的多个模型就会同时改变效果。也就是说,sharedMesh和sharedMaterial发生改变后,所有使用sharedMesh和sharedMaterial资源的3D模型都会表现出相同的效果。

3. materials和sharedMaterials

        与material和sharedMaterial一样,materials是实例型的,sharedMaterials是共享型的,只不过现在它们变成了数组形式。

        无论对materials进行什么操作,都会复制一份一模一样的来替换,sharedMaterials操作后,指向这个材质球的所有模型都会改变效果。materials&sharedMaterials和material&sharedMaterial的区别是,materials和sharedMaterials可以针对不同的子网格,material和sharedMaterial只针对主网格。也就是说,material和sharedMaterial等于materials[0]和sharedMaterials[0]。

四、蒙皮骨骼动画

        3D模型要做动作,首先是模型网格上的点、线、面要动起来,只有点、线、面动起来了,每帧渲染的时候才能渲染出不同的网格形状,从而才有看起来会动的画面。那么怎么让点、线、面动起来呢?

        主要有两种方法:一种是用一种算法来改变顶点位置,我们通常称之为顶点动画;另一种是用骨骼的方式去影响网格顶点,我们称之为骨骼动画。这两种动画方式都是通过在每一帧里偏移模型网格上的各个顶点,让模型变形,从而形成动画的效果的。每一帧模型网格的形状不一样,播放时就形成了动画,两种方法虽然方式不同,但都遵循同一个原理。

        刚性层级式动画

        起初3D模型动画只有刚性层级式动画(rigid hierarchical animation),它将整个模型拆分成多个部位,然后按照层级节点的方式安装上去。

        这样,模型以层级的方式布置在节点上,当父节点移动、旋转、缩放时,子节点也随之而动。刚性层级式动画的问题很多,其中比较严重的是关节连接位置常产生“裂缝”,因为它们并不是由一个模型衔接而成的,而是由多个模型拼凑起来的。

        变形目标动画

        变形目标动画(morph target animation)的方法常使用在脸部动画中,它将动画制作成几个固定的极端姿势的模型,然后在两个模型的每个顶点之间做线性插值,脸部动作大约需要50组肌肉驱动,这种复杂细微程度的动画用两个网格顶点之间的线性插值来表现会比较合适。

1. 骨骼点

        骨骼动画由骨骼点组成,骨骼点可以认为是带有相对空间坐标点的数据实体,骨骼动画中可以有许多个骨骼点,但根节点只有一个。(在现代手机游戏中,每个人物骨骼动画的数量一般为30个左右,PC单机游戏中可达75个左右。骨骼数量越多,动画就越有动感,但同时也会消耗掉更多的运算量。)

        骨骼点为树形结构,一个骨骼可以有很多个子骨骼,子骨骼存在于父骨骼的相对空间下,子骨骼与父骨骼拥有相同的功能,由于子骨骼在父骨骼的空间下,因此,当父骨骼移动、旋转、缩放时,子骨骼也随着父骨骼一起移动、旋转、缩放,它们的相对位置、相对角度、相对比例不变。

        在Unity3D的蒙皮网格组件中,bones变量用于存储所有骨骼点,骨骼点在蒙皮网格中是以Transform数组的形式存储的,这一点可以从bones变量就是Transform[]数组类型得知。

        骨骼点可以影响周围一定范围内的顶点,单一顶点也可以受到多个骨骼的影响。除了骨骼数据,模型中的每个顶点都有对其顶点本身影响最多的4个骨骼的权重值,Unity3D对这4个骨骼的权重值进行了存储,将它们存放在BoneWeight的Struct结构中,每个SkinMeshRender类都有一个boneWeights数组变量,用于记录所有顶点的骨骼权重值,那些没有骨骼动画的网格,就没有这些数据。

        从Unity3D的图形质量设置(Quality setting)中,我们可以看到,Blend Weights参数可用于设置一个顶点能被多少骨骼影响。其中有1 Bone、2 Bones、4 Bones等参数,表达的意思分别是一个顶点能被1个骨骼影响,或者被2个骨骼影响,或者被4个骨骼影响。被影响的骨骼数越多,CPU消耗在骨骼计算蒙皮上的时间就越长,消耗量越大。

         骨骼动画是以顶点的骨骼权重数据来决定顶点受哪些骨骼点的影响的,每个顶点都可以受到骨骼点的影响。在Unity3D中,每个顶点最多被4个骨骼点影响,这些数据被存储在BoneWeight实例里,该实例用于描述当前顶点分别受到哪4个骨骼点的影响,它们分别占有多少权重。

        当骨骼点移动时,引擎就会使用这些顶点权重值来计算顶点的旋转度、偏移量和缩放度。 简单来说就是,用顶点上的骨骼权重数据确定该点受到哪些骨骼点的影响,影响的程度有多大。

2. 制作蒙皮动画步骤

        我们制作蒙皮动画通常分为三步:

        第一步是使用3DMax、Maya等3D模型软件在几何模型上构建一系列的骨骼点(bones),并计算出几何模型的每个顶点受这些骨骼点影响的权重值(BoneWeight)。

        第二步是动画师通过3D模型软件制作一系列动画,这些动画都是通过骨骼点的偏移、旋转、缩放来完成的,每一帧都有可能发生变化,关键帧与关键帧之间会补间一些非关键帧的动画。制作完毕后,导出引擎专有的动画文件格式。在Unity3D中,我们以.fbx作为专有格式文件。

        第三步则是在Unity3D中导入并播放动画,播放动画时就已经存储了动画师制作的骨骼点位每帧发生变化的数据,动画序列帧会根据每帧的动画数据来持续改变一系列骨骼点,骨骼点的变化又会导致几何模型网格上的顶点发生相应的变化。

3. 关键帧

        通常我们使用的都是关键帧动画,就是Unity3D里的Animation文件。在某个时间点上对需要改变的骨骼做关键帧,而不是在每帧上都执行关键帧的操作。使用关键帧作为骨骼的旋转位移点,好处是不需要为每帧都设置骨骼点的位置变化,在关键帧与关键帧之间,骨骼位置可以由Animation组件做平滑插值计算,这样可以大大减少数据量,相当于关键帧之间做了补间动画。补间动画的目的就是对需要改变的骨骼做平滑的位移、旋转、缩放的插值计算,从而实时得到相应的结果,以减少数据的使用量。

        由于4×4矩阵能够完整地表达点位的偏移、缩放和旋转等操作,也能通过连续右乘法计算出从根节点到父节点再到子节点上的具体方位,因此4×4矩阵是骨骼点必要的数据,它表达了相对空间的偏移量,即骨骼节点变化矩阵=根节点矩阵×父父父节点矩阵1×父父节点矩阵×父节点矩阵×骨骼节点矩阵。

五、网格数据从制作到渲染的过程

        首先,美术人员制作3D模型并导出成Unity3D能够识别的格式,即.fbx文件,其中已经包含了顶点和索引数据。

        然后在程序中将.fbx实例化成Unity3D的GameObject,它们身上附带的MeshFilter组件存储了网格的顶点数据和索引数据(我们也可以自己创建顶点数组和索引数组,以手动的方式输入顶点数据和索引数据)。

        MeshFilter可用于存储顶点和索引数据,MeshRender或SkinMeshRender可用于渲染模型,这些顶点数据通常都会与材质球结合,在渲染时一起送入图形卡,其中与我们预想的不一样的是,在送入时并不会由索引数据送入,而是由三个顶点一组组成的三角形顶点送入图形卡。接着由图形卡负责处理我们送入的数据,然后渲染帧缓存,并输出到屏幕。

六、动态实现从建模到蒙皮动画的整个过程

1. 代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TestMesh : MonoBehaviour
{public SkinnedMeshRenderer rend;public Animation anim;public AnimationCurve curve;public AnimationClip clip;public string clipName = "test";// Start is called before the first frame updatevoid Start(){// 新建一个动画组件和蒙皮组件gameObject.AddComponent<Animation>();gameObject.AddComponent<SkinnedMeshRenderer>();rend = GetComponent<SkinnedMeshRenderer>();anim = GetComponent<Animation>();// 新建一个网格组件,并编入4个顶点形成一个矩形形状的网格Mesh mesh = new Mesh();mesh.vertices = new Vector3[] { new Vector3(-1, 0, 0), new Vector3(1, 0, 0), new Vector3(-1, 5, 0), new Vector3(1, 5, 0) };mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1) };mesh.triangles = new int[] { 0, 1, 2, 1, 3, 2 };mesh.RecalculateNormals();// 新建一个漫反射的材质球rend.material = new Material(Shader.Find("Diffuse"));// 为每个顶点定制相应的骨骼权重BoneWeight[] weights = new BoneWeight[4];weights[0].boneIndex0 = 0;weights[0].weight0 = 1;weights[1].boneIndex0 = 0;weights[1].weight0 = 1;weights[2].boneIndex0 = 1;weights[2].weight0 = 1;weights[3].boneIndex0 = 1;weights[3].weight0 = 1;// 将骨骼权重赋值给网格组件mesh.boneWeights = weights;// 创建新的骨骼点,设置骨骼点的位置、父骨骼点和位移旋转矩阵Transform[] bones = new Transform[2];Matrix4x4[] bindPoses = new Matrix4x4[2];bones[0] = new GameObject("Lower").transform;bones[0].parent = transform;bones[0].localRotation = Quaternion.identity;bones[0].localPosition = Vector3.zero;bindPoses[0] = bones[0].worldToLocalMatrix * transform.localToWorldMatrix;bones[1] = new GameObject("Upper").transform;bones[1].parent = transform;bones[1].localRotation = Quaternion.identity;bones[1].localPosition = new Vector3(0, 5, 0);bindPoses[1] = bones[1].worldToLocalMatrix * transform.localToWorldMatrix;mesh.bindposes = bindPoses;// 将骨骼点和网格赋值给蒙皮组件rend.bones = bones;rend.sharedMesh = mesh;// 定制几个关键帧curve = new AnimationCurve();curve.keys = new Keyframe[] { new Keyframe(0, 3, 0, 0), new Keyframe(2, -3, 0, 0), new Keyframe(4, 3, 0, 0) };// 创建帧动画clip = new AnimationClip();clip.legacy = true;     //正确clip.SetCurve("Lower", typeof(Transform), "m_LocalPosition.z", curve);//clip.legacy = true;   //错误,应先设置legacy为true,再SetCurve,否则发布exe后报错clip.wrapMode = WrapMode.Loop;// 将帧动画赋值给动画组件,并播放动画anim.AddClip(clip, clipName);anim.playAutomatically = true;anim.clip = clip;anim.Play(clipName);Debug.Log("play");}// Update is called once per framevoid Update(){}
}

2. 相关数据

(1)Curve属性效果

(2)mesh数据

3. 整体效果

4. 注意细节

        clip.legacy的设置要在SetCurve之前,否则发布exe后会报错:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/41762.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虚幻——动画蓝图、状态机制作人物走跑跳动作

一、名词解释 序列——一段动作。 混合空间——混合不同的动作。将多个序列排序播放。 动画蓝图——根据状态播放不同的动画。 二、混合空间制作走跑动作 由于走和跑的动作比较连续&#xff0c;并且都是由速度控制&#xff0c;所以要把待机、走、跑这三个动作混合在一起。 1.创…

Unity UI 做 图表动画

UI分为三张图片&#xff0c;背景图&#xff0c;前景橘色&#xff0c;前景蓝色&#xff0c;三张图片大小一致&#xff0c;前景就是没有图片的image&#xff0c;填充的颜色。形状是通过shader改变的。 这是一个图标的基本结构&#xff0c;center是中心点&#xff0c;1、2、3...是…

广告中oCPX到底是如何进行优化的?

自从Facebook引入oCPM出价以来&#xff0c;国内的头条广告、微信广点通、百度信息流都陆续推出了自己的oCPX出价&#xff0c;oCPX出价已经成为主流广告投放平台的标配。 简单而言&#xff0c;oCPX是一种出价机制&#xff0c;允许广告主按照转化行为成本出价&#xff1b;假设对…

文字转语音神器!

大家好&#xff0c;我是懂王。 经常刷短视频的兄弟应该知道&#xff0c;有很多短视频的字幕都是用机器人语音来制造的&#xff0c;类似于手机上的 AL 助手语音&#xff0c;不过声音比 siri 和小爱同学要难听一点。 虽然这种机器声音听起来略带生硬&#xff0c;然而对于视频创…

语音转文字怎么转?分享这些实用软件

在参加日常工作会议时&#xff0c;有时候大家记录的速度跟不上对方的语速&#xff0c;会导致会议记录不完整&#xff0c;影响到工作效率。有些小伙伴就把会议内容进行录音&#xff0c;待会后再将录音文件进行整理&#xff0c;这样做既方便快捷&#xff0c;同时能提高工作效率。…

chrome文字转语音(tts)

文章目录 一、文章参考二、TTS (Text-To-Speech) 是文本转语音2.1 概念2.2 windows 操作系统2.3 验证是否有Windows TTS&#xff08;语音转文本&#xff09; 三、chrome 文字转语音3.1 Web Speech相关的API实际上有两类3.2 语音合成Speech Synthesis API3.2.1 SpeechSynthesisU…

在线文字转成语音怎么转

很多小伙伴在办公或学习中&#xff0c;经常或需要浏览大量资料。随着时间越来越长&#xff0c;我们的眼睛就会多度疲劳。为了不戴上眼镜&#xff0c;我们只能改变当前的方式&#xff0c;也就是把文字变成语音去听&#xff0c;而不是去看。那么就有小伙伴想问了在线文字转成语音…

体验最佳的一个TTS文字转语音工具

文本转语音 (TTS) 技术在当今的数字世界中变得越来越流行&#xff0c;其应用范围从语音导航到教学视频、教育和娱乐。 TTS 技术允许用户将文本转换为语音&#xff0c;使其成为一种极其方便、高效和灵活的交流方式。 个人的使用场景是抖音短视频语音配音和电影解说&#xff0c;…

一个在线文字转语音工具

一个在线文字转语音工具 因为参加比赛过程中要频繁使用文字转语音的功能&#xff0c;遂写了这个工具&#xff0c;暂时先用着。 工具基于百度API &#xff0c; 目前只支持 1K 以内的文字转语音。 后续版本拟增加讯飞接口&#xff0c;批量转换&#xff0c;语音识别&#xff0c;在…

SpeechSynthesisUtterance文字转语音播报

一、介绍 SpeechSynthesisUtterance是HTML5中新增的API,用于将指定文字合成为对应的语音.也包含一些配置项,指定如何去阅读(语言,音量,音调)等 二、基本属性 var speech new SpeechSynthesisUtterance() speech.lang 获取并设置话语的语言&#xff08;en-US、zh-CN&#x…

文字转语音功能

大家有没有为如何找到一款文字转语音功能还能免费使用&#xff0c;操作简单的网站而苦恼&#xff0c;这边为大家强烈推荐一款操作简单而且免费使用的网站 96编辑器里的文字转语音功能 什么是文字转语音&#xff1f; 顾名思义&#xff0c;文字转语音是将文字转化成语音的形式&…

TTS Text-to-speech(文字转语音)服务

目录 中文帮助文档&#xff1a; 创建语音资源&#xff1a; 填写注册信息&#xff1a; 转到资源服务 编写测试代码(C#)&#xff1a; C#需要的包【NuGet搜索&#xff1a;CognitiveServices】 视频连接&#xff1a; 官网链接&#xff1a;Speech Studio - Microsoft Azure &am…

微软杀疯了,谷歌蒸发1000亿市值作陪,中文编程和它却打起翻身仗

微软VS谷歌&#xff0c;究竟谁是最后赢家&#xff1f; 当微软宣布收购OpenAI开发的ChatGPT的决定一出&#xff0c;Google深感威胁&#xff0c;开发出Gmail的早期员工甚至大胆预测&#xff0c;Google离完全毁灭只剩下一到两年&#xff01; 好歹也在互联网之战中屹立多年&#…

手写 100% 代码的 19 年老程序员,拒绝使用 Copilot、GPT-4 工具后,惨遭淘汰、解雇!...

整理 | 屠敏 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 一个月前&#xff0c;GitHub CEO Thomas Dohmke 为自家的 AI 辅助编码工具 GitHub Copilot X 站台&#xff0c;在全球网络峰会现场&#xff0c;亲自下场体验了一把&#xff0c;最终用 18 分钟编写出了一…

【网工最关心的问题,看Chat GPT怎么回答?】

最近打开微信群聊&#xff0c;都是在说ChatGPT相关内容 那ChatGPT是什么&#xff1f; ChatGPT是由美国人工智能实验室OpenAI开发的一个对话AI模型&#xff0c;于2022年11月正式推出。它因其极其出色的文本生成和对话交互能力在世界范围内迅速走红&#xff0c;五天内用户破百万&…

盘点GPT-4,大语言模型最新综述来了

Datawhale干货 最新&#xff1a;大模型综述&#xff0c;来源&#xff1a;机器之心 为什么仿佛一夜之间&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域就突然突飞猛进&#xff0c;摸到了通用人工智能的门槛&#xff1f;如今的大语言模型&#xff08;LLM&#xff09;…

GPT-4,或许真的可以让“人工”更“智能”

自2018年GPT-1发布起&#xff0c;每年一更新。距离2020年GPT-3发布已有两年&#xff0c;这段时间里&#xff0c;大家都在期待和畅想&#xff0c;GPT-4到底会带来怎样的惊喜。 期间&#xff0c;“通过图灵测试”&#xff0c;“GPT-4Beta版访问权限已提供给某公司”等消息不断&a…

市面上最好用的两款AI换脸开源神器

1.faceswap 地址链接&#xff1a;Welcome - Faceswap 2.swapface 地址链接&#xff1a;Swapface 现在ai是一个非常大的风口&#xff0c;人们都在寻找各种开源的工具。 这两款软件是非常好用的&#xff0c;我测评了很多款其他的软件&#xff0c;包括手机移动端&#xff0c;…

这 10 个好玩的 AI 项目开源了!

今日推荐开源项目目录&#xff1a; 基于 AI 的口语训练平台 一句话生成 3D 模型 歌声转换 识图模型 01 基于 AI 的口语训练平台 Polyglot 是一个开源的基于 AI 的口语训练平台客户端&#xff0c;可以在 Windows、Mac 上使用。 比如你想练习英语口语&#xff0c;只需在该平…

OpenAI 更新了AGI发展路线图

从最近的ChatGPT的表现来看&#xff0c;通往AGI的路径似乎更清晰了。AGI是人类历史上最重要的技术发明之一&#xff0c;将对社会、经济、政治等各个领域产生深远的影响。 OpenAI是一个致力于创造和推广人工智能&#xff08;AI&#xff09;的非营利组织&#xff0c;其目标是实现…