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:
- 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. - 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 . - 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ê.