Dreiecksfüllroutine (blitzbase.de)

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

Blitzkrieg Bop

Betreff: Dreiecksfüllroutine (blitzbase.de)

BeitragSa, Sep 27, 2008 3:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey Smile,
es geht um folgendes:

Auf www.blitzbase.de gab es eine Routine zur Dreiecksfüllung. Ich habe in der Routine einen kleinen Bug gefunden und komme im Moment nicht auf die Lösung, wie ich ihn am besten entfernen kann.

Zunächst der Code, so wie er auf www.blitzbase.de zu finden war:
Code: [AUSKLAPPEN]
Dim xval(20)
Dim yval(20)

Graphics 640,480,0,2
Color 255,0,255

Triangle 100,20,300,400,0,200
;50,0,80,20,30,20

WaitKey
End

Function Triangle(x0,y0,x1,y1,x2,y2)
    xval(0)=x0
    yval(0)=y0
    xval(1)=x1
    yval(1)=y1
    xval(2)=x2
    yval(2)=y2
    poly(3)
End Function

Function Quad(x0,y0,x1,y1,x2,y2,x3,y3)
    xval(0)=x0
    yval(0)=y0
    xval(1)=x1
    yval(1)=y1
    xval(2)=x2
    yval(2)=y2
    xval(3)=x3
    yval(3)=y3
    poly(4)
End Function

Function poly(vcount)
; get clipping region
    width=GraphicsWidth()
    height=GraphicsHeight()
; find top verticy
    b=vcount-1
    y=yval(0)
    While c<>b
        c=c+1
        yy=yval(c)
        If yy<y y=yy d=c
    Wend
    c=d
    t=c
; draw top to bottom
    While y<height
; get left gradient
        If y=yval(c)
            While y=yval(c)
                x0=xval(c) Shl 16
                c=c+1
                If c>b c=a
                If c=t Return
                If y>yval(c) Return
            Wend
            h=yval(c)-y

            g0=((xval(c) Shl 16)-x0)/h
        EndIf
; get right gradient
        If y=yval(d)
            While y=yval(d)
                x1=xval(d) Shl 16
                d=d-1
                If d<a d=b
                If y>yval(d) Return
            Wend
            h=yval(d)-y
            g1=((xval(d) Shl 16)-x1)/h
        EndIf
; calc horizontal span
        x=x1 Sar 16
        w=((x0 Sar 16)-x)+1
; draw down to next vert
        If (w>0 And y>-1 And x<width And x+w>0)
            If x<0 w=w+x x=0    ;crop left
            If x+w>width w=width-x    ;crop right
            Rect x,y,w,1
        EndIf
; next
        x0=x0+g0
        x1=x1+g1
        y=y+1
    Wend
End Function


Nun zu dem Bug: Gibt man beispielsweise folgende Koordinaten für das Dreieck an:
Code: [AUSKLAPPEN]
x0 = 0
y0 = 479

x1 = 640/2
y1 = 0

x2 = 639
y2 = 479

geschieht folgendes: Das Dreieck wird gezeichnet, allerdings nur bis zur 478'ten Zeile. Die letzte Zeile (479) bleibt ungefärbt.
Interessant: Ändert man beispielsweise y0 und y2, so dass gilt:
Code: [AUSKLAPPEN]
y0 = y2 = 480

dann funktioniert alles bestens.

Ich würde nur gerne eine allgemeingültige Lösung haben.

Besten Dank im Voraus,
Bye.
~ Hey Ho Let's Go ~
 

Blitzkrieg Bop

BeitragFr, Okt 17, 2008 16:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,
das Ganze ist ziemlich wichtig, daher ein kleiner Push - verbunden mit der Frage, ob wirklich niemand was zur Lösung des Problems beitragen kann Confused.

Bye.
~ Hey Ho Let's Go ~

ozzi789

BeitragFr, Okt 17, 2008 17:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Hab ich das jetzt richtig verstanden , das müsst so ausehn
Code: [AUSKLAPPEN]
Triangle 0,479,640/2,0,639,479
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5
 

Blitzkrieg Bop

BeitragFr, Okt 17, 2008 17:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Okay, nochmal zur genaueren Erläuterung:
Der Funktionsaufruf sollte in der Tat so aussehen:

Code: [AUSKLAPPEN]
Triangle 0,479,640/2,0,639,479


Ich habe das dadurch entstehende Resultat mal als Bild hochgeladen:

user posted image

Der Fehler ist bei näherer Betrachtung deutlich zu erkennen!

Bye.
~ Hey Ho Let's Go ~

ozzi789

BeitragFr, Okt 17, 2008 17:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja die unterste linie is ned dort, das meinste oda ?
Nimm 480 anstatt 479 wo is da das problem ?
Des is ne koordinate und wenn du 479 an gibst und der screen 480 gross is, is das ja klar des die unterste ned ausgefüllt ist ><
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5
 

Blitzkrieg Bop

BeitragFr, Okt 17, 2008 19:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey,
sorry aber das was du sagst ist totaler Quatsch. Bei einer Auflösung von 640*480 sind alle Pixel im Bereich 0 <= X < 640 | 0 <= Y < 480 "sichtbar".

Kann es sein, dass dir da elementare Grundkenntnisse fehlen? Smile

Bye.
~ Hey Ho Let's Go ~

sheldon

