|

Grundlagen der Grafikprogrammierung - Teil 8 - by Delax
Tach!
Zur Erinnerung: das letzte Mal hatten wir die ultimative Grundlage: eine PutPixel Routine, mit der man an einen Punkt (X,Y) einen Pixel mit einer Farbe setzen kann. Ohne das geht gar nichts. Jetzt bauen wir darauf auf und lernen einige weitere wichtige Kleinigkeiten: erst Linien und das nächste Mal dann noch Kreise. Danach binden wir alles erst einmal in eine eigene kleine Unit.
Doch nun erst einmal Linien. Schauen wir uns einmal eine Linie in einem Koodinatensystem an: sie hat Start- und Endpunkt mit je einem X und Y Wert und eine bestimmte Steigung. Wer in Mathe gut aufgepasst hat: die Formel für eine Linie lautet Y=mX+c (bzw. manchmal auch Y=mx+b). X/Y ist die X/Y Koordinate, m ist die Steigung und b der Schnittpunkt mit der Y Achse.

Machen wir jetzt einmal ein kleines Gedankenspiel. Eine tolle Sache in der Grafikprogrammierung ist ein Dreieck. Wenn es dann noch ein rechtwinkliges ist, haben wir den Jackpot. Werfen wir noch einmal einen Blick auf die Linie, nur diesmal als imaginäres Dreieck:

Wie wir sehen haben wir sogar feste Koordinaten für diesen 3. Punkt. Egal, gehe wir einmal konkret mit Zahlen an die Sache ran: x1 = 2; y1 = 4; x2 = 7; y2 = 1; Um die Strecken zu benennen nehmen wir mal die normalen Schulbezeichnungen:

Und nun? Supereinfach! Wir wissen, wie lange die Strecken sind! a ist zum Beispiel 5. Wieso? Ganz einfach! Weil die X Werte subtrahiert 5 ergeben (7-2 = 5). Und b ist 3 (4-1 = 3). Jetzt können wir auch mühelos die Steigung errechnen. Die beträgt nämlich auf X bezogen Y/X = 3/5 = 0.6. Das bedeutet, wann immer wir einen Schritt nach rechts (X entlang) gehen, müssen wir 0.6 Schritte nach oben gehen.
Und jetzt sollte allen eigentlich etwas auffallen: wie zur Hölle geht man denn bitte 0.6 Pixel nach oben?! Antwort: gar nicht! Das geht so nämlich nicht! Und bevor ihr die Messer und Briefbomben auspackt: das ganze hatte auch einen Sinn: spätestens bei 3D Geschichten wird euch der Kram wieder über den Weg laufen! Zumindest wenn sie tiefer gehen. Und wenn ihr so eine simple Erklärung schon zu kompliziert findet, könnt ihr auch gleich aufhören und euch anderem widmen.
Nun aber zu einer tauglicheren Lösung. Linienansätze gibt es viele. Die meißten entstanden aus der Not Linien mit Plottern zu drucken, die eben nur x/y Koordinaten kannten. Der berühhmteste Anstatz stammt wohl von Bresenham. Ich werde ihn nicht komplett erklären, sondern nur einen groben Abriß geben. Wer sich näher für Bresenhams Algorithmen (nicht nur Linien!) interessiert, kann ja mal für sich nachschlagen.
Als erstes prüft man, wie die Linie genau verläuft: von links unten nach rechts oben, rechts oben nach rechts unten oder wie auch immer. Je nach Fall muß man mit anderen Vorzeichen arbeiten. Der erste Pixel ist logischerweise der erste angegebene Punkt, also x1, y1. Dann geht man davon aus, man ist am Anfang der Linie. Man berechnet nun wieviele Pixel man in eine Richtung auf der Y-Achse zeichnen kann, bis man einen X-Wert weiter rücken muß.
Springen wir mal in den Source. Die Routine ist schon ein bischen optimiert und stammt aus Toxic Avengers Tutorial und wurde nur ein kleines bischen angepasst.
PROCEDURE Line(destiny : pointer; x1,y1,x2,y2 : longint; color1, color2 : byte);
Var dx,dy,sx,sy,k : longint;
BEGIN
sx:=1;
sy:=1;
dx:=x2-x1;
if dx<0 then begin
dx:=-dx;
sx:=-1;
end;
dy:=y2-y1;
if dy<0 then begin
dy:=-dy;
sy:=-1;
end;
k:=-(dx shr 1);
PutPixel(destiny,x1,y1,color1, color2);
while (x1<>x2) or (y1<>y2) do
if (k>=0) and (y1<>y2) then begin
inc(y1,sy);
dec(k,dx);
PutPixel(destiny,x1,y1,color1, color2);
end
else begin
inc(x1,sx);
inc(k,dy);
PutPixel(destiny,x1,y1,color1, color2);
end;
END;
Als kleine Nebenbemerkung: diese shl Geschichten sind schon eine kleine Optimierung. Anstatt mit 2 zu multiplizieren/ dividieren nutzt man einfach "binary shifting", also das links/ rechts Verschieben von den binären Werten der Zahlen. Dazu kommen wir aber später noch, wenn wir ein wenig Optimierung betreiben ;)
Ein komplettes Beispiel noch zum Schluß: Hier als Datei zum download
Wie gesagt schauen wir uns das nächste Mal Kreise an. Bis dahin: have a nice day!
Delax/ Sundancer Inc.
[delax@sundancerinc.de]
Back to previous page
|