当前位置: 首页 > news >正文

unity3d中的BlendShape混合动画

unity3d中的BlendShape混合动画

https://blog.csdn.net/ychl87/article/details/11605339

一.unity3d中加载模型时,网格顶点发生变化的解决办法。

unity3d中mesh网格为三角网格,目前unity3d直接导入模型时,会使得模型的顶定点数发生改变。解决的办法:在project中点击已经加载的模型,在Import Setting中将Normals设为None,点击Apply。然后再将Normals设为Import,重新加载,再点击Apply。


二.unity3d中BlendShape混合动画编程

主要参考了http://forum.unity3d.com/threads/15424-Morph-Target-Script。

在unity3d中使用Mesh.vertices获得顶点位置,使用Mesh.normal获得顶点法线。当BS模型的权重时,需要重新计算Mesh.vertices和Mesh.normal,再使用RecalculateBounds重新计算BS模型边界。


定义BS类,记录每个BS模型的顶点位置,顶点法线


    internal class BlendShapeVertex
        {
            public int originalIndex;
            public Vector3 position;
            public Vector3 normal;
        }
     
        internal class BlendShape
        {
            public BlendShapeVertex[] vertices;// = new Array();
        }


其中定义originalIndex是为了记录某个顶点的索引值。因为在BS模型中,很多顶点位置都与对应的基础表情顶点位置一致,所以在重新计算新的混合表情时,就不需要再计算这些点,提高运算速率。


建立BS模型数据

    void BuildBlendShapes()
        {
     
            blendShapes = new BlendShape[attributeMeshes.Length];
     
            for (int i = 0; i < attributeMeshes.Length; i++)
            {
                blendShapes[i] = new BlendShape();
                
                int blendShapeCounter = 0;
                for (int j = 0; j < workingMesh.vertexCount; j++)
                {
                    
                    if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j])
                    {
                        blendShapeCounter++;
                    }
                }
                
                blendShapes[i].vertices = new BlendShapeVertex[blendShapeCounter];
                blendShapeCounter = 0;
                for (int j = 0; j < workingMesh.vertexCount; j++)
                {
                    if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j])
                    {
                        BlendShapeVertex blendShapeVertex = new BlendShapeVertex();
                        blendShapeVertex.originalIndex = j;
                        blendShapeVertex.position = attributeMeshes[i].vertices[j] - workingMesh.vertices[j];
                        blendShapeVertex.normal = attributeMeshes[i].normals[j] - workingMesh.normals[j];
     
                        blendShapes[i].vertices[blendShapeCounter]=blendShapeVertex;
                        blendShapeCounter++;
                    }
                }
            }
        }


BS融合


    public void SetMorph()
        {
            Vector3[] morphedVertices = sourceMesh.vertices;
            Vector3[] morphedNormals = sourceMesh.normals;
     
            for (int j = 0; j < attributeMeshes.Length; j++)
            {
                if (!Mathf.Approximately(attributeProgress[j], 0))
                {
                    for (int i = 0; i < blendShapes[j].vertices.Length; i++)
                    {
                        int a = blendShapes[j].vertices[i].originalIndex;
                        if(a!=i)
                        {
                            int aa = 0;
                        }
                        morphedVertices[blendShapes[j].vertices[i].originalIndex] += blendShapes[j].vertices[i].position * attributeProgress[j];
                        morphedNormals[blendShapes[j].vertices[i].originalIndex] += blendShapes[j].vertices[i].normal * attributeProgress[j];
                    }
                }
            }    
            workingMesh.vertices = morphedVertices;
            workingMesh.normals = morphedNormals;
            workingMesh.RecalculateBounds();
        }


