ich habe ja vor einigen Monaten nach Hilfe gefragt um Backface-Culling und Z-Buffering in mein Isometrie-Zeichenprogramm einzubinden.
Leider hatte ich aufgrund von Zwischenfällen die mir einige Zeit und Nerv geraubt hat keine Zeit mich weiter um das Programm zu kümmern und konnte in der Zeit nur Backface-Culling implementieren und habe das Z-Buffering stehen gelassen.
Vor einigen Tagen kam mir jedoch eine Idee wie ich das (theoretisch) einfach lösen kann und momentan sieht es schon ziemlich gut aus, habe jedoch einen kleinen Fehler drinnen.
Und zwar probiere ich es gerade so, dass ich jedes Polygon einzeln auf ein Bitmap zeichnen lasse in der Position die es später auch haben soll. (Dazu sind noch Bilder angefügt, da Bilder bekannterweise mehr als 1000 Worte sagen )
Nun habe ich pro Polygon ein Bitmap bei der ich dann Pixel für Pixel nach gezeichneten Stellen suche und, falls ein gezeichneter Pixel vorhanden ist, dessen Position im 3D-Raum zurückrechne um dann berechnen zu können wie "nah" der Pixel von der Kamera ist. Am Schluss kombiniere ich einfach alle Bitmaps zu einem und lasse anhand der Pixeltiefe entscheiden ob es zu sehen ist oder nicht. Ich glaube genau da liegt der Fehle, beim bestimmen welche Tiefe der Pixel hat. (Im Bild im Anhang kann man den Fehler gut erkennen wenn man reinscrollt und beide Ergebnisse mal ein vergleicht. Beim vom Programm erzeugten sieht verläuft zum beispiel die Linie vom 2. Polygon nicht parallel zu den anderen vom 1. Polygon, das kann ja schon mal nicht stimmen )
Um die Koordinate wieder zurück zu rechnen benutze ich folgende Methode: (Das ganze Projekt ist auch im Anhang)
for x := LRect.Left to LRect.Right do begin for y := LRect.Top to LRect.Bottom do begin if LData.GetPixel(X,Y) <> $00000000 then begin
LX := X;
LY := Y;
Pixels[LX,LY].Color := LData.GetPixel(LX,LY);
Pixels[LX,LY].Vector := CalculateCoordinate(APolygon,PointF(LX,LY));
LCam := Vector3D(Pixels[LX,LY].Vector.X-Pixels[LX,LY].Vector.Z,Pixels[LX,LY].Vector.Y-Pixels[LX,LY].Vector.Z,0);
Pixels[LX,LY].Depth := LCam.Distance(Pixels[LX,LY].Vector); // Hier wird die Tiefe berechnet end; end; end;
begin
Colors := [$FFFF0000,$FFFF00FF,$FF00FF00,$FF0000FF];
for c := 0 to Length(Apolygons)-1 do begin
LBuffer := TPixelBuffer.Create(500,500);
LBuffer.CreateMatrix(APolygons[c],Colors[c]);
Buffers.Add(LBuffer); end;
LBuffer := TPixelBuffer.Create(500,500); for x := 0 to 499 do// Hier wird noch mal die finale Matrix erstellt begin for y := 0 to 499 do begin for c := 0 to Buffers.Count-1 do begin if (Buffers[c].Pixels[x,y].Depth < Lbuffer.Pixels[x,y].Depth) then// Überprüfung ob der Pixel gezeichnet werden soll oder ob er überdeckt ist begin
Lbuffer.Pixels[x,y].Depth := Buffers[c].Pixels[x,y].Depth;
Lbuffer.Pixels[x,y].Height := Buffers[c].Pixels[x,y].Height;
LBuffer.Pixels[x,y].Color := Buffers[c].Pixels[x,y].Color; end; end; end; end;
for x := 0 to 499 do begin for y := 0 to 499 do begin
LData.SetPixel(X,Y,LBuffer.Pixels[X,Y].Color); end; end;
LBitmap.SaveToFile('./test.png'); end;
Im anhang sieht man das es auch schon fast funktioniert, jedoch glaube ich das die Tiefenberechnung fehlerhaft ist oder das vielleicht die CalculateCoordinate auch nicht wirklich gut gelöst ist :/
Ich hoffe ich habe mich so ausgedrückt das man mein Anliegen gut versteht, ist schon ziemlich spät und muss nun schlafen sonst raubt mir Delphi wieder mal die ganze Nacht... und den Tag darauf sowieso!
Edit: Ach ja der code wurde auf die schnelle geschrieben als "proof of concept", im Zeichenprogramm hat der nichts zu suchen