我们在程序上使科幻模型复杂化:什么是Greeble以及如何使用它

图片

首先,让我抱怨“ greeble”是从字典中被淘汰的一个可怕的词。

好吧,从灵魂中去除石头,我们转向解释。 Greeble是添加到模型的细小重复细节,以使其具有规模感和某种美感。 得益于经典科幻电影,蘑菇已变得很流行,在电影中,物理雕塑常常是“模特”:


如果您已经从我的拉伸教程中了解了如何拉伸程序网格,那么您将了解如何添加蘑菇。 将简单的蘑菇添加到网格中可以通过将所有网格多边形挤出任意长度来实现

但是,您可能已经注意到,上面的教程仅关注拉伸的三角形,而本文开头的图像是方形蘑菇。 我必须调整网格,以便将其划分为四边形,并且许多网格通常由具有三个以上索引的多边形组成。 因此,在本教程中,我们将学习如何拉伸具有n个索引的多边形并将此算法应用于整个网格以创建蘑菇。 我们还学习了几种方法来改变蘑菇状算法,以获得不太统一的结果。

表面法线


首先,让我们找出如何计算具有任意n个索引的多边形的法线。 如果我们可以假定此多边形是平面的 ,也就是说,它的所有顶点都在同一平面上,则此过程与计算具有三个索引的多边形的法线没有什么不同。

表面法线是垂直于多边形表面的方向,可以通过获取沿多边形边缘指向的两个向量向量积来计算。

然后我们对该向量进行归一化 ,使其长度为1,因为从法线到曲面,我们只需要方向而不是长度。

 函数getFaceNormal(网格,多边形)
   Vec3 v1 =网格:getVertex(多边形[1])
   Vec3 v2 =网格:getVertex(多边形[2])
   Vec3 v3 =网格:getVertex(多边形[3])
   Vec3 e1 = v2-v1
   Vec3 e2 = v3-v2
   Vec3正常= e1:十字(e2)
  返回正常值:normalize()
结束 

如果我们不能自信地假定多边形是平面的,那么上面介绍的算法将首选前两个索引所在的平面。 为了更准确地表示多边形指向的方向,我们可以取边的所有矢量积平均值

 函数getFaceNormal(网格,多边形)
   Vec3 n = Vec3(0,0,0)
  对于我= 1,#poly -2做
     Vec3 v1 =网格:getVertex(多边形[1])
     Vec3 v2 =网格:getVertex(多边形[1+ i])
     Vec3 v3 =网格:getVertex(多边形[2+ i])
     n:加((v2-v1):十字(v3-v1))
  结束
  返回n:归一化()
结束 


显示平面四边形拉伸的示例。

挤压成型


现在我们有了关于表面法线的信息,可以在法线方向上拉伸多边形了。 简而言之,为了拉伸多边形,我们通过沿表面法线方向移动旧顶点来创建新顶点。

更多详细信息:

  1. 沿正常方向在旧峰“上方”创建新峰

    可以如下计算新顶点:

      (旧峰的位置)+(法线方向) 

    这会使旧位置沿表面法线方向“移动”。

    例如,看上面的图像, v1在其上沿法线方向移动到v5。
  2. 创建四边形以连接新顶点和旧顶点。

    应当注意,对于新多边形中的每个索引,都会创建一个新的四边形。

    例如,看一下从v8,v7,v3和v4创建四边形
  3. 新顶点创建新多边形替换旧多边形 例如,看一下从v5,v6,v7和v8创建的四边形。


 函数extrudePoly(网格,polyIndex,长度)
   int [] poly = mesh.polys [polyIndex]
   int [] newPoly = []
   Vec3 n = getFaceNormal(网格,多边形)

   -(1)创建拉伸顶点
  对于j = 1,#poly do
    局部p =网格:getVertex(多边形[j])
     newPoly [#newPoly + 1] =#mesh.verts
     -长度确定挤出的长度
    网格:addVertex(p +(n *长度))
  结束

   -(2)带有四边形的线迹挤压侧面
  对于j0 = 1,#poly做
    本地j1 = j0%#poly + 1
    网格:addQuad(
      聚[j0],
      聚[j1],
       newPoly [j1],
       newPoly [j0]
     )
  结束

   -(3)将现有的面移至凸出的顶点
  对于j = 1,#poly do
     mesh.polys [pi] [j] = newPoly [j]
  结束
结束 


均匀采蘑菇。

所有网状蘑菇


现在我们有了getSurfaceNormal()函数和extrude()函数,蘑菇化非常容易! 我们只需将extrude()函数应用于每个网格多边形 。 我们使用随机长度的挤出,以便每个挤出的多边形的尺寸略有不同,从而产生质感。 下面显示的算法应用于上面显示的多维数据集,该多维数据集完全由四边形组成。

 功能greeble(mesh)
  对于我= 1,#mesh.polys做
     -这些随机值是任意的:p
    浮点长度=随机:getUniformRange(0.1,1.0)
    挤出多边形(网格,i,长度)
  结束
  返回网格
结束 

恭喜,我们如雨后春笋般赚了。 但是我们可以做更多! 现在,如雨后春笋般非常均匀。 这是两个修改示例,使之更加有趣。


修改1:替代品的存在取决于偶然性


这非常简单:只需滚动模具以确定是否应将蘑菇形应用于每个多边形。 因此,蘑菇变得不太均匀。 下面显示的算法应用于上面的多维数据集。

 对于我= 1,#mesh.polys做
    <strong>如果是随机的:机会(0.33),则</ strong>
     浮点长度=随机(0.1,1.0)
     挤出多边形(网格,i,长度)
   结束
 结束
 返回网格
结束 


修改2:添加挤出比例


这需要更改挤出算法。 创建拉伸多边形的顶点时,可以将它们朝多边形的中心减小随机数量,以使对象看起来更有趣。

首先,我们的extrude()函数必须接收一个附加参数,该参数确定新多边形的变窄量。 我们将其定义为称为scale Vec3。 为了将顶点移向中心,我们用scale的值在顶点原始位置多边形中心之间进行插值

(如果您需要了解用于查找多边形中心的算法,建议您快速跳转至三角剖分教程,并阅读有关中点三角剖分(质心三角剖分)的信息。)

  -找到多边形的中心
 Vec3 c =网格:getFaceCentroid(poly)
对于j = 1,#poly do
  局部p =网格:getVertex(多边形[j])
   newPoly [#newPoly + 1] =#mesh.verts
  自我:addVertex(
     math.lerp(cx,px,scale.x)+ nx *长度,
     math.lerp(cy,py,scale.y)+ ny *长度,
     math.lerp(cz,pz,scale.z)+ nz *长度
   )
  网格:addVertex(p +(n *长度))
结束 

现在,您可以通过按每个多边形缩放一个随机值,在蘑菇状算法中使用它。 这样我们就得到了上面显示的图像。

 功能greeble(mesh)
  对于我= 1,#mesh.polys做
    浮点长度=随机:getUniformRange(0.1,1.0)
     Vec3比例=(随机:getUniformRange(0.1,1.0),
                  随机:getUniformRange(0.1,1.0),
                  随机:getUniformRange(0.1,1.0))
    拉伸多边形(网格,i,长度,比例)
  结束
  返回网格
结束 

结束


太好了,我们到了尽头! 希望本教程对您有所帮助。

Source: https://habr.com/ru/post/zh-CN482316/


All Articles