Quando avevo bisogno di una stima della curvatura della mesh per uno skin shader, l'algoritmo su cui ho finito per sistemarmi era questo:
Innanzitutto, ho calcolato una curvatura scalare per ciascun bordo della mesh. Se il bordo ha posizionip1,p2 e normalin1,n2 , allora ho stimato la sua curvatura come:
curvature=(n2−n1)⋅(p2−p1)|p2−p1|2
Questo calcola la differenza nelle normali, proiettata lungo il bordo, come una frazione della lunghezza del bordo. (Vedi sotto per come mi è venuta questa formula.)
Quindi, per ogni vertice ho osservato le curvature di tutti i bordi che lo toccavano. Nel mio caso, volevo solo una stima scalare della "curvatura media", quindi ho finito per prendere la media geometrica dei valori assoluti di tutte le curvature del bordo in ciascun vertice. Nel tuo caso, potresti trovare le curvature minime e massime e considerare quei bordi come le principali direzioni di curvatura (magari ortonormalizzandoli con il vertice normale). È un po 'approssimativo, ma potrebbe darti un risultato abbastanza buono per quello che vuoi fare.
La motivazione di questa formula è guardare cosa succede in 2D quando viene applicato a un cerchio:
Supponiamo di avere un cerchio di raggio (quindi la sua curvatura è 1 / r ) e di avere due punti sul cerchio, con le loro normali n 1 , n 2 . Le posizioni dei punti, relative al centro del cerchio, saranno p 1 = r n 1 e p 2 = r n 2 , a causa della proprietà che un cerchio o le normali della sfera indicano sempre direttamente dal suo centro.r1/rn1,n2p1=rn1p2=rn2
Pertanto è possibile ripristinare il raggio come o | p 2 | / | n 2 | . Ma in generale, le posizioni dei vertici non saranno relative al centro del cerchio. Possiamo aggirare il problema sottraendo i due:
p 2 - p 1r=|p1|/|n1||p2|/|n2|
p2−p1rcurvature=1r=rn2−rn1=r(n2−n1)=|p2−p1||n2−n1|=|n2−n1||p2−p1|
Il risultato è esatto solo per cerchi e sfere. Tuttavia, possiamo estenderlo per renderlo un po 'più "tollerante" e utilizzarlo su mesh 3D arbitrarie e sembra funzionare abbastanza bene. Possiamo rendere la formula più "tollerante" proiettando prima il vettore sulla direzione del bordo, p 2 - p 1 . Ciò consente che questi due vettori non siano esattamente paralleli (come nel caso del cerchio); proietteremo semplicemente via qualsiasi componente che non sia parallelo. Possiamo farlo punteggiando con il vettore di bordo normalizzato:
curvaturan2−n1p2−p1
curvatura= ( n2- n1) ⋅ normalizzare ( p2- p1)| p2- p1|= ( n2- n1) ⋅ ( p2- p1) / | p2- p1|| p2- p1|= ( n2- n1) ⋅ ( p2- p1)| p2- p1|2
Et voilà, c'è la formula che appare in cima a questa risposta. A proposito, un bel vantaggio laterale dell'utilizzo della proiezione firmata (il prodotto punto) è che la formula dà quindi una curvatura firmata: positiva per convessa e negativa per superfici concave.
Un altro approccio che posso immaginare di usare, ma non ho provato, sarebbe quello di stimare la seconda forma fondamentale della superficie in corrispondenza di ciascun vertice. Questo potrebbe essere fatto impostando una base tangente sul vertice, quindi convertendo tutti i vertici vicini in quello spazio tangente e usando i minimi quadrati per trovare la matrice 2FF più adatta. Quindi le principali direzioni di curvatura sarebbero gli autovettori di quella matrice. Questo sembra interessante in quanto potrebbe farti trovare direzioni di curvatura "implicite" dai vertici vicini senza spigoli che puntano esplicitamente in quelle direzioni, ma d'altra parte c'è molto più codice, più calcolo e forse meno numericamente robusto.
Un documento che adotta questo approccio è Rusinkiewicz, "Stima delle curvature e dei loro derivati su maglie triangolari" . Funziona stimando la matrice 2FF più adatta per triangolo, quindi facendo la media delle matrici per vertice (simile a come vengono calcolate le normali lisce).