BeitragFr, Okt 17, 2008 19:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Blitzkrieg Bop hat Folgendes geschrieben:
Hey,
sorry aber das was du sagst ist totaler Quatsch. Bei einer Auflösung von 640*480 sind alle Pixel im Bereich 0 <= X < 640 | 0 <= Y < 480 "sichtbar".

Kann es sein, dass dir da elementare Grundkenntnisse fehlen? Smile

Bye.



Quatsch, ozzi hat Recht.

Bei einer Auflösung von 640*480 sind 640 Pixel 'nach rechts' 'sichtbar' und 480 Pixel 'nach unten' 'sichtbar'.
 

Blitzkrieg Bop

BeitragFr, Okt 17, 2008 20:01
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Bei einer Auflösung von 640*480 sind 640 Pixel 'nach rechts' 'sichtbar' und 480 Pixel 'nach unten' 'sichtbar'.


Dagegen sagt auch keiner was. Man sollte nur bedenken, dass man von X = 0 bzw. Y = 0 (je nachdem welche Achse man gerade betrachtet) als "Startpunkt" ausgeht. Dementsprechend ist der letzte (640 'te) Pixel in X-Richtung an der Stelle X = 639 und analog dazu liegt der letzte (480 'te Pixel) in Y-Richtung an der Stelle Y = 479.

Vielleicht verstehe ich ja nicht worauf ihr hinaus wollt Shocked.

Bye.
~ Hey Ho Let's Go ~
 

Phlox

BeitragFr, Okt 17, 2008 20:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Was regt ihr euch so auf, bei 2D muss man halt ein wenig
tricksen/pfuschen.

Xeres

Moderator

BeitragFr, Okt 17, 2008 20:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Man kann doch selbst nachmessen...
Code: [AUSKLAPPEN]
Rect 0, 0, 5, 480,1

unter die Triangle-Funktion setzen... Mit der Länge 480 wird auch der letzte Pixel korrekt gezeichnet. Wo die Koordinaten sein sollten und was tatsächlich gezeichnet wird, sind doch sowieso zwei verschiedene Geschichten.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Blitzkrieg Bop

BeitragFr, Okt 17, 2008 20:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Was regt ihr euch so auf, bei 2D muss man halt ein wenig
tricksen/pfuschen.


Na ja, das wäre doch irgendwie sehr unbefriedigend. Tricksen/Pfuschen ist hier sicherlich keine akzeptable Methode.

Innerhalb des Algos befindet sich ein Bug. Es geht darum, ihn zu beheben. Und das muss ohne Workarounds und/oder Trickserei und Pfuscherei möglich sein.

Edit:

Zitat:
Man kann doch selbst nachmessen...

unter die Triangle-Funktion setzen... Mit der Länge 480 wird auch der letzte Pixel korrekt gezeichnet. Wo die Koordinaten sein sollten und was tatsächlich gezeichnet wird, sind doch sowieso zwei verschiedene Geschichten.


Wenn man von dem gegebenen Beispiel ausgeht:
Code: [AUSKLAPPEN]
Triangle 0,479,640/2,0,639,479

dann kann man sich die Verbindung zwischen Punkt 1 (0|479) und Punkt 3 (639|479) gut bildlich vorstellen.

Wenn man nun z.B. eine normale Linie zwischen diesen Koordinaten zeichnet:
Code: [AUSKLAPPEN]
Line 0,479,639,479

so wird diese Linie auch dargestellt.

Dementsprechend sollte auch die Füllroutine an dieser Stelle eine Linie berechnen und später anzeigen lassen.

Bye.

ozzi789

BeitragFr, Okt 17, 2008 23:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Kein Bug

Die funktion behandelt einfach die erste linie auf dem Screen als 1 und nicht wie andere Befehle wie Line mit 0


Entweder du schreibst die Funktion um oder du must dich damit abfinden Very Happy
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5
 

Blitzkrieg Bop

BeitragFr, Okt 17, 2008 23:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Kein Bug

Die funktion behandelt einfach die erste linie auf dem Screen als 1 und nicht wie andere Befehle wie Line mit 0


Na ja, man kann es sich auch sehr leicht machen, indem man die Dinge einfach so abstempelt. Warum wird diese letzte Linie nicht berechnet? Warum und unter welchen Umständen wird die Funktion vorzeitig durch ein Return verlassen? Das sind die wichtigen Fragen; das sind die Fragen auf die es hier ankommt. Aber um diese zu beantworten muss man sich zunächst mit dem Algo beschäftigen. Ich habe es versucht, aber bisher keine zufriedenstellende Lösung gefunden.

Und die Tatsache, dass die letzte Linie nicht gemalt, kann man durchaus als Bug bezeichnen. Aber das soll nun auch nicht das Thema sein.

Zitat:
Entweder du schreibst die Funktion um oder du must dich damit abfinden

Was meinst du wohl, warum ich diesen Thread gestartet habe?
Richtig, um Hilfe zur Lösung des Problems zu erhalten.

Aber freut mich, dass du zumindest das Problem jetzt erkannt hast.

Bye.
~ Hey Ho Let's Go ~

ozzi789

BeitragSa, Okt 18, 2008 0:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Funktion ist halt so wie sie ist, was gibts da zu erklären, kein grund zum flamen
Ist es wirklich so schwer jetzt halt einfach nen Pixel dazu zählen ?
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group