zoukankan      html  css  js  c++  java
  • 【转载】基于平均法线实现顶点网格变形控制的总结

    原文链接:http://blog.csdn.net/haohan_meng/article/details/22640991

      顶点网格的变形功能,这在Unity官方商店的技术展示Demo中有一个案例。自己就是在这个案例的基础上进行的学习。案例中的功能全部都是用JS实现的,自己依样画葫芦,改成了C#,并对其中一些核心代码的工作原理进行了分析与学习,最终形成了这篇总结。其中的不正之处欢迎大家批评指出。

           看到文章的标题,我们可能会想,要完成网格模型的变形,需要哪几个要素? 简单来说,就是两个:顶点与法线。其中,顶点指的是网格模型的每一个顶点的坐标位置(模型的自身坐标系);法线指的是每一个顶点的法线(表示顶点方向的单位向量)。它们都属于网格模型顶点属性的范畴。有了这两个变形的基本要素,我们便可以开始着手实现模型的变形了。在开始实现以前,先让我们对模型变形的基本套路有个大体了解,这好让我们按图索骥,有的放矢。

            当我们在进行网格模型的变形时,通常会按照下面的几步去做:

            1、选择触发条件。所谓触发条件,是指触发网格模型变形的前提条件,常用的有物体间的碰撞、鼠标的点击等。

            2、进行顶点筛选。在触发条件触发变形后,我们需要进行顶点的筛选。所谓顶点筛选,是指通过设定某些条件,对网格模型的全部顶点进行筛选,从而获取到所有我们需要修改的顶点。这是很重要的一步,这一步的核心是顶点的筛选算法,这个算法要根据不同的筛选条件来确定。

            3、计算变化因子。经过顶点的筛选,我们已经知道哪些顶点是需要修改的了。而所谓的变化因子,就是告诉我们,这些顶点要发生怎样的位置变化,要怎样修改。针对需要修改的顶点,选取合适的算法,计算它们各自的变化因子。这同样也是一步核心操作。

            4、完成顶点变形,使修改生效。在这一步,我们需要把计算得来的变化因子应用到经过筛选的顶点上,并使这些修改最终生效,从而实现顶点网格的变形效果。

            接下来,让我们根据以上总结的4个步骤,结合代码,来具体实现顶点网格的变形功能。

            在本例中,我们使用通过鼠标点击,实现模型变形(凹陷或凸起)的方式。因此,第一条中的触发条件,就是鼠标的点击。

            首先,在Update函数中检测鼠标的左键是否按下,如果没有按下,则直接返回跳出,不进行后续的处理,否则,继续向后执行。

     

             通过从鼠标所在的位置发射射线,来进行碰撞检测。如果有碰撞发生,就记录下相关的碰撞信息(填充RaycastHit结构),并获取碰到的网格模型的网格过滤器。然后计算碰撞点在模型自身坐标空间中的位置。到这里,我们的触发条件部分就可以算完成了。在进入顶点筛选之前,还有一个至关重要的概念没有介绍——什么是平均法线法。这一部分的代码如图所示:

     

     

            那么什么是平均法线?顶点的法线,描述了每一个顶点的方向。我们进行顶点网格的变形,实质上就是改变了顶点的位置。那么顶点的位置要如何变化,这需要一个方向,来描述位置的改变。我们要求取的这个平均法线,就表示了所有要改变位置的顶点的一个公共变化方向。有了这个平均法线,我们就知道顶点该向哪个方向去移动,而置于移动多少,这将在稍后说明。

            自己在初次阅读这段求取平均法线的代码时,心里一直有个疑惑,就是为何用平均法线就能近似代表顶点的变化方向呢?答案是,这是对现实的模拟。在网上看到过一篇论文《基于平均法线法自动生成汽车覆盖件冲压方向研究》的摘要,里面就描述了在物体表面受力时,基于平均法线来自动获得冲压方向(受力方向,也就是模型的变形方向)的方法。正是看到了这里,才让我对平均法线的意义茅塞顿开,原来这完全是对现实情况的模拟。那么我们该如何来求这个平均法线,这就让我们进入第二部分,顶点筛选,来分析代码中的DeformMesh函数。

     

            顶点的筛选,我们采用了计算每一个顶点到碰撞点距离的方式。事先设定一个变形半径,在这个半径内的顶点就是我们要修改的点,反之不予处理。这里的距离比较我们采用了平方的方式,目的是为了减少开销。当我们已经获取到所有需要修改的顶点,接下来就是计算它们的平均法线,也就是确定变形的方向。平均法线的计算,采用了每一个顶点的法线求取矢量和的方式,并且用了加权平均,这里的权重因素考虑的是顶点到碰撞点的距离,因为离碰撞点越近,受到的影响也就越大,那么对最后得到的平均法线的影响就大。在根据距离求取权重因子的过程中,使用了线性的计算方式,公式如代码中的LinearFallOff函数所示。好了,最后将计算得出的平均法线进行标准化,因为我们只需要它的方向,而标准化将有助于我们的计算。代码如图所示:

     

             接下来,有了每一个顶点的位置变化方向,我们还要求出上面所说的变化距离,即在平均法线所表示的方向上移动多少,也就是求第三步中的变化因子。每一个顶点的变化因子,实质上也是一个权重,因为顶点距离碰撞点越近,变形距离肯定越大,也就是权重越大。这里的权重计算,我们采用了高斯模糊的方式,通过高斯分布的二维密度函数,来计算每一个顶点的概率大小,并将此概率作为权重来使用。不过,自己在这里也有个问题尚未解决,那就是代码中的高斯计算公式,是怎样通过高斯分布的密度函数换算过来的,因为它并非是该密度函数的标准书写方式。另外,对于高斯模糊的算法,自己也准备整理一篇总结,它的用处实在是太大了。代码如图所示:

             最后,我们只要把修改的顶点赋给mesh的顶点数组,然后执行第四步的使用修改生效,完成变形效果就可以了。

     

             总结写的有些仓促,不对的地方十分欢迎大家的批评,对于自己还没弄明白的问题,还要继续探究。看看窗外,还是雾霾,这个大清早,又是新的一天了: )

  • 相关阅读:
    lnmp 优化
    linux-lnmp 搭建报错
    nfs 配置
    全网备份脚本rsync
    .Net面试题二
    软件设计模式
    .Net面试题一
    asp.net运行机制
    NHiberante的优缺点
    什么是架构、框架、模式和平台
  • 原文地址:https://www.cnblogs.com/jeason1997/p/4821008.html
Copyright © 2011-2022 走看看