3D Kennfeld: beliebige Punkte im 3D-Raum zu einer Fläche verbinden



  • Hallo Grafikspezialisten!

    Ich fighte jetzt schon eine Weile mit OpenGL. Wie man aus vorgegebenen n*m großen Matritzen (Heigh-Maps) eine Fläche aus Vierecken generiert ist ja keine allzu schwierige Aufgabe.

    Mein Problem ist nun, wie ich aus einer beliebigen Punktwolke eine Oberfläche generieren kann, speziell ein 3D-Kennfeld.

    Ich habe dazu ein Koordinatensystem aus Linien. Die Eingangsgrößen sind X1 (x), X2 (y), die Ausgangsgröße ist Y (z). Jede dieser Eingangsgrößen hat einen Bereich von Min/Max in dem Werte auftreten können.
    Meinetwegen

    X1min = -50.0
    X1max = 50.0

    X2min = -10.0
    X2max = 30.0

    Ymin = -5.0
    Ymax = 52.0

    Das Koordinatensystem spannt sich dabei von P(0,0,0) aus in die 3 Koordnatenrichtungen mit jeweils dem Endpunkt 100.

    Der Benutzer soll nun von außen Punkte vorgeben können:

    z.B:

    X1 = 23.5
    X2 = -1.0
    Y = 34.0

    usw.

    und aus dieser vorgegebenen Punktwolke (vielleicht Punkteliste?) soll nun eine Fläche (Kennfeld) generiert werden. Und da stehe ich irgendwie auf'm Schlauch. Gib es vielleicht eine OpenGL-Funktion die mir sowas automatisch aus einer übergebenen Punkteliste generiert? Oder wie wäre es effektiv da ran zu gehen?

    MfG F98.



  • Also du hast ein 1D Array mit Höhenangaben und kennst die Dimensionen des Feldes wenn ich das richtig verstanden habe ?! Das soll jetzt eine 3D Darstellung a la Heightmap werden oder wie ? 😕



  • Ich habe nur die Punkte in beliebiger Reihenfolge (Eingangs- und Ausgangswerte innerhalb des Defibereiches) sozusagen in einer Liste vorliegen. Meinetwegen 5 Punkte. Und diese 5 Punkte sollen eine Oberfläche aufspannen. Das eigentliche Problem dabei ist, die Zugehörigkeit der Punkte zueinander zu ermitteln, also welche Punkt mit welchem durch eine Fläche verbunden werden soll. Ich kann ja nicht einfach jeden Punkt mit jedem verbinden, da kommt ja ein skurriles Gebilde raus, nur eben keine Fläche. 😞



  • Man müsste die Punkte so sortieren das sie auf X und Z Achse ihre Position in einem Raster kriegen.

    Quasi:

    +--------------
    | P        P
    |
    |    P  P
    |
    | P
    |
    

    Dann holst du dir von oben Links an, jeden Punkt und machst einen Triangle-Fan mit den nächstgelegenen Nachbarn.



  • Du meinst also, die Punkte mit sowas verbinden:

    glBegin(GL_TRIANGLE_FAN);
    
    glVertex3f(-1.0f, -0.5f, -4.0f);    // A
    glVertex3f( 1.0f, -0.5f, -4.0f);    // B
    glVertex3f( 0.0f,  0.5f, -4.0f);    // C
    
    ...
    
    glEnd();
    

    warum dazu eigentlich nicht GL_TRIANGLE_STRIP nehmen?

    Das schwierige an der ganzen Sache ist eben, die Liste zu sortieren. Die müßte dann doch eben erst nach X und dann nach Z sortiert werden, oder?


  • Mod

    F98 schrieb:

    Ich habe nur die Punkte in beliebiger Reihenfolge (Eingangs- und Ausgangswerte innerhalb des Defibereiches) sozusagen in einer Liste vorliegen. Meinetwegen 5 Punkte. Und diese 5 Punkte sollen eine Oberfläche aufspannen. Das eigentliche Problem dabei ist, die Zugehörigkeit der Punkte zueinander zu ermitteln, also welche Punkt mit welchem durch eine Fläche verbunden werden soll. Ich kann ja nicht einfach jeden Punkt mit jedem verbinden, da kommt ja ein skurriles Gebilde raus, nur eben keine Fläche. 😞

    wenn du jeden punkt mit jedem verbindest, müßtest du am ende eigentlich einen normalen, convexen körper erhalten.

    aber da gibt es dermassen viele möglichkeiten, das ich garnet wüste wo anzufangen wenn ich es erklären müßte 🙂

    aber es gibt ein ganz derbes problem mit der erzeugung der geometrie, je nachdem welches verfahren man verwendet, wird das ganze anders aussehen. woher soll man nun wissen welches verfahren die dabei ab wohlsten ist?

    rapso->greets();



  • Nuja, Deine Aussage hilft mir aber nicht gerade viel ...



  • rapso schrieb:

    wenn du jeden punkt mit jedem verbindest, müßtest du am ende eigentlich einen normalen, convexen körper erhalten.

    Das bezweifele ich schonmal, denn daraus ergibt sich nur ein Liniengewirr. Oder meinst du vielleicht, das man nicht jeden punkt mit jedem verbindet, sondern alle Kombinationen von 3 Punkten sucht und Dreiecke formt? Dann würde man zwar auch keinen sauber definierten Körper erhalten, aber durch den z-Buffer würde man nur die Dreiecke sehen, die zur konvexen Hülle der Punkte gehören. Die Konvexe Hülle ist also gewissermassen die Oberfläche. Ist es die gesuchte Oberfläche?

    Bye, TGGC (Demo or Die)


  • Mod

    F98 schrieb:

    Nuja, Deine Aussage hilft mir aber nicht gerade viel ...

    schade dass es dir nicht hilft deinen wunsch genauer zu äußern, so wirst du viele versuche brauchen deine wunschoberfläche zu erhalten.

    @TGGC, ja, hast recht, mir ging es um das erscheinungsbild bei allen 3-eck flächemöglichkeiten.

    rapso->greets();



  • So, ich habe mal ein gängiges Beispiel compiliert, allerdings habe ich darin wieder ein 1000x1000 Array verwendet, in dem die Höhenpunkte drin sind. Das näherungsweise Einsortieren der Punktwolke in dieses Array muss ich dann eben extra implementieren.

    http://fatman98.fa.funpic.de/Test/

    Jetzt meine Probleme:

    1. Die 2 Gebirge erscheinen in ihrer Länge und Breite oval, obwohl ich sie aus jeweils 4 Vierecken male, eigenlich müßten die Dinger ja kreisrund sein. Woran liegt das?

    2. Durch die Gebirge sieht mal ab und zu noch den Hintergrund durch, aber eben nicht immer. Wie kann ich das abstellen, die Anweisungen

    glEnable(GL_DEPTH_TEST);              // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);               // The Type Of Depth Testing To Do
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    

    sollten das doch beheben? Tun sie aber nicht.



  • Hi,

    Ich könnte mir vorstellen, dass sich dein Problem mit dem Algorithmus zur Mesh-Optimierung von Hoppe lösen lassen könnte. Vielleicht mit einigen Vereinfachungen.

    Der Algorithmus läuft zwar normalerweise in die andere Richtung (von einem Mesh mit vielen Dreiecken zu einem mit wenigen), er wird allerdings von Hoppe auch dazu benutzt Geometrie aus Punktwolken zu generieren.

    Im Wesentlichen funktioniert er so:
    Gegeben sei eine Menge von Kontrollpunkten (das sind deine Punkte), so wie ein Dreiecksgitter (dazu könnte man das Rechteck [xmin, xmax] x [ymin, ymax] wählen und es durch zwei Dreiecke darstellen). Der Algorithmus modifiziert das Gitter nun so, dass

    1.) der Abstand der Kontrollpunkte zum Gitter minimiert wird
    2.) die Länge der Kanten möglichst klein bleibt
    3.) möglichst wenige Dreiecke verwendet werden.

    Dazu wird zum einen für jede Komponente (x, y, z) ein lineares Gleichungssystem gelöst, so dass 1 und 2 erfüllt sind (die Gitterpunkte werden entsprechend verschoben) so wie in einem anderen Schritt folgende Operationen ausgeführt:

    1.)edge-collapse
    2.)edge-swap
    3.)edge-split

    Die Operationen werden für eine zufällig gewählte Kante nacheinander durchprobiert und falls sie die Energie des Mesh-Kontrollpunkt-Systems reduzieren ausgeführt.
    Die Energie wird definiert als

    E = SummeDerAbständeDerKontrollpunkteZumMesh + c_rep * AnzahlDerGitterPunkte + c_spring * SummeDerKantenlängen

    c_rep, c_spring sind vom Benutzer zu wählende Konstanten.

    Nicht so leicht das in ein paar Zeilen zu quetschen, und auch die Implementierung ist recht aufwändig. Wie gesagt: Unter Umständen reicht es für dein Problem eine einfachere Version des Algorithmus anzuwenden.
    Auch wenn es sehr, sehr Aufwändig ist führt es wahrscheinlich zu den schönsten Ergebnissen!

    Um das paper zu finden einfach bei google suchen:
    Hoppe mesh optimization



  • Ich frag mich natürlich, was passiert, wenn zwei Punkte übereinanderliegen.

    Bye, TGGC (Demo or Die)



  • Der Algorithmus wird die durch die Punke definierte Fläche natürlich nur approximieren.
    Das kann dann entweder so aussehen, dass die Fläche zwischen den Punkten hindurchläuft, oder - das hängt von der Wahl der Konstanten ab - in der Tat eine 'senkrechte Wand' produziert wird.

    Bis jetzt bin ich allerdings davon ausgegangen, dass keine Überhänge zugelassen sind. Genausowenig Punkte die genau übereinander liegen. Ansonsten wäre unsere Fläche nämlich durch die vorgegebenen Punkte nicht mehr eindeutig definiert.



  • Klingt gut und ist interessant, brauch ich aber jetzt nicht mehr. Meine 2 Fragen von Seite 1 wurden noch nicht beantwortet. Gibt es hier keinen der schon mal aus lustigen 4Ecken Oberflächen generiert hat? 😞



  • Na die nächsten. Wird dann natürlich nicht regelmässig. Aber sollte doch klappen!?



  • Hm. Versteh ich jett nicht ganz. Was meinst Du mit "nächsten" und "klappen"?



  • Dein zweites Problem wird wahrscheinlich damit zusammenhängen, dass zNear / zFar zu klein ist.



  • Hi, ich verwende dafür folgende Werte:

    zNear = 0.1F;
    zFar = 12200.0F;

    Mein Koordinatensystem erstreckt sich dabei von 0.0 - 1000.0 in jede Achsenrichtung. Was wären dann sinnvollere Werte für zNear und zFar?


  • Mod

    far muss nicht weiter sein als du sehen kannst, in deinem fall also maximal 1000.f*sqrtf(2.f)

    rapso->greets();



  • Also 1000.0*1.4 ist einfach zu wenig, da ist slbst bei höchstem Zoom nur das halbe Gitter zu sehen. 5000 Muss es schon sein, und selbst da treten diese komischen flackernden Überblendeffekte auf.


Anmelden zum Antworten