Laden...

Erstellung eines dreidimensionalen interaktiven Fensters zur Darstellung von Kometenbahnen

Erstellt von TheMarksman vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.910 Views
T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren
Erstellung eines dreidimensionalen interaktiven Fensters zur Darstellung von Kometenbahnen

Hallo zusammen!

Ich bin neu hier im Forum und bin mir deswegen auch nicht wirklich sicher, ob dieses Thema wirklich in dieses Forum gehört. Sollte ich mich geirrt haben, dann lasst mir bitte einen kleinen Hinweis zukommen, dann werde ich mich bemühen, es sofort in das richtige Forum zu verschieben!

Kurz zu meiner Person: Ich bin Schüler an einem Gymnasium und Programmieren ist schon seit langem(soferrn man das sagen kann) mein Hobby. Ich nehme an einem Seminar teil, das sich mit Kometen usw. beschäftigt. In diesem Rahmen werde ich auch meine Seminararbeit schreiben, wodurch auch folgende Frage entstaden ist.

Ich will im Rahmen meiner Arbeit ein Programm schreiben, dass die Umlaufbahnen in Universum berechnet und grafisch darstellt. Ich habe mir dazu schon Fachliteratur angeeignet und die mathematischen Berechnungen stellen kein Problem dar.
Nur habe ich mit grafischer Umsetzung nicht viel Erfahrung und habe gehofft, mir von ein paar alten Profis ein paar Tipps geben lassen zu können.
Ich habe mir vorgestellt, dass die grafische Umsetzung meines Programmes in etwa (!) so aussieht, wie dieses Java-Element auf der NASA-Webseite, die unter diesem Link erreichbar ist. Ich habe hierbei beispielsweise den Kometen 1P/Halley ausgewählt.
NASA Website - Orbital Diagram

Es handelt sich hierbei um eine Art dreidimensionalen Raum, den man mit Hilfe von Schiebereglern bewegen kann. Eine Zoom-Funktion wäre auch nicht schlecht. Er soll, wie im Link ersichtlich, Ellipsen enthalten, die in einem bestimmten Winkel zueinander stehen.
Eine ähnliche Umsetzung würde ich in meiner Windows Form Application auch anstreben.

Habt ihr irgendwelche Tipps für mich, wie ich da rangehen kann? Nötige Grundlagen besitze ich. Wenn nicht bin ich jederzeit bereit, mir diese anzueignen. Ich schreibe natürlich in C# und benutze VisualStudio2010 Ultimate Version und besitze zudem noch XNA, falls das weiterhilft.
Ich würde mich über jeden Tipp oder Ratschlag freuen! Wie würdet ihr bei der Realiserung eines solchen Projekts vorgehen? Vielleicht habt ihr auch ein paar Links, die diesen Sachverhalt genauer erklären? Ich bin für jeden konstruktiven Beitag dankbar!

Vielen Dank im Vorraus!

5.658 Beiträge seit 2006
vor 9 Jahren

Hi TheMarksman,

ich hab mal einen Screenshot des Applets an deinen Beitrag angehängt, damit man gleich sehen kann, worum es geht.

Habt ihr irgendwelche Tipps für mich, wie ich da rangehen kann?

Zunächst einmal mußt du, wie bei jedem anderen Programm auch, deine Anforderungen aufschreiben, danach ein Datenmodell entwerfen, das den Anforderungen entspricht, und dann eine Software-Architektur entwerfen, die mithilfe des Models die geforderten grafischen Ausgaben erzeugen kann. Also im Grunde die Schritte, wie sie hier aufgezählt werden: [Artikel] Drei-Schichten-Architektur

Und was die Grafik betrifft: Deine Anforderungen sind demnach, Ellipsen und beschriftete Marker für die Himmelskörper in einem 3D-Raum anzuzeigen. Für 3D-Grafik gibt es mehrere Möglichkeiten (außer XNA, das du ja bereits genannt hast): [FAQ] Wie finde ich den Einstieg in die 3D-Programmierung mit C#?.

