Kiedy potrzebowałem oszacowania krzywizny siatki dla modułu cieniującego, algorytm, na którym ostatecznie się zdecydowałem, był następujący:
Najpierw obliczyłem krzywiznę skalarną dla każdej krawędzi siatki. Jeśli krawędź ma pozycje i normalne n 1 , n 2 , to oszacowałem jej krzywiznę jako:p1, p2)n1, n2)
krzywizna = ( n2)- n1) ⋅ ( str2)- p1)|p2)- p1|2)
Oblicza to różnicę w normalnych, rzutowanych wzdłuż krawędzi, jako ułamek długości krawędzi. (Zobacz poniżej, jak wymyśliłem tę formułę).
Następnie dla każdego wierzchołka patrzyłem na krzywizny wszystkich dotykających go krawędzi. W moim przypadku chciałem po prostu skalarnego oszacowania „średniej krzywizny”, więc skończyłem na średniej geometrycznej wartości bezwzględnych wszystkich krzywizn krawędzi na każdym wierzchołku. W twoim przypadku możesz znaleźć minimalne i maksymalne krzywizny i przyjąć te krawędzie za główne kierunki krzywizny (być może ortonormalizując je przy normalnym wierzchołku). To trochę trudne, ale może dać ci wystarczająco dobry wynik, co chcesz zrobić.
Motywacją dla tej formuły jest sprawdzenie, co dzieje się w 2D po zastosowaniu do koła:
Załóżmy, że masz okrąg o promieniu (więc jego krzywizna wynosi 1 / r ) i masz dwa punkty na kole, z ich normalnymi n 1 , n 2 . Pozycje punktów, w stosunku do środka okręgu, będą wynosić p 1 = r n 1 i p 2 = r n 2 , ze względu na właściwość, że normalne koło lub kula zawsze wskazują bezpośrednio od środka.r1 / rn1, n2)p1= r n1p2)= r n2)
Dlatego możesz odzyskać promień jako lub | p 2 | / | n 2 | . Ogólnie jednak pozycje wierzchołków nie będą względne względem środka okręgu. Możemy obejść ten problem, odejmując dwa:
p 2 - p 1r = | p1| / | n1|| p2)| / | n2)|
p2)- p1rkrzywizna = 1r= r n2)- r n1= r ( n2)- n1)= | p2)- p1|| n2)- n1|= | n2)- n1|| p2)- p1|
Wynik jest dokładny tylko dla kręgów i sfer. Możemy go jednak rozszerzyć, aby uczynić go nieco bardziej „tolerancyjnym”, i używać go na dowolnych siatkach 3D, i wydaje się, że działa dość dobrze. Możemy uczynić formułę bardziej „tolerancyjną”, najpierw rzutując wektor na kierunek krawędzi, p 2 - p 1 . To pozwala, aby te dwa wektory nie były dokładnie równoległe (jak w przypadku koła); po prostu rzutujemy każdy komponent, który nie jest równoległy. Możemy to zrobić, kropkując znormalizowanym wektorem krawędzi:
krzywiznąn2)- n1p2)- p1
krzywizna= ( n2)- n1) ⋅ normalizuj ( str2)- p1)| p2)- p1|= ( n2)- n1) ⋅ ( str2)- p1) / | p2)- p1|| p2)- p1|= ( n2)- n1) ⋅ ( str2)- p1)| p2)- p1|2)
Et voila, na początku tej odpowiedzi pojawiła się formuła. Nawiasem mówiąc, miłą zaletą korzystania z podpisanej projekcji (iloczyn punktowy) jest to, że formuła daje podpisaną krzywiznę: dodatnią dla wypukłych i ujemną dla wklęsłych powierzchni.
Innym podejściem, które mogę sobie wyobrazić, ale którego nie próbowałem, byłoby oszacowanie drugiej podstawowej formy powierzchni w każdym wierzchołku. Można to zrobić, ustawiając podstawę styczną na wierzchołku, a następnie przekształcając wszystkie sąsiednie wierzchołki w tę przestrzeń styczną i używając najmniejszych kwadratów, aby znaleźć najlepiej dopasowaną macierz 2FF. Wtedy głównymi kierunkami krzywizny byłyby wektory własne tej macierzy. Wydaje się to interesujące, ponieważ pozwala znaleźć kierunki krzywizny „sugerowane” przez sąsiednie wierzchołki bez żadnych krawędzi wyraźnie wskazujących w tych kierunkach, ale z drugiej strony jest o wiele więcej kodu, więcej obliczeń i być może mniej odporny numerycznie.
Artykuł, który przyjmuje takie podejście, to Rusinkiewicz, „Szacowanie krzywizn i ich pochodnych na siatkach trójkątów” . Działa poprzez oszacowanie najlepiej dopasowanej macierzy 2FF na trójkąt, a następnie uśrednienie macierzy na wierzchołek (podobnie jak w przypadku obliczania gładkich normalnych).