Dies erwies sich als eine lustige Übung; nette Frage!
Zuerst fragen Sie speziell, ob Sie eine solche Kugel auf eine TImage
zeichnen möchten, aber diese Komponente soll zum Anzeigen von Grafiken verwendet werden. Sicher, es hat eine Leinwand, auf der gezeichnet werden kann, aber hierunter verwende ich eine TPaintBox
, die die bevorzugte Komponente für die eigene Malerei ist. Denn du musst das selbst malen. Ganz und gar.
Einige Berechnungen zum Berechnen der 3D-Punkte auf einer Kugel, zum Drehen des Globus um mehrere Achsen und zum Konvertieren der 3D-Punkte in das 2D-Bildschirmkoordinatensystem. Die Grundlagen sind:
%Vor%Einige Globe-Variablen, mit denen gearbeitet werden kann:
%Vor%Code zur Berechnung aller Punkte der Breitenkreise:
%Vor%Code zur Berechnung aller Punkte der Längengradmeridiane:
%Vor%Diese Punkte können zum Zeichnen von Linien oder Kurven auf dem Malkasten verwendet werden. Der Z-Wert dieser Punkte wird nicht zum Zeichnen verwendet, aber sie sind hilfreich, um zu entscheiden, ob der Punkt auf der Vorder- oder Rückseite des Globus liegt.
Logik und Hilfsmittel. Bevor alle Punkte, Linien oder Kurven vor dem Globus gezeichnet werden können, müssen zuerst die auf der Rückseite des Globus befindlichen Punkte gezeichnet werden, um Tiefe zu erhalten.
Ein Zeichenframework oder eine Zeichnungsbibliothek. Delphi ist standardmäßig mit Windows GDI Standard ausgestattet, das über die Eigenschaft Canvas
des Malkastens verfügbar ist. Eine andere Möglichkeit ist GDI +, die fortgeschrittener ist und effizienter sein kann. Vor allem unter Berücksichtigung von Anti-Aliasing. Dies sind die beiden Frameworks mit denen ich gearbeitet habe, aber es gibt auch andere. Zum Beispiel: OpenGL, das 3D-Objekte automatisch in 2D umwandelt und in der Lage ist, 3D-Oberflächen, Lichtquellen, Materialien, Shader und viele weitere Funktionen hinzuzufügen.
Eine Testanwendung, die am Ende dieser Frage hinzugefügt wird.
Eine doppelte Puffertechnik, um die Farbe flickerfrei zu machen. Ich habe ein separates Bitmap-Objekt ausgewählt, auf dem alles gezeichnet wird, bevor ich dieses Bitmap auf den Malkasten male. Das Demo-Programm demonstriert auch die Leistung ohne es (Routine: GDIMultipleColorsDirect
).
Fügen Sie ein Farbfeld in Ihr Formular ein und legen Sie seine Eigenschaft Align
auf alClient
fest, fügen Sie eine Timerkomponente für die Simulation hinzu, fügen Sie Formularereignishandler für OnCreate
, OnDestroy
, OnKeyPress
und% co_de hinzu % und fügen Sie einen Ereignishandler für OnResize
hinzu.
Mit der Standard-GDI zeichne ich Linien von jedem Punkt zu jedem nächsten Punkt. Um ein Gefühl der Tiefe (Perspektive) hinzuzufügen, gab ich den Linien vorne eine größere Breite. Außerdem lasse ich allmählich die Farben der Linien von dunkel nach hell übergehen (Routine: PaintBox1.OnPaint
).
Schön, aber alle Pixel sind so hart! Lass uns versuchen, selbst Anti-Aliasing zu machen ...;) Außerdem habe ich die Farbanzahl auf zwei reduziert: dunkel vorne, hinten hell. Dies um alle separaten Liniensegmente loszuwerden: Jetzt wird jeder Kreis und Meridian in zwei Polylinien aufgeteilt. Ich habe eine dritte Farbe dazwischen für den Anti-Aliasing-Effekt verwendet (Routine: GDIMultipleColors
).
Dieses Anti-Aliasing ist nicht besonders reizvoll. Um wirklich glatte Farben zu erhalten, konvertieren wir den Code in den GDI + -Stil. Für Delphi ab 2009 ist die Bibliothek von hier verfügbar. Für ältere Delphi-Versionen ist die Bibliothek von hier verfügbar.
In GDI + funktioniert das Zeichnen etwas anders. Erstellen Sie ein Objekt GDIThreeColors
und hängen Sie es mit seinem Konstruktor an einen Gerätekontext an. Anschließend werden Zeichnungsoperationen für das Objekt von der API übersetzt und an den Zielkontext ausgegeben, in diesem Fall die Bitmap (Routine: TGPGraphics
).
Nun, das ist schon einiges. Aber dieser Globus besteht aus Polylinien mit nur zwei verschiedenen Linienbreiten. Lass uns etwas dazwischen hinzufügen. Die Anzahl der Segmente in jedem Kreis oder Meridian wird durch die Konstante GDIPlusDualLinewidths
(Routine: Precision
) gesteuert.
Drücken Sie eine Taste, um die oben genannten Routinen zu durchlaufen.
%Vor%(Mit Dank an Bummis Kommentar .)