Complicamos os modelos de ficção científica de maneira processual: o que é Greeble e como usá-lo

imagem

Para começar, deixe-me reclamar que “greeble” é uma palavra terrível a ser banida do dicionário.

Bem, removendo a pedra da alma, passamos às explicações. Greeble são pequenos detalhes repetidos adicionados a um modelo para dar uma sensação de escala e uma certa estética. Os cogumelos se tornaram populares graças aos filmes clássicos de ficção científica, nos quais a escultura física era frequentemente o "modelo":


Se você já sabe do meu tutorial sobre extrusão como extrudar malhas processuais, então entende como adicionar cogumelos. A adição de cogumelos simples à malha pode ser realizada extrudindo todos os polígonos da malha para um comprimento aleatório .

No entanto, você deve ter notado que o tutorial acima trata apenas de triângulos extrudados, enquanto a imagem no início do artigo é quadrada. Eu tive que ajustar a malha para que ela fosse dividida em quadrângulos, e muitas malhas geralmente consistem em polígonos com mais de três índices. Portanto, neste tutorial, aprenderemos como extrudar um polígono com n índices e aplicar esse algoritmo a toda a malha para criar cogumelos. Também aprendemos algumas maneiras de fazer variações no algoritmo crescente para obter resultados menos uniformes.

Superfície normal


Primeiro, vamos descobrir como o normal de um polígono com n índices arbitrários é calculado. Se pudermos supor que esse polígono é plano , ou seja, todos os seus vértices estão no mesmo plano, o processo não difere do cálculo da normal de um polígono com três índices.

A superfície normal é a perpendicular à face do polígono, que pode ser calculada tomando o produto vetorial de dois vetores apontando ao longo da borda do polígono .

Em seguida, normalizamos esse vetor para que seu comprimento seja 1, pois do normal para a superfície precisamos apenas de direção, não de comprimento.

  função getFaceNormal (malha, poli)
   Vec3 v1 = malha: getVertex (poli [1])
   Vec3 v2 = malha: getVertex (poli [2])
   Vec3 v3 = malha: getVertex (poli [3])
   Vec3 e1 = v2 - v1
   Vec3 e2 = v3 - v2
   Vec3 normal = e1: cruz (e2)
   retornar normal: normalize ()
 fim 

Se não pudermos assumir com confiança que o polígono é plano, o algoritmo apresentado acima prefere o plano no qual os dois primeiros índices estão localizados. Para uma representação mais precisa da direção na qual o polígono aponta, podemos obter a média de todos os produtos vetoriais das arestas :

  função getFaceNormal (malha, poli)
   Vec3 n = Vec3 (0, 0, 0)
   para i = 1, #poly -2 do
     Vec3 v1 = malha: getVertex (poli [1])
     Vec3 v2 = malha: getVertex (poli [1+ i])
     Vec3 v3 = malha: getVertex (poli [2+ i])
     n: add ((v2 - v1): cross (v3 - v1))
   fim
   return n: normalize ()
 fim 


Um exemplo mostrando a extrusão de um quadrilátero plano.

Extrusão


Agora que temos informações sobre a superfície normal, estamos prontos para extrudar o polígono na direção normal. Simplificando, para a extrusão do polígono, criamos novos vértices movendo os vértices antigos na direção da superfície normal.

