Normalen berechnen mit Winkel / für Smoothing
-
Hallo
weis von euch jemand,
wie die Normalenberechnung mit einem angegebenen Winkel funktioniert?In größeren CAD Programmen heisst die Funktion
- Recalculate Normals - Übergabeparameter: der Winkel
- Smoothing - selber ÜbergabeparameterIn OpenSG ist dies implementiert: calcVertexNormals(geo, deg2rad(30))
OpenSceneGraph, welchen ich verwende, enthält dies leider nicht.wäre sehr nett wenn mir jemand helfen könnte.
Benötige ein Smoothing, im Winkel von 30 Grad
Dankeschön
Gruß Matthias
-
Da werden die Normalen an Eckpunkten "gemittelt" (z.B. durch die Fläche der beteiligten Polygone gewichtet), wenn der Winkel zwischen den Normalen nicht größer als der angegebene Winkel ist. Zumindest kenne ich das noch so, aus damaligen Zeiten.
-
Wie würde das in einer Funktion aussehen?
-
ich kenne das anders.
jedes dreieck regestriert sich an der ecke mit seiner normalen. im zweiten pass geht man fuer jedes dreieck, fuer jede ecke die regestrierten normalen durch und bezieht nur die in seine berechnungen ein, die unter dem schwellenwert sind, bezueglich der normalen des dreiecks.
-
wo kann man solch eine funktion mal anschauen?
kennt von euch jemand ein Beispiel?
mir würde auch pseudocode reichen
-
Gegeben sei ein Array von Vertex-Position und eine Indexed-Triangle-List (diese beinhaltet pro Dreieck jeweils 3 Indizes in das Vertex-Array).
Daraus kannst Du einen Datensatz erzeugen der fuer jede Vertex-Position die anliegenden Dreiecke enthaelt:typedef std::vector<int> TriList; // beliebiger Container TriList* buildTrianglesPerVertex(int *indices, int numTriangles, int numVertices) { TriList *facesAtVertex= new TriList[numVertices]; for (int tri=0;tri<numTriangles;tri++) { for (int index=0;index<3;index++) { // nummer des dreiecks in die entsprechende Vertexliste einfuegen facesAtVertex[*indices++].push_back(tri); } } return faceAtVertex; }
Anhand dessen nimmst Du Dir jetzt jeden Eckpunkt eines Dreiecks und addierst die Normalenvektoren der anliegenden Dreiecke sofern der Winkel zwischen den Dreiecken einen gegebenen Schwellwert nicht ueberschreitet:
Vector* averageFaceNormals(int *indices, Vector *faceNormals, int numTriangles, float threshold) { // threshold ist der maximal erlaubte winkel zwischen zwei flaechen in rad threshold= cos(threshold); // spart acos() bei winkelvergleich // Normalen anlegen (3 pro Dreieck) und mit (0,0,0) initialisieren Vector *averageNormals= new Vector[numTriangles*3]; for (int i=0;i<numTriangles*3;i++) averageNormals[i]= Vector(0,0,0); // alle dreiecke durchgehen for (int tri=0;tri<numTriangles;tri++) { // an jedem eckpunkt den mittelwert aller anliegenden dreiecke bilden for (int index=0;index<3;index++) { // liste der anliegenden dreiecke: const TriList& list= faceAtVertex[*indices++]; Vector average(0,0,0); // alle Flaechen-Normalen summieren for (TriList::const_iterator it= list.begin();it!=list.end();it++) { // winkel zwischen der beiden flaechen bestimmen (dot-product) float angle= faceNormals[*it] * faceNormals[tri]; if (angle>threshold) average+= faceNormals[*it]; } average.normalize(); mVertexNormals[tri*3+index]= average; } } return averageNormals; }
Um die Normalenvektoren pro Vertex zu speichern wuerde ein weiterer Schritt folgen der alle Vertices dupliziert deren Referenz an unterschiedliche Dreiecken auch unterschiedliche Normalen hat und die Indizes entsprechend anpasst.