unity3d中BlendShape融合

    using UnityEngine;
    using System.Collections;
     
    public class MorphTargets : MonoBehaviour {
     
        internal class BlendShapeVertex
        {
            public int originalIndex;
            public Vector3 position;
            public Vector3 normal;
        }
     
        internal class BlendShape
        {
            public BlendShapeVertex[] vertices;
        }
     
        public Mesh sourceMesh; //The original mesh
        public Mesh[] attributeMeshes; //The destination meshes for each attribute.
        public float[] attributeProgress;
        private BlendShape[] blendShapes;
        private Mesh workingMesh;
     
        void Awake()
        {
            attributeProgress = new float[attributeMeshes.Length];
            for (int i = 0; i < attributeMeshes.Length; i++)
            {
                if (attributeMeshes[i] == null)
                {
                    Debug.Log("Attribute " + i + " has not been assigned.");
                    return;
                }
            }
            MeshFilter filter = gameObject.GetComponent(typeof(MeshFilter)) as MeshFilter;
            filter.sharedMesh = sourceMesh;
            workingMesh = filter.mesh;
            
            int vertexCount = sourceMesh.vertexCount;
            for (int i = 0; i < attributeMeshes.Length; i++)
            {
                if (attributeMeshes[i].vertexCount != vertexCount)
                {
     
                    Debug.Log("Mesh " + i + " doesn't have the same number of vertices as the first mesh");
                    return;
                }
            }
     
            BuildBlendShapes();
        }
     
        void BuildBlendShapes()
        {
     
            blendShapes = new BlendShape[attributeMeshes.Length];
     
            for (int i = 0; i < attributeMeshes.Length; i++)
            {
                blendShapes[i] = new BlendShape();
                
                int blendShapeCounter = 0;
                for (int j = 0; j < workingMesh.vertexCount; j++)
                {
                    
                    if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j])
                    {
                        blendShapeCounter++;
                    }
                }
                
                blendShapes[i].vertices = new BlendShapeVertex[blendShapeCounter];
                blendShapeCounter = 0;
                for (int j = 0; j < workingMesh.vertexCount; j++)
                {
                    if (workingMesh.vertices[j] != attributeMeshes[i].vertices[j])
                    {
                        BlendShapeVertex blendShapeVertex = new BlendShapeVertex();
                        blendShapeVertex.originalIndex = j;
                        blendShapeVertex.position = attributeMeshes[i].vertices[j] - workingMesh.vertices[j];
                        blendShapeVertex.normal = attributeMeshes[i].normals[j] - workingMesh.normals[j];
     
                        blendShapes[i].vertices[blendShapeCounter]=blendShapeVertex;
                        blendShapeCounter++;
                    }
                }
            }
        }
     
     
        public void SetMorph()
        {
            Vector3[] morphedVertices = sourceMesh.vertices;
            Vector3[] morphedNormals = sourceMesh.normals;
     
            for (int j = 0; j < attributeMeshes.Length; j++)
            {
                if (!Mathf.Approximately(attributeProgress[j], 0))
                {
                    for (int i = 0; i < blendShapes[j].vertices.Length; i++)
                    {
                        int a = blendShapes[j].vertices[i].originalIndex;
                        if(a!=i)
                        {
                            int aa = 0;
                        }
                        morphedVertices[blendShapes[j].vertices[i].originalIndex] += blendShapes[j].vertices[i].position * attributeProgress[j];
                        morphedNormals[blendShapes[j].vertices[i].originalIndex] += blendShapes[j].vertices[i].normal * attributeProgress[j];
                    }
                }
            }    
            workingMesh.vertices = morphedVertices;
            workingMesh.normals = morphedNormals;
            workingMesh.RecalculateBounds();
        }

————————————————
版权声明:本文为CSDN博主「ychl87」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ychl87/article/details/11605339

 

 

 

 

 

 

相关文章:

  • Unity-Animator深入系列---状态机面板深入
  • 为Unity3D创建素材(2):模型、绑定、动画
  • 在Unity中实现BlendShape表情和骨骼动画混合的实践
  • Unity通过导入器优化动画关键帧数据
  • Unity技术分享(58)|粒子系统优化 | 同屏HUD过多| ResampleCurves的作用...
  • Nebula3 RTTI Tips Tricks
  • UE4 Material_01:堡垒之夜砍伐树木效果
  • Unity Avatar Mask 动画混合
  • Unity3d 导入fbx文件 Mecanim装备错位的解决方法
  • unity 对Animator动画系统的研究
  • Fbx 对应序列化
  • Max 中制作 BlendShape 的关键帧动画
  • Unity 中使用 Animator 控制 BlendShape 的 AnimationClip 播放
  • Unity BlendShape 表情编辑器设计
  • eclipse代码自动换行:wordwrap
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 时间复杂度分析经典问题——最大子序列和
  • co.js - 让异步代码同步化
  • HashMap剖析之内部结构
  • Javascript编码规范
  • leetcode386. Lexicographical Numbers
  • Quartz初级教程
  • Redis字符串类型内部编码剖析
  • SQLServer之创建显式事务
  • unity如何实现一个固定宽度的orthagraphic相机
  • 笨办法学C 练习34:动态数组
  • 从PHP迁移至Golang - 基础篇
  • 反思总结然后整装待发
  • 今年的LC3大会没了?
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 看域名解析域名安全对SEO的影响
  • 力扣(LeetCode)56
  • 追踪解析 FutureTask 源码
  • No resource identifier found for attribute,RxJava之zip操作符
  • # Panda3d 碰撞检测系统介绍
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (14)Hive调优——合并小文件
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • (五)IO流之ByteArrayInput/OutputStream
  • (转) 深度模型优化性能 调参
  • (转)http协议
  • (转)ObjectiveC 深浅拷贝学习
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET Framework与.NET Framework SDK有什么不同?
  • .NET 动态调用WebService + WSE + UsernameToken
  • .NET 设计一套高性能的弱事件机制
  • .net的socket示例
  • .net流程开发平台的一些难点(1)
  • .NET微信公众号开发-2.0创建自定义菜单
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • @Autowired和@Resource装配
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——