Mais detalhes:

  1. Crie novos picos “acima” dos antigos na direção normal.

    Novos vértices podem ser calculados da seguinte maneira:

      (posição do pico antigo) + (direção normal) 

    Isso "muda" a posição antiga na direção da superfície normal.

    Por exemplo, veja a imagem acima, nela a v1 se move na direção normal para a v5.
  2. Crie quadrângulos para conectar os vértices novos e antigos.

    Note-se que para cada índice no novo polígono, um novo quadrilátero é criado.

    Por exemplo, dê uma olhada em um quad criado a partir das v8, v7, v3 e v4 .
  3. Substitua o polígono antigo por um novo polígono criado por novos vértices. Por exemplo, dê uma olhada em um quad criado a partir das v5, v6, v7 e v8.


  função extrudePoly (malha, poliIndex, comprimento)
   int [] poly = mesh.polys [polyIndex]
   int [] newPoly = []
   Vec3 n = getFaceNormal (malha, poli)

   - (1) Crie verts extrudados
   para j = 1, #poly
     local p = malha: getVertex (poly [j])
     newPoly [#newPoly + 1] = # mesh.verts
     - length determina o comprimento da extrusão
     malha: addVertex (p + (n * comprimento))
   fim

   - (2) Costure os lados da extrusão com quadriláteros
   para j0 = 1, #poly do
     j1 local = j0% #poly + 1
     mesh: addQuad (
       poli [j0],
       poli [j1],
       newPoly [j1],
       newPoly [j0]
     )
   fim

   - (3) Mova a face existente para vértices extrudadas
   para j = 1, #poly
     mesh.polys [pi] [j] = newPoly [j]
   fim
 fim 


Cogumelo uniforme.

Toda a malha de cogumelo


Agora que temos a função getSurfaceNormal () e a função extrude (), é fácil multiplicar os cogumelos! Simplesmente aplicamos a função extrude () a cada polígono da malha . Usamos a extrusão com um comprimento aleatório para que cada polígono extrudado tenha um tamanho ligeiramente diferente, o que cria uma sensação de textura. O algoritmo mostrado abaixo é aplicado ao cubo apresentado acima, que consiste inteiramente em quadrângulos.

  função greeble (malha)
   para i = 1, # mesh.polys do
     - esses valores aleatórios são arbitrários: p
     comprimento do flutuador = aleatório: getUniformRange (0.1, 1.0)
     extrudePoly (malha, i, comprimento)
   fim
   malha de retorno
 fim 

Parabéns, nosso cogumelo ganhou. Mas nós podemos fazer mais! Agora a proliferação de cogumelos é bastante uniforme. Aqui estão dois exemplos de modificações para torná-lo mais interessante.


Modificação 1: a presença de fungling depende do acaso


É bem simples: basta rolar o dado para determinar se o cogumelo deve ser aplicado a cada polígono. Graças a isso, a proliferação de cogumelos se torna menos uniforme. O algoritmo mostrado abaixo é aplicado ao cubo acima.

  para i = 1, # mesh.polys do
    <strong> se aleatório: chance (0,33), então </strong>
      comprimento do flutuador = aleatório (0,1, 1,0)
      extrudePoly (malha, i, comprimento)
    fim
  fim
  malha de retorno
 fim 


Modificação 2: Adicionar escala de extrusão


Isso requer alteração do algoritmo de extrusão. Quando criamos os vértices de um polígono extrudado, podemos reduzi-los em direção ao centro do polígono em uma quantidade aleatória para tornar o objeto mais interessante.

Para começar, nossa função extrude () deve receber um parâmetro adicional que determina a quantidade de restrição do novo polígono. Vamos defini-lo como Vec3 chamado scale . Para mover um vértice em direção ao centro, interpolamos a posição do vértice entre sua posição original e o centro do polígono pelo valor da scale .

(Se você precisar conhecer o algoritmo para encontrar o centro de um polígono, recomendo pular rapidamente para o tutorial sobre triangulação e ler sobre a triangulação do ponto médio (triangulação do centróide).)

  - encontre o centro do polígono
 Vec3 c = malha: getFaceCentroid (poli)
 para j = 1, #poly
   local p = malha: getVertex (poly [j])
   newPoly [#newPoly + 1] = # mesh.verts
   self: addVertex (
     math.lerp (cx, px, scale.x) + nx * comprimento,
     math.lerp (cy, py, scale.y) + ny * comprimento,
     math.lerp (cz, pz, scale.z) + nz * comprimento
   )
   malha: addVertex (p + (n * comprimento))
 fim 

Agora você pode usá-lo no algoritmo de multiplicação escalando por um valor aleatório para cada polígono. Então, temos a imagem mostrada acima.

  função greeble (malha)
   para i = 1, # mesh.polys do
     comprimento do flutuador = aleatório: getUniformRange (0.1, 1.0)
     Escala Vec3 = (aleatória: getUniformRange (0.1, 1.0),
                   random: getUniformRange (0.1, 1.0),
                   random: getUniformRange (0.1, 1.0))
     extrudePoly (malha, i, comprimento, escala)
   fim
   malha de retorno
 fim 

O fim


Ótimo, chegamos ao fim! Espero que este tutorial tenha sido útil para você.

Source: https://habr.com/ru/post/pt482316/


All Articles