Wobei man sich natürlich fragen kann, ob das alles nicht ein bißchen einfacher geht. Zumal Linien und Kurven von der Grafikkarte sowieso nicht wesentlich performanter gerendert werden können, als auf der CPU. Mann könnte z.B. die Planeten- und Kometenbahnen aus dem 3D-Raum in den 2D-Raum projizieren und dann einfach mit Windows Forms zeichen: [Tutorial] Zeichnen in Windows-Forms-Programmen (Paint/OnPaint, PictureBox)

Noch eleganter geht es aber mit WPF. Dort könntest du die Daten der Himmelskörper direkt an die grafischen Objekte wie Ellipsen und Kurven binden.

Christian

Weeks of programming can save you hours of planning

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

Vielen Dank für deine schnelle Antwort!

Dass ich die Planetenbahnen in den zweidimensionalen Raum projeziere, war mein Plan B, falls das mit dem dreidimensionalen nicht klappt.
Der Grund wieso ich mich totzdem an eine 3D Umsetzung mache, ist einfach, weil es weitaus cooler ist:D
Ich werde mich jetzt mal in nächster Zeit in die von dir vorgeschlagenen Themen einarbeiten.
Gibt es eigentlich ein fertiges 3D-Koordinatensystem in den Tiefen der Libaries, das ich verwenden könnte?
Ansonsten werde ich mich mal in den nächsten Tagen genauer damit beschäftigen und dann bei Bedarf konkretere Rückfragen stellen!

Bin natürlich nach wie vor für weitere Vorschläge offen!

Und danke soweit Christian!

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

Hallo zusammen,
ich arbeite gerade wieder an meinem Programm. In meiner Fachliteratur finde ich leider nur einen Quellcode in C++ geschrieben. Dort ist immerwieder die Rede von einem Datentyp Vec3D. Dieser soll, wie aus dem Namen schon ersichtlich, einen dreidimensionalen Vektor darstellen.

Dasselbe Problem besteht mit dem Datentyp Mat3D. Dieser soll eine Matrix darstellen.

Gibt es irgendetwas ähnliches in C#? Oder kann mir jemand einen Tipp geben, wie ich das implimentieren kann?

Ich hoffe einige hier im Forum sind zweisprachig aufgewachsen und können mir helfen;)

Vielen Dank im Vorraus!

5.658 Beiträge seit 2006
vor 9 Jahren

Hi TheMarksman,

Datentypen für 2D- und 3D-Vektoren sowie Matrizen findest du in allen gängigen Bibliotheken. Sogar WPF hat soetwas. Du mußt du mal in der entsprechenden Doku suchen oder bei Google.

Christian

Weeks of programming can save you hours of planning

212 Beiträge seit 2008
vor 9 Jahren

Guten Morgen 😃

Also ich würde versuchen das Projekt mit ZedGraph zu realisieren.

Hier ist ein Beispiel, das geht schon mal in deine Richtung.

Wenn man das dann noch mit diesem Beispiel kombiniert, geht das doch schon sehr in die gewünschte Richtung.

Eine Zoomfunktion bringt das Teil schon von Haus aus mit 😉

Mit Oxyplot könntest du das ganze auch noch MVVM konform (Drei Schichten Architektur) realisieren. Ich kann allerdings nicht sagen wie weit Oxyplot jetzt ist. Als ich mich damit beschäftigt habe, konnte das Control im Vergleich zu ZedGraph nicht mithalten. Aber MVVM würde ich an deiner Stelle erstmal als nebensächlich betrachten. MVVM wäre sicher eine eigenständiges Thema für eine Seminararbeit und würde dein eigentliches Ziel erstmal verzögern.

Gruß
Christoph

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

Vielen Dank für eure Antworten! Ich werde mir das ganze mal anschauen und mich dann wieder melden.
Schönen Abend noch!

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

