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

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值