查看: 1853|回复: 2
打印 上一主题 下一主题

[其他] 蒙皮网格中的骨骼权重

[复制链接]

2317

主题

54

听众

2万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
20645
精华
62

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2014-8-31 23:16:56 |只看该作者 |倒序浏览
什么是骨骼权重:
骨骼权重在蒙皮网格中使用,举个例子来说,手腕关节运动时,受到2块主要骨骼的影响,手腕关节可以看作蒙皮网格中的顶点,在Unity中一个顶点最多受4块骨骼的影响,每块骨骼的影响程度有一个百分比,即骨骼权重,所有骨骼权重相加为1. 每个顶点会保存一个影响该顶点的变换数组,这些变换是当前骨骼相对于父对象的变换。利用递归的方式来得到每块骨骼在世界坐标系下的位置,详细关于这些变换的原理,还望从网上找找资料看。


下面这个脚本代码来自官方手册,这里做一下解析,明白了这个代码,以后使用蒙皮网格,操作骨骼权重就不成问题了

using UnityEngine;

using System.Collections;
public class UseMeshBoneWeight : MonoBehaviour {

             public Texture2D tex2D;

void Start() {

  gameObject.AddComponent<Animation>();

  gameObject.AddComponent<SkinnedMeshRenderer>();

  SkinnedMeshRenderer renderer = GetComponent<SkinnedMeshRenderer>();

  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)};//该平面在xy所在的平面

  mesh.uv = new Vector2[] {new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1)};//纹理坐标的左下角为(0,0)

  mesh.triangles = new int[] {0, 1, 2, 1, 3, 2};//右手螺旋,判断面的朝向

  mesh.RecalculateNormals();//重新计算法向量,

  renderer.material = new Material(Shader.Find(" Diffuse"));

  BoneWeight[] weights = new BoneWeight[4];
//这里只用到了2块骨骼,也就是说网格的所有顶点最多受2块骨骼的影响

  weights[0].boneIndex0 = 0;//顶点0 使用的骨骼变换索引为0  可见每个顶点只受到一块骨骼的影响
//所以 当这块影响它的骨骼 的变换发生变化,该顶点将受到影响,这是只有一块骨骼,所以,骨骼变换到
//什么地方,该顶点就从原来的位置&times;(骨骼变换所使用的矩阵)=现在的位置

  weights[0].weight0 = 1;//权重为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;//绑定姿势数组是BoneWeight指定的索引的变换矩阵

  renderer.bones = bones;//这个用来渲染蒙皮网格的Bone用 当骨骼移动的时候 受该骨骼影响的顶点就会应用bindPoses中设定的变换矩阵,这个变换矩阵会和顶点原来的变换位置做乘积

  renderer.sharedMesh = mesh;

                        renderer.material.SetTexture("_MainTex", tex2D);

  AnimationCurve curve = new AnimationCurve();

  curve.keys = new Keyframe[] {new Keyframe(0, 0, 0, 0), new Keyframe(1, 3, 0, 0), new Keyframe(2, 0.0F, 0, 0)};//Keyframe的4个参数为,时间点,该时间点位置的曲线

                        //值 进切线 出切线

  AnimationClip clip = new AnimationClip();

  clip.SetCurve("Lower", typeof(Transform), "m_LocalPosition.z", curve);

  animation.AddClip(clip, "test");

                        animation["test"].wrapMode = WrapMode.PingPong;

  animation.Play("test");

}

}

使用 新建一个GameObject 空的  将该代码附加到该GameObject上,运行 ,可以 在代码中添加材质的纹理
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

hyui    

1

主题

2

听众

6671

积分

高级设计师

Rank: 6Rank: 6

纳金币
2715
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2014-9-1 04:47:30 |只看该作者
Great article !
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-9-22 05:35 , Processed in 0.086796 second(s), 31 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部