oi eu sou um novato completo em computação gráfica, desculpe se é uma resposta estúpida. Estou tentando criar um mecanismo 3D simples a partir do zero, mais para fins educacionais do que para uso real.
por enquanto eu computo apenas face normais. nesse caminho:
Eu tenho um objeto de superfície com dentro de uma lista de triângulo. eu computo normais dentro da classe Triangle, desta maneira:
triangle.computeFaceNormals() {
Vec3D u = v1.sub(v3)
Vec3D v = v1.sub(v2)
Vec3D normal = Vec3D.cross(u,v)
normal.normalized()
this.n1 = this.n2 = this.n3 = normal
}
e ao construir a superfície:
t = new Triangle(v1,v2,v3)
t.computeFaceNormals()
surface.addTriangle(t)
e acho que essa é a melhor maneira de fazer isso .. não é?
agora .. isso funciona, ok. mas a luz não está suavizada. Eu estou tentando calcular também normais de vértice. (estou testando meu motor com superfícies tubolares, para que eu tenha quase todo o vértice compartilhado com mais de um triângulo)
Eu encontrei este algoritmo simples: flipcode vértice normal, mas .. hei este algoritmo tem .. complexidade exponencial? (se minha memória não falhar no meu conhecimento em ciência da computação ..) (por outro lado .. ele possui 3 loops aninhados .. não acho que seja a melhor maneira de fazê-lo ..)
alguma sugestão?
t
é o resultado decomputeFaceNormals
(que não retorna nada), não um triângulo.Respostas:
"Melhor" é bastante subjetivo - envolverá pesar o que você precisa do algoritmo, em comparação com entradas, complexidade de tempo de execução e outras propriedades.
Dito isto, tanto a sua abordagem quanto a abordagem do FlipCode vinculado são razoáveis em termos de produção de resultados utilizáveis (você pode simplesmente copiar suas 'normais de rosto' para cada vértice, se não estiver compartilhando instâncias reais de vértices entre triângulos, o que não estou claro). do seu código). Outras técnicas incluem ponderar a contribuição de cada face normal pelo tamanho do ângulo feito com cada face compartilhada pelo vértice.
Você está certo, pois a abordagem FlipCode parece subótima como está escrita, mas pode ser mal especificada: é um pouco incerto se pretende ou não sugerir que o segundo loop atravesse todas as faces do modelo, em comparação com as poucas faces que compartilham o mesmo. vértice em questão. Se você tiver as informações de adjacência para reduzir o espaço de pesquisa do segundo loop, isso se tornará menos preocupante. É claro que você pode não ter essas informações de adjacência - isso é o que quero dizer com considerar quais entradas você tem disponível para o seu algoritmo.
Se você não deseja apenas copiar a face normal para os vértices, ou está compartilhando vértices e não deseja dividi-los, pode:
Isso pressupõe que cada triângulo está realmente referenciando cada vértice em vez de armazenar uma cópia dele - não sei qual idioma você está usando, então não sei se é esse o caso ou não.
fonte
Josh Petrie tem razão. Se você deseja calcular valores normais do vértice, deve ponderar a contribuição do triângulo por ângulo. Mas você pode usar uma solução ingênua e apenas somar todas as normais de todas as faces ao redor do vértice.
Então você apenas calcula todos os normais normais e os normaliza. Em seguida, defina todas as normais do vértice para zero. Em seguida, para cada face (triângulo), adicione seu normal a todos os seus vértices. Em seguida, normalize todas as normais do vértice. E está feito.
Não é muito correto, mas pode ser o suficiente.
E o seu cálculo normal do rosto acima - está correto, mas você deve saber de que lado as cabeças normais. Pode subir ou descer. Depende do produto cruzado - AxB não é o mesmo que BxA - fornece o vetor oposto.
fonte
Vamos supor que temos um cubo feito de 6 retângulos. Já sabemos que o vértice normal de um cubo não é a soma normalizada das faces da conexão devido à aresta aguda. Se você criar um mapa do valor do vértice e os diferentes vértices normais para um cubo, você terá 3 normais para cada vértice.
Mantendo o ponto acima em mente, é assim que eu calculo os vértices normais (eu testei e estou usando).
Cada face controla os valores normais do vértice a serem usados, pois duas faces podem compartilhar um vértice, não significa que o vértice normal será o mesmo para cada face.
Vamos supor que estamos tentando calcular o vértice normal para vert ao renderizar face2 .
vert é compartilhada por face0 , face1 , face2 , face3 e Face4 . Todas as faces acima são vizinhas em ordem e face0 e face4 se conectam para formar um loop.
O vértice normal para vert é a soma de toda a cadeia vizinha conectada à face2 normalizada. A cadeia para se o ângulo entre duas faces vizinhas for superior a 0,8 radianos (ângulo == arccos (crossProduct (faceA.surface_normal, faceB.surface_normal))).
Se o ângulo entre face0 e face1 é superior a 0,8 radiano e o ângulo entre face3 e Face4 é superior a 0,8 radiano do que o vértice normal para vert quando render face2 é normalizar ( surfnormal1 + surfnormal2 + surfnormal3 ).
fonte