捏脸系统中的差异矩阵推导

在上篇文章<<Unity 人物捏脸的实现>>中,最后留了一个悬念,就是

差异矩阵

这个矩阵是怎么计算来的。这里给大家补上。

几何意义

Mesh绑定(图1)

还是以上图为例,蓝色小球Vertex是Mesh上的一个顶点,它绑定骨骼BN_20(在BN_20本地坐标空间下,坐标值保持不变)。捏脸的时候不可能逐顶点调整位置,那就要调整骨骼,因为存在绑定关系,所以调整骨骼的时候,顶点小球的世界坐标也会跟着变化,以保证在骨骼本地坐标下位置不变。有点绕口。好好理一下就明白了。
假设调整骨骼到一个新的位置,比如我们把骨骼BN_10绕Z轴旋转90度(会带动BN_20移动,进而影响顶点蓝色小球)


骨骼旋转后顶点的新位置(图2)

现在顶点已经到了新位置,我们的目的是要计算新位置(图2中的篮球位置)相对于调整前的骨骼(图1中的BN_20)的Bindpose(从模型空间到骨骼本地坐标的转换矩阵),这样,骨骼动画把骨骼重置位置后,小球就能保证还在调整后的位置了。我们为了达到下图的效果:


目的效果(图3)

还记得上篇文章中的公式吧:


移动顶点,得到新的坐标(图4)

这里这个M_translation就是一个矩阵,原来的骨骼乘上这个矩阵,就会到新的位置(红色骨骼从图1的位置到图2的位置),同样,顶点位置乘上这个矩阵,也会到新的位置(由图1到图2中篮球位置).所以我们可以叫它差异矩阵。

差异矩阵推导

假设原本(图1中)BN_20本地空间内的一点A

两边都乘上差异矩阵就会到新位置(图2中).

A的新位置,即可以用原来骨骼的本地到世界矩阵乘上差异矩阵来求出,也可以用新姿态下骨骼的本地到世界矩阵来求出,则推导出

其中骨骼的新旧姿态下的本地到世界矩阵都是已知量,则差异矩阵就可以求出来了。
图5

第一行,可以看做等号两边的尾部都乘上原骨骼的本地到世界矩阵的逆矩阵,则左边成了差异矩阵乘以单位矩阵,右边就是结果。其中本地到世界的逆矩阵就是世界到本地矩阵,所以推出第二行。这里的M_delta就是图4中的M_translation,命名有点混乱。上篇文章说了图4中下面一行括号中的就是新的bindpose,把图5结果带入图4的括号中,则
新的Bindpose

对应的代码如下:
Matrix4x4 newBindPose = oldBone.transform.worldToLocalMatrix * newBone.transform.localToWorldMatrix * oldBone.transform.worldToLocalMatrix * mesh.localToWorldMatrix;

至此骨骼的新Bindpose已经计算完毕,下面给Mesh应用上,这样骨骼位置不变,但是顶点相对于骨骼的位置发生了改变,骨骼动画驱动骨骼不停变化过程中,顶点始终和骨骼保持新的相对位置,从而达到捏脸的效果。应用新的bindpose代码入下:

    //给模型应用新的BindPose
    private static void ApplyNewBindpose(GameObject meshObj, Dictionary<string, Matrix4x4> bindposes)
    {   
        SkinnedMeshRenderer smr = meshObj.GetComponent<SkinnedMeshRenderer>();
        if (smr == null)
        {
            Debug.LogError("Not found SkinnedMeshRenderer " + meshTransform.name);
            return;
        }
        //实例化一份新的mesh,因为要修改mesh的数据,原始的mesh不要动,只读
        Mesh mesh = GameObject.Instantiate<Mesh>(smr.sharedMesh);
        
        Matrix4x4[] bindposes = mesh.bindposes;
        Transform[] bones = smr.bones;
        for (int i = 0; i < bones.Length; ++i)
        {
            if (bindposes.ContainsKey(bones[i].name))
            {
                bindposes[i] = bindposes[bones[i].name];
            }
        }

        mesh.bindposes = bindposes;
        smr.sharedMesh = mesh;
    }

今天的内容都是数学公式,比较枯燥,大家如果不喜欢推导过程,可以直接拿结果去用,bindpose_new那个公式。
好了,捏脸系统的完整思路就是这样了,欢迎大家指出错误和不足之处,共同进步。
【转载请注明出处】

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容