Quando eu precisava de uma estimativa da curvatura da malha para um shader de pele, o algoritmo em que acabei decidindo foi o seguinte:
Primeiro, calculei uma curvatura escalar para cada aresta da malha. Se a aresta tem as posições p1,p2 e normais n1,n2 , calculei sua curvatura como:
curvature=(n2−n1)⋅(p2−p1)|p2−p1|2
Isso calcula a diferença nas normais, projetadas ao longo da borda, como uma fração do comprimento da borda. (Veja abaixo como criei esta fórmula.)
Então, para cada vértice, observei as curvaturas de todas as arestas que o tocavam. No meu caso, eu só queria uma estimativa escalar de "curvatura média", então acabei tomando a média geométrica dos valores absolutos de todas as curvaturas de arestas em cada vértice. Para o seu caso, você pode encontrar as curvaturas mínima e máxima e considerar essas arestas como as principais direções da curvatura (talvez ortogonalizá-las com o vértice normal). Isso é um pouco difícil, mas pode fornecer um resultado bom o suficiente para o que você deseja fazer.
A motivação para esta fórmula é observar o que acontece em 2D quando aplicado a um círculo:
Suponha que você tenha um círculo de raio (então sua curvatura é 1 / r ) e você tenha dois pontos no círculo, com suas normais n 1 , n 2 . As posições dos pontos, em relação ao centro do círculo, vai ser p 1 = r n 1 e p 2 = r n 2 , devido à propriedade que um círculo ou esfera normais sempre apontar directamente para fora a partir do seu centro.r1/rn1,n2p1=rn1p2=rn2
Portanto, você pode recuperar o raio como ou | p 2 | / | n 2 | . Mas, em geral, as posições dos vértices não serão relativas ao centro do círculo. Podemos contornar isso subtraindo os dois:
p 2 - p 1r=|p1|/|n1||p2|/|n2|
p2−p1rcurvature=1r=rn2−rn1=r(n2−n1)=|p2−p1||n2−n1|=|n2−n1||p2−p1|
O resultado é exato apenas para círculos e esferas. No entanto, podemos estendê-lo para torná-lo um pouco mais "tolerante" e usá-lo em malhas 3D arbitrárias, e parece funcionar razoavelmente bem. Podemos tornar a fórmula mais "tolerante" projetando primeiro o vetor na direção da aresta, p 2 - p 1 . Isso permite que esses dois vetores não sejam exatamente paralelos (como estão na caixa do círculo); projetaremos qualquer componente que não seja paralelo. Podemos fazer isso pontilhando o vetor de aresta normalizado:
curvaturan2−n1p2−p1
curvature=(n2−n1)⋅normalize(p2−p1)|p2−p1|=(n2−n1)⋅(p2−p1)/|p2−p1||p2−p1|=(n2−n1)⋅(p2−p1)|p2−p1|2
Et voilà, existe a fórmula que apareceu no topo desta resposta. A propósito, um bom benefício lateral do uso da projeção assinada (o produto escalar) é que a fórmula fornece uma curvatura assinada: positiva para superfícies convexas e negativa para superfícies côncavas.
Outra abordagem que posso imaginar usando, mas ainda não tentei, seria estimar a segunda forma fundamental da superfície em cada vértice. Isso pode ser feito configurando uma base tangente no vértice, convertendo todos os vértices vizinhos nesse espaço tangente e usando os mínimos quadrados para encontrar a matriz 2FF mais adequada. Então, as principais direções de curvatura seriam os autovetores dessa matriz. Isso parece interessante, pois pode permitir que você encontre as direções da curvatura "implícitas" pelos vértices vizinhos, sem arestas explicitamente apontadas para essas direções, mas, por outro lado, há muito mais código, mais computação e talvez menos numericamente robusto.
Um artigo que adota essa abordagem é Rusinkiewicz, "Estimando curvas e suas derivadas em malhas triangulares" . Ele funciona estimando a matriz 2FF de melhor ajuste por triângulo e, em seguida, calculando a média das matrizes por vértice (semelhante à forma como as normais suaves são calculadas).