Die neue Computergeneration schaffte neue Sehgewohnheiten in Form von oft atemraubenden 3D-Grafiken und -Animationen. In diesem vierteiligen Kurs lernen Sie, wie Sie Ihrem Atari ST zum Sprung in die dritte Dimension verhelfen.
Als Handwerkszeug benötigen Sie lediglich das Turbo-C-Entwicklungspaket von Borland, mit dem alle Beispielprogramme entstanden sind. Diese arbeiten in allen Grafikauflösungen. Das Entwicklungspaket ist jedoch nicht bindend erforderlich, da sich alle Programme auch ablauffĂ€hig auf der TOS-Diskette befinden. Neben minimalen Mathematik-Kenntnissen setzen wir auch etwas C-Know-How voraus. Es wurde bewuĂt weitgehend auf die komplizierte Matrizendarstellung und mathematische Herleitungen verzichtet, auch das komplizierte Raytracing klammern wir aus. In diesem Kursteil weihen wir Sie in die Grundlagen der dreidimensionalen Grafik ein, besprechen die Realisierung einfacher Vektorgrafiken und zeigen diese anhand eines kleinen Programms, das ĂŒbrigens die im Artikel »Genormte Grafikwelt« (TOS 10 und 11 /90) besprochenen BGI-Grafikfunktionen verwendet.
In der Welt der Computergrafik bewegen wir uns auf drei Achsen: links/rechts, vor/zurĂŒck und hoch/ runter. Möchten wir eine bestimmte Position in dieser Welt beschreiben, so mĂŒssen wir die Stellungen auf jeder der drei Achsen eindeutig definieren. Hierzu legen wir an jeder Achse eine Skala an. Die drei Skalenwerte sind dann die Koordinaten der Position.
Die dreidimensionalen Grafiken, die wir in diesem Lehrgang entwerfen, bestehen stets aus einer Reihe von Objekten, die sich wiederum aus einer Anzahl von Kanten bzw. FlÀchen zusammensetzen. Deren Endpunkte bzw. Ecken sind jeweils eindeutig durch Koordinaten festgelegt.
Kommen wir nochmals auf die drei Dimensionen zurĂŒck. Wie Sie vielleicht noch aus dem Mathematikunterricht wissen, wird jede der drei Achsen mit einem Buchstaben gekennzeichnet. Die links/rechts-Dimension ist die x-Achse, hoch/ runter die y-Achse und vor/zurĂŒck die z-Achse. Ein Punkt P wird dann in der Form P(x;y;z) festgelegt, wobei wir fĂŒr x, y, und z die entsprechenden Koordinaten einsetzen. Diese können auch negativ sein, zum Beispiel P(2;-4;11). Der Mittelpunkt des dreidimensionalen Universums mit den Koordinaten (0;0;0) heiĂt »Ursprung«. Möchten wir von ihm zum Punkt P(2; -4;11) gelangen, so mĂŒssen wir zwei Schritte nach rechts, vier nach unten und elf nach vorne in die Tiefe gehen.
Wie aber können wir dreidimensionale Positionen zeichnerisch darstellen? Die ersten beiden Dimensionen lassen sich problemlos auf dem Bildschirm oder einem Blatt Papier zeichnen, indem wir ein rechtwinkliges Koordinatensystem einfĂŒhren, bei welchem die x-Achse von links nach rechts und die rechtwinklig angeordnete y-Achse von unten nach oben verlĂ€uft. Damit sind die zwei Dimensionen unseres Darstellungsmediums allerdings schon ausgelastet, die dritte Achse mĂŒĂte quasi in den Bildschirm bzw. in das Papier hinein verlaufen.
In der Mathematik hilft man sich mit dem dreidimensionalen, kartesischen Koordinatensystem. In diesem verlÀuft die z-Achse diagonal zwischen den x - und y-Achsen von links unten nach rechts oben. Möchten Sie beispielsweise den Punkt P(2;1;3) darstellen, so starten Sie im Ursprung, bewegen den Stift um zwei Einheiten nach rechts, eine Einheit nach oben, drei Einheiten nach oben rechts und tragen nun den Punkt ein. Einfache Objekte wie Dreioder Vierecke stellen wir dar, indem wir die Eckpunkte auf die genannte Weise eintragen und die entsprechenden Ecken durch Kanten verbinden. Stellen wir zwei FlÀchen dar, die sich nur durch ihre z-Koordinaten unterscheiden, so bemerken wir, daà eine der FlÀchen nach oben rechts versetzt ist.
Wir erhalten also einen Aufblick von rechts oben auf unseren Körper. Das dreidimensionale kartesische Koordinatensystem ist leicht durchschaubar und eignet sich daher sehr gut zur manuellen Darstellung auf dem Papier und Entwurf von Objekten. Bei der Bildschirmdarstellung nimmt uns der Computer die Arbeit ab. Deshalb nutzen wir ein anderes, komplizierteres Koordinatensystem, das viel mehr Realismus vermittelt. Hierbei orientieren wir uns an den ĂŒblichen Sehgewohnheiten. Wir wissen, daĂ ein entferntes Objekt kleiner erscheint. UnterstĂŒtzt von den stereoskopischen SehfĂ€higkeiten können wir sehr genau feststellen, wie weit ein Körper entfernt ist. WĂ€hrend stereoskopische Bilder nur mit gröĂerem Aufwand zu realisieren sind, lĂ€Ăt sich eine Tiefendarstellung mit entfernungsabhĂ€ngiger Darstellungsgrösse, die sogenannte Zentralperspektive, leicht realisieren.
Bild 1. Das kartesische Koordinatensystem
Bild 2. Koordinaten von oben betrachtet
Werfen wir hierzu einen Blick auf Bild 2, das die Szenerie in Vogelperspektive zeigt. Wir sehen Kamera K, die auf dem Bildschirm B die Projektion des Objektes O aufnimmt. Deutlich ist der fiktive Lichtstrahl vom Objekt O ĂŒber den Bildschirm B zur Kamera K zu sehen. Dieser bildet zusammen mit der z-Achse ein spitzes Dreieck. Nehmen wir an, uns wĂ€ren die x- und z-Koordinaten des Objektes und die (negative) z-Koordinate der Kamera (Augabstand) bekannt. Nun möchten wir wissen, welche x-Koordinate die Projektion von O auf dem Bildschirm (z=0) besitzt. Da zwei Ă€hnliche Dreiecke vorliegen, bedienen wir uns zur Lösung dieses Problemes des Strahlensatzes. Dieser besagt, daĂ die SeitenverhĂ€ltnisse zweier Ă€hnlicher Dreiecke stets identisch sind. Betrachten wir zunĂ€chst das kleine Dreieck: Eine SeitenlĂ€nge ist die x-Koordinate des Bildes B, nĂ€mlich xB, die zweite der Abstand zwischen Ursprung und der Kamera -z«, das VerhĂ€ltnis ist also xB/-zK. Die entsprechenden SeitenlĂ€ngen des groĂen Dreiecks sind die x-Koordinate des Objektes xO und der Abstand zwischen Objekt und Kamera zO-zK, woraus sich das VerhĂ€ltnis xO/(zO-zK) ergibt. Laut Strahlensatz gilt:
xB/-zK = xO/(zO-zK)
Die x-Koordinate des Bildes ist also:
xB = -(xO*zK)/(zO-zK)
In der yz-Ebene ergibt sich die abgewandelte Formel:
yB = -(yO*zK)/(zO-zK)
Aus dieser Formel ist zu erkennen, daĂ bei wachsendem Abstand des Körpers zO der Nenner des Bruches gröĂer wird, weshalb die Projektionskoordinate xB bzw. yB geringer wird, das Bild also kleiner erscheint. Somit ist die Zentral Perspektive realisiert.
Betrachten wir das auf der TOS-Diskette enthaltene Demoprogramm »3D_1.C«. Starten Sie zunĂ€chst die zO Programmdatei »3D_1.PRG«. Auf dem Bildschirm erscheint, wie in Bild 3 zu sehen, eine vierseitige Pyramide in Zentralperspektive. Mit den Tasten a bzw. A können wir den Augabstand verringern bzw. erhöhen. Wie Sie sehen, erscheint das Bild bei kleinerem Augabstand stĂ€rker verzerrt, es entsteht ein »Weitwinkeleffekt« wie beim Fotografieren. Mit dem Augabstand, der in unserem Beispiel anfangsaufeinen »Normalwert« von -450 gesetzt wird, verĂ€ndern wir das Erscheinungsbild der Grafik. Mit den Tasten 4 und 6 auf der Zahlentastatur können Sie die Pyramide nach links bzw. rechts bewegen (x-Achse), mit 8 und 2 nach oben bzw. unten (y-Achse) und mit - und ] weiter in die Ferne bzw. NĂ€he verschieben (z-Achse). Bei Ănderung der z-Position bemerken Sie die GröĂenĂ€nderung.
Bild 3. Der Lohn der MĂŒhe
Werfen wir nun einen ersten Blick auf den Programmtext. Die Pyramide besteht einfach aus sechs Kanten, die wiederum jeweils durch die x-, y - und z-Koordinaten ihrer beiden Eckpunkte festgelegt wurden. Dies geschah in dem zweidimensionalen double-Feld »k[KANTEN][6]«. So bestimmen die ersten sechs Koordinaten [ -40,-20,-10,30,-30,-20 ] die Kante von P1 (-40,-20,-10) zu P2(30,-30,-20). Legen Sie doch einmal einen neuen Körper im Quelltext fest. Die Koordinaten sollten jeweils im Bereich von -50 bis +50 liegen. Auch die Kantenzahl Ă€ndern Sie, indem Sie »#define KANTEN 6«-Deklaration entsprechend abwandeln und neue Koordinatenzeilen hinzufĂŒgen. Die Position des Objektes wird in den Variablen »xpos«, »ypos« und »zpos« gespeichert, die »k[]«-Koordinaten bleiben stets unangetastet. In der »projection«-Funktion erfolgt die Verschiebung des Objektes durch Addition der Koordinaten mit den »..pos«-Werten und die Projektion in das 2D-System, wobei wir folgende Gleichungen verwenden:
distance = z+zpos â (double) auge;
/* Abstand des Punktes */
*px=xcenter + (int)(((double)-auge*x/distance)+xpos)*xscale;
*py=ycenter -- (int) (((double)-auge*y/distance)+ypos)*yscale;
ZunĂ€chst ermitteln wir den Abstand zwischen Kamera und Auge, zu dem wir die z-Position des Objektes »zpos« addieren, und wenden darauf den Strahlensatz an. Auch hierbei werden jeweils die aktuellen Positions-Koordinaten »xpos« bzw. »ypos« addiert, damit das Objekt am rechten Ort erscheint. Die Multiplikation mit »..scale« dient der Anpassung an alle Grafikauflösungen. AnschlieĂend addieren wir »..center«, damit der Ursprung in der Bildschirmmitte liegt. Diese Variablen sind in der Funktion »init_all« initialisiert.
Die Darstellung des kompletten Objektes ist denkbar einfach. In der »draw_all«-Funktion wandelt das Programm in einer for-Schleife alle 3D-Koordinaten per »projection«-Aufruf in 2D-Werte um und zeichnet die zugehörigen Kanten per »line«-Funktion. Schon sind wir imstande, dreidimensionale Grafiken aus einzelnen Kanten zu erzeugen, oft als Vektorgrafiken bezeichnet. Im nĂ€chsten Teil werden wir diese drehen, komplexere Objekte aufbauen und eine fiktive Kamera einfĂŒhren, mit der wir uns in der 3D-Welt bewegen. (ah)
KursĂŒbersicht
Teil 1: Grundlagen ⥠Gittergrafik ⥠einfaches Programmbeispiel
Teil 2: 3D-Datenstruktur ⥠Kamera ⥠scriptfĂ€higes ProgrammgerĂŒst
Teil 3: Versteckte Linien ⥠Schattierung ⥠Programmerweiterung
Teil 4: Generator fĂŒr komplexe Objekte ⥠Ausblick