So, hab mich mal mit allem hier vorgeschlagenem näher befasst und bin forh, dass ich schon mal so weit gekommen bin. Ich habe mich jetzt entschieden sowohl eine 2D als auch eine 3D Darstellung für mein Programm zu wählen.
Das mit ZedGraph hat super geklappt!

Das mit WPF klappt soweit auch ganz gut, nur habe ich ein kleines Grafik-Problem, bei dem ich eure Hilfe bräuchte:
Ich habe bis jetzt drei Koordinatenachsen und die Umlaufbahn des Kometen berechnet und im R3 defeniert.
Wie ihr auf dem angehängten Foto sehen könnt, führt das aber zu sehr seltsamen Effekten.
Denn eigentlich müssten ja die Koordinatenachsen die Ellipse an machen Stellen überdecken, sodass diese nicht mehr sichtbar ist bzw. eben genau andersrum.

Also meine Frage: Wie kann ich definieren, dass ein Objekt im Vordergrund bzw. Hintergrund liegt, sodass das Ganze aufhört bei jeder Bewegung zu flimmern.

Wenn ich wichtige Informationen vergessen habe, einfach kurz nachfragen. Dann werde ich mich bemühen diese so schnell wie möglich nachzutragen!

Ich hoffe ihr könnt mir helfen!

742 Beiträge seit 2005
vor 9 Jahren

Dafür ist der Z-Buffer da. Hast du den zufällig irgendwie deaktiviert?

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

Ähm... Ich habe noch nie was von einem Z-Buffer gehört. Also wenn ich ihn deaktiviert habe, dann war das unabsichtlich. Ich werde mich jetzt mal einlesen, was das Teil so macht.

Wenn du Lust hast, kannst du mir ja ein paar gute Webseiten empfehlen oder mir kurz erklären was das ist. Wenn du keine Zeit hast, ist auch nicht schlimm:)

Wünsche Dir noch einen schönen Tag!

5.658 Beiträge seit 2006
vor 9 Jahren

Hi TheMarksman,

unter WPF läßt sich der Depth-Buffer nicht manuell aktivieren oder deaktivieren. Allerdings gibt es Materialien (Specular oder Emissive), die den Depth-Buffer nicht beeinflussen. Kannst du evtl. mal einen Codeausschnitt posten, der zeigt, wie du die Geometrie erstellst und renderst?

Christian

Weeks of programming can save you hours of planning

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

Ich hab jetzt nur mal einen kleinen Auschnitt aus dem Code gewählt, der nur die "Verkleidung der Z-Achse im Positiven Bereich beschreibt. Der Rest der Koordinatenachsenverkleidung funktioniert nach dem selben Schema:


public void CreateCoSyAxis(double width, double renderingDistance)
        {
            
            double half = width / 2;

            //Z-Achse Deckel positiv
            MeshGeometry3D mesh = new MeshGeometry3D();

            // Verkleidung Z-Achse positiv Deckel
            mesh.Positions.Add(new Point3D(-half, half, half));                             
            mesh.Positions.Add(new Point3D(half, half, half));
            mesh.Positions.Add(new Point3D(-half, half, renderingDistance));
            mesh.Positions.Add(new Point3D(half, half, renderingDistance));

            mesh.TriangleIndices.Add(2);
            mesh.TriangleIndices.Add(3);
            mesh.TriangleIndices.Add(1);
            mesh.TriangleIndices.Add(1);
            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(2);

mGeometry = new GeometryModel3D(mesh, new DiffuseMaterial(Brushes.Moccasin));
            mGeometry.Transform = new Transform3DGroup();
            group.Children.Add(mGeometry);

}

Wie ich die Ellipse baue, ist etwas komplizierter. Ich versuche es mal so gut wie möglich zu beschreiben. Also mit den ganzen Kepler Algorithmus ist es mir gelungen die Umlaufbahn des Kometen im Raum zu bestimmen. Da kommen also eine Menge an Punkten raus, die eine Ellipse im Raum definieren. Da diese Ellipse allerdings von der Kamera gut sichtbar sein soll, habe ich mir gedacht, ich baue, wie bei den Koordinatenachsen, eine Art "Kasten" herum, in dessen Mittelpunkt die errechnete Ellipsenbahn liegt. Dabei wird die Ellipse vom Brennpunkt der Ellipse her Schrittweise durchgegangen und solche Kästen festgelegt. Wenn man ja ganz viele kleine "Kästen" aneinanderreiht, sieht das ja auch recht gut so aus, wie eine Ellipse. Die Eckpunkte dieser "Kästen" berechne ich mit Hilfe von Vektoren, was aber hier unwichtig ist. Auf jeden Fall werden die fertig berechneten Eckpunkte in eine Array mit dem Namen coord3DGrid geschrieben und folgender Methode zum Darstellen übergeben:


public void CreateOrbit(Point3D[] coord3DGrid)
        {
            MeshGeometry3D mesh = new MeshGeometry3D();

            for (int i = 0; i < coord3DGrid.Length; i++)
            {
                mesh.Positions.Add(coord3DGrid[i]);
            }

            for (int i = 0; i < coord3DGrid.Length; i++)
            {
                Vector3D normal = new Vector3D(0, 1, 0);
                mesh.Normals.Add(normal);
            }

           
            for (int z = 0; z < coord3DGrid.Length/8; z++)
            {
                

                //Deckel
                mesh.TriangleIndices.Add(3 + z * 8);
                mesh.TriangleIndices.Add(6 + z * 8);
                mesh.TriangleIndices.Add(0 + z * 8);
                mesh.TriangleIndices.Add(0 + z * 8);
                mesh.TriangleIndices.Add(5 + z * 8);
                mesh.TriangleIndices.Add(3 + z * 8);

                mesh.TriangleIndices.Add(14 + z * 8);
                mesh.TriangleIndices.Add(3 + z * 8);
                mesh.TriangleIndices.Add(5 + z * 8);
                mesh.TriangleIndices.Add(5 + z * 8);
                mesh.TriangleIndices.Add(8 + z * 8);
                mesh.TriangleIndices.Add(14 + z * 8);


                //Boden
                mesh.TriangleIndices.Add(2 + z * 8);
                mesh.TriangleIndices.Add(7 + z * 8);
                mesh.TriangleIndices.Add(1 + z * 8);
                mesh.TriangleIndices.Add(1 + z * 8);
                mesh.TriangleIndices.Add(4 + z * 8);
                mesh.TriangleIndices.Add(2 + z * 8);

                mesh.TriangleIndices.Add(15 + z * 8);
                mesh.TriangleIndices.Add(12 + z * 8);
                mesh.TriangleIndices.Add(1 + z * 8);
                mesh.TriangleIndices.Add(1 + z * 8);
                mesh.TriangleIndices.Add(2 + z * 8);
                mesh.TriangleIndices.Add(15 + z * 8);

                //Seite innen
                mesh.TriangleIndices.Add(4 + z * 8);
                mesh.TriangleIndices.Add(1 + z * 8);
                mesh.TriangleIndices.Add(5 + z * 8);
                mesh.TriangleIndices.Add(5 + z * 8);
                mesh.TriangleIndices.Add(0 + z * 8);
                mesh.TriangleIndices.Add(4 + z * 8);

                mesh.TriangleIndices.Add(1 + z * 8);
                mesh.TriangleIndices.Add(12 + z * 8);
                mesh.TriangleIndices.Add(8 + z * 8);
                mesh.TriangleIndices.Add(8 + z * 8);
                mesh.TriangleIndices.Add(5 + z * 8);
                mesh.TriangleIndices.Add(1 + z * 8);

                //Seite außen
                mesh.TriangleIndices.Add(2 + z * 8);
                mesh.TriangleIndices.Add(7 + z * 8);
                mesh.TriangleIndices.Add(6 + z * 8);
                mesh.TriangleIndices.Add(6 + z * 8);
                mesh.TriangleIndices.Add(3 + z * 8);
                mesh.TriangleIndices.Add(2 + z * 8);

                mesh.TriangleIndices.Add(15 + z * 8);
                mesh.TriangleIndices.Add(2 + z * 8);
                mesh.TriangleIndices.Add(3 + z * 8);
                mesh.TriangleIndices.Add(3 + z * 8);
                mesh.TriangleIndices.Add(14 + z * 8);
                mesh.TriangleIndices.Add(15 + z * 8);

                

            }
Material material = new DiffuseMaterial(new SolidColorBrush(Colors.Aquamarine));
            GeometryModel3D triangleModel = new GeometryModel3D(mesh, material);
            
            //Build the visual object
            ModelVisual3D model = new ModelVisual3D();
            model.Content = triangleModel;
}

Ich hoffe das hilft weiter. Wenn noch was fehlt, ergänze ich noch gerne etwas:)

Danke schon mal für eure Bemühungen!

5.658 Beiträge seit 2006
vor 9 Jahren

Hi TheMarksman,

für mich sieht das nach einem Problem mit den Normalen aus. Probier mal, die Normalen andersherum auszurichten, und/oder die einzelnen Dreiecke in entgegengesetzter Richtung zu definieren. Die Dreiecke selbst müssen immer entgegen des Uhrzeigersinns definiert sein, oder andersherum: die Vorderseite eines Dreiecks ist dort, wo die Punkte entgegen des Uhrzeigersinns angeordnet sind.

Wenn du dann noch eine Lichtquelle (DirectionalLight) in deine Szene einfügst und die Darstellung der Rückseiten deaktivierst, kannst du genau erkennen, ob die einzelnen Flächen in die richtige Richtung zeichen.

Da es erstmal nur um die richtige Erstellung von Meshes geht, kannst du dich auch an dieses Beispiel halten: Drawing a Cube in WPF.

Christian

Weeks of programming can save you hours of planning

T
TheMarksman Themenstarter:in
8 Beiträge seit 2015
vor 9 Jahren

Ich habe jetzt mal mit den Normalvektoren rumgespielt und mir auch meine Definition der Mesh nochmal angeschaut. Ich konnte allerdings keine Lösungs des Problems damit finden. Ich habe bei meinen einzelnen Kästen nur die Außenseite definert, also gegen den Uhrzeigersinn, da man die Seiten im Kasten drin, selbst sowieso nicht sehen kann. Ist das vielleicht mein Fehler? Ich frage nur vorher nach, ob es das sein könnte, da das ein Haufen Arbeit ist und ich vorher eure Meinung will, bevor ich loslege. Zudem habe ich bei den Koordinatenachsen keine Normals definiert. Ich habe das probehalber auch schon mal gemacht, allerdings ebenso erfolglos. Kann das auch eventuell was mit dem Licht zu tun haben? Da habe ich nämich ein AmbientLight und ein DirectionalLight.

Schönen 1. April noch!

742 Beiträge seit 2005
vor 9 Jahren

Für mich sieht das nicht nach den Normalenvektoren aus. Dann sähen die einzelnen Meshes schon komisch aus.

Ich könnte mir noch vorstellen, dass es sich um Z-Buffer-Fighting handelt: Z-fighting

Das ist aber auf dem Screenshot schwer zu erkennen. Du kannst ja mal deine Anwendung hochladen. In Bewegung sieht man das Problem vll. besser.

5.658 Beiträge seit 2006
vor 9 Jahren

Gegen das Z-Fighting kann man prophylaktisch mal die Near- und Far-Planes der Kamera so nah wie möglich zusammenlegen. D.h. die Near-Plane sollte so weit wie möglich von der Kamera weg, und die Far-Plane so nah wie möglich an der Kamera dran sein.

Christian

Weeks of programming can save you hours of planning