| Autor |
Beitrag |
Yogu
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Mi 10.10.07 18:13
Wie berechne ich die Positionen von Koordinaten hinter der Kamera?[meta]3D, Kamera, Koordinaten hinter Kamera, Position berechnen[/meta]
Frage offen
Hallo,
ich habe mal versucht, 3D selber hinzubasteln. Ich habe mir also eine Komponente gebastelt, die 3D-Punkte etc. anzeigen kann. Die hat eine Liste, in der Dreiecke (Triangles) gespeichert werden. Über die Methode Paint wird das Bild neu aufgebaut. Ich arbeite mit DoubleBuffering, was heißt, dass ich eine Bitmap habe, in der ich erst das ganze Bild aufbaue, um es dann fertig in den Objekt-Canvas zu übertragen. Das klappt alles schon mal ganz gut. Bewegen kann man sich übrigens über zwei Vektoren: ViewVector und TurnVector.
In der Methode Paint werden alle Dreiecke abgeklappert und gezeichnet; danach wird "geflippt".
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TGSDraw.Paint; var i: Integer; begin for i := 0 to Triangles.Count-1 do DrawTriangle(Triangles[i]); Flip; end; |
In der Methode DrawTriangle wird ein Dreieck gezeichnet. Vorher brauche wir allerdings noch die Definition eines Dreiecks:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| TGSValue = Double;
TGSVector = record X: TGSValue; Y: TGSValue; Z: TGSValue; end;
TGSPoint2D = record X: TGSValue; Y: TGSValue; end;
TGSTriangle = record Vector1: TGSVector; Vector2: TGSVector; Vector3: TGSVector; end; |
Und die Zeichenprozeduren:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TGSDraw.PaintLine(P1, P2: TGSPoint2D); var Step, xDiff, yDiff, X, Y: TGSValue; i: Integer; const StepLength = 1; begin Step := Sqrt(Sqr(P2.X-P1.X) + Sqr(P2.Y-P1.Y)) / StepLength; if Step = 0 then Step := StepLength; xDiff := (P2.X-P1.X) / Step; yDiff := (P2.Y-P1.Y) / Step; X := P1.X; Y := P1.Y; for i := 1 to Round(Step) do begin X := X + xDiff; Y := Y + yDiff; BackBuffer.Canvas.Pixels[Round(X), Round(Y)] := Pen.Color; end; end;
procedure TGSDraw.PaintTriangle(P1, P2, P3: TGSPoint2D); begin PaintLine(P1, P2); PaintLine(P2, P3); PaintLine(P3, P1); end; |
Also, in DrawTriangle wird ein Dreieck gezeichent. Das Dreieck wird in 3 Linien aufgeteilt, und diese mit DrawLine gezeichnet. Zuerst werden die Koordinaten für die beiden Punkte berechnet, danach wird eine Linie gezeichenet.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TGSDraw.DrawLine(V1, V2: TGSVector); var D1, D2: TGSVector; P1, P2: TGSVector2D; begin V1 := RotateVector(V1); D1.X := V1.X-ViewVector.X; D1.Y := V1.Y+ViewVector.Y; D1.Z := (V1.Z-ViewVector.Z) / 500; V2 := RotateVector(V2); D2.X := V2.X-ViewVector.X; D2.Y := V2.Y+ViewVector.Y; D2.Z := (V2.Z-ViewVector.Z) / 500;
if (D1.Z < 0.01) and (D2.Z < 0.01) then Exit; if (D1.Z < 0.01) and (D2.Z > 0.01) then D1 := GSIntersectionPoint(D1, D2, GSVector(1,0,1), GSVector(1,0,1)); if (D1.Z > 0.01) and (D2.Z < 0.01) then D2 := GSIntersectionPoint(D1, D2, GSVector(1,0,1), GSVector(1,0,1));
if D1.Z < 0.01 then P1.X := NAN else P1.X := Width div 2 + Round(D1.X/D1.Z); if D1.Z < 0.01 then P1.Y := NAN else P1.Y := Height div 2 +Round(D1.Y/D1.Z); if D2.Z < 0.01 then P2.X := NAN else P2.X := Width div 2 + Round(D2.X/D2.Z); if D2.Z < 0.01 then P2.Y := NAN else P2.Y := Height div 2 +Round(D2.Y/D2.Z); PaintLine(P1, P2); end; |
Und diese Methode zeichnet ein Dreieck:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TGSDraw.DrawTriangle(Triangle: TGSTriangle); begin DrawLine(Triangle.Vector1, Triangle.Vector2); DrawLine(Triangle.Vector2, Triangle.Vector3); DrawLine(Triangle.Vector3, Triangle.Vector1); end; |
Um das zu verstehen, muss ich erst meine "Tiefentheorie" vorstellen:
Je weiter ein Punkt enternt ist, dessto näher neigt er zur Betrachtermitte. Ein Punkt, der genau vor der Nase (oder besser vor den Augen) schwebt, dehnt sich über die Gesamte Anzeigefläche aus. Weiter hinten sind die Punkte enger zusammen, deshalb erscheinen die Objekte dort kleiner.
Dass das stimmt, könnt ihr in meinem Programm sehen.
GameStudio 3D, ohne Rotatoin
GameStudio 3D, Anfang Rotation
GameStudio 3D, Rotation abgeschlossen
GameStudio 3D, fehlerhafte Berechnung von halbsichtbaren Linien
Jetzt aber mein Problem:
Wie soll ich Linien zeichnen, die zum Teil hinter der Kamera liegen? Ich habe schon erfahren, dass ich einen Hilfspunkt erstellen muss, der gerade noch im sichtbaren Bereich liegt. Dazu bräuchte ich aber den Schnittpunkt von zwei 3D-Geraden. und das ist alles andere als einfach... Ich habe einen Versuch gewagt, den Schnittpunkt zu berechnen. Aber igendwas stimmt noch nicht. In der Schnittpunktsmethode liegt der Fehler nicht, die habe ich schon getestet.
So habe ich die Schnittpunktsmethode definiert:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function GSIntersectionPoint(V1, V2, V3, V4: TGSVector): TGSVector; var M1, M2, C1, C2: TGSValue; begin if V1.X-V2.X = 0 then M1 := NAN else M1 := (V1.Y-V2.Y)/(V1.X-V2.X); if V3.X-V4.X = 0 then M2 := NAN else M2 := (V3.Y-V4.Y)/(V3.X-V4.X); C1 := V1.Y-M1*V1.X; C2 := V3.Y-M2*V3.X; if M1-M2 = 0 then Result.X := NAN else Result.X := (C2-C1)/(M1-M2); if M1-M2 = 0 then Result.Y := NAN else Result.Y := M1*(C2-C1)/(M1-M2)+C1;
if V1.X-V2.X = 0 then M1 := NAN else M1 := (V1.Z-V2.Z)/(V1.X-V2.X); if V3.X-V4.X = 0 then M2 := NAN else M2 := (V3.Z-V4.Z)/(V3.X-V4.X); C1 := V1.Z-M1*V1.X; C2 := V3.Z-M2*V3.X; if M1-M2 = 0 then Result.Z := NAN else Result.Z := M1*(C2-C1)/(M1-M2)+C1; end; |
Ihr könnt die die Methode auch testen:
Schnittpunkt 2D
Schnittpunkt 3D
Die GSW-Datei
GSW heißt GameStudioWorld. Und so ist die Datei aufgebaut:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| [HEAD] Title=Titel der Datei [VECTORS] Vektorname1=X Y Z Vektorname2=X Y Z Vektorname3=X Y Z [TRIANGLES] Dreieck1=Vektornanme1 Vektorname2 Vektorname3 |
Ihr könnt eine GSW-Datei über das Datei-Menü öffnen.
Die letzten 3 Downloads sind auch im Anhang.
Einloggen, um Attachments anzusehen!
Zuletzt bearbeitet von Yogu am Sa 29.12.07 17:38, insgesamt 10-mal bearbeitet
|
|
Logikmensch
      
Beiträge: 390
Win XP
Delphi 2007 Prof., XE2, XE5
|
Verfasst: Do 11.10.07 09:07
Also erst einmal: Ich liebe Dein Programm schon jetzt. Ich bin ein riesen Fan von gerade solchen 3D-Projekten in der Anfangsphase.
Um die Division durch Null abzufangen würd' ich erst mal
Delphi-Quelltext 1:
| if abs(DiffZ)>0 then... |
schreiben, denn bei Gleitkommazahlen kann es leicht mal passieren, dass eine -0 bei Berechnungen rauskommt. Das kann, muss aber nicht Dein Problem lösen. Die Frage ist, was mit den <0-Abfragen dann passieren müsste. Aber ich würde es erst einmal so ausprobieren.
Viel Erfolg und bitte weitermachen - du bist auf dem richtigen Weg!
_________________ Es gibt keine Probleme - nur Lösungen!
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Do 11.10.07 19:30
Was mir jetzt noch auffällt, ist, dass das Ganze unendlich langsam wird, wenn ich mich der Mitte nährere. Das müsste dann die Beinahe-Division-Durch-Null sein. Die dauert ja bekanntlich bei kleine Zahlen ziemlich lange. Und danach kommt irgendwann die Division durch Null, obwohl ich die (auch mit Abs) schon geprüft habe. Sehr komisch...
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Do 11.10.07 19:46
So, jetzt habe ich ein bisschen an der Drehung gearbeteitet. Ich hab das von einem Buch abgeleitet, und irgendwas ist falsch daran. Ich schreib erst mal das vom Buch:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TPoly2D.Rotate (Winkel: Integer); var cosq, sinq: Extended; i, xx, yy: Integer; begin Clear; cosq := cos (Winkel*Pi/180); sinq := sin (Winkel*Pi/180); for i := 1 to EckZahl do begin xx := Vertex[i].X; yy := Vertex[i].Y; Vertex[i].X := Round (xx * cosq - yy * sinq); Vertex[i].Y := Round (xx * sinq + yy * cosq); end; Draw; end; |
(Wenns jemand interessiert oder Copyrights verletzt, das ist von Hans-Georg Schumann in 3D-Programmieren mit Delphi für Kids)
Und jetzt meins:
Befor die Vektoren zum Anzeigen vorbereitet werden, wird erst einmal das ausgefürt:
Delphi-Quelltext 1: 2:
| Vector.X := Vector.X * cos(TurnVector.Z) - Vector.Y * sin(TurnVector.Z); Vector.Y := Vector.X * sin(TurnVector.Z) + Vector.Y * cos(TurnVector.Z); |
So, ihr könnts euch vorstellen, was passiert. Der Würfel wird zusammengeklappt. Ich glaube, das sind typische Anzeichen von irgendwelchen Verwechslungen, blos welche??
Zuletzt bearbeitet von Yogu am Do 11.10.07 20:29, insgesamt 1-mal bearbeitet
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Do 11.10.07 20:28
So, jetzt habe ich aber was geschafft. Die Drehung dürfte abgehakt sein, dank einem Tutorial. Da ist das alles schön sauber erklärt.
Mein einziges Problem ist jetzt das "durchgehen" durch den Würfel. Nährers siehe oben.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 12.10.07 10:21
IMHO fragst Du nicht korrekt ab, ob ein Punkt hinter Dir ist.
Das kannst Du leicht erreichen, indem Du die Strecke mit der geringsten Länge ermittelst, die senkrecht zur Blickrichtung ist. Ist der Vektor (vom Stand-Punkt) zum zu zeichnenden Punkt) entgegen der Blickrichtung gerichtet, so liegt der Punkt hinter dir.
Liegen beide Punkte einer zu zeichnenden Gerade hinter Dir, wird die Gerade ignoriert.
Liegen beide Punkte vor Dir, wird die Gerade gezeichnet.
Liegt nur ein Punkt vor Dir, der andere hinter Dir, so wird ein Hilfspunkt berechnet, der zwischen A und B genau auf der Kamera-Ebene liegt. Von diesem Punkt aus wird nur der Teil der Geraden gezeichnet, die vor Dir liegt.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Logikmensch
      
Beiträge: 390
Win XP
Delphi 2007 Prof., XE2, XE5
|
Verfasst: Fr 12.10.07 13:02
Hallo!
Schön, dass Du weitergekommen bist. Übrigens: Nochmal zur Division durch Null:
Du hast geschrieben:
| Zitat: | | Was mir jetzt noch auffällt, ist, dass das Ganze unendlich langsam wird, wenn ich mich der Mitte nährere. Das müsste dann die Beinahe-Division-Durch-Null sein. Die dauert ja bekanntlich bei kleine Zahlen ziemlich lange. Und danach kommt irgendwann die Division durch Null, obwohl ich die (auch mit Abs) schon geprüft habe. Sehr komisch... |
Wichtig ist, dass man bei Gleitkommazahlen nicht wirklich 100%ig sicher sein kann, dass eine abgeprüfte Zahl sich bei einer Berechnung nicht doch wieder als Null gibt. Beispiel:
Der Test =0 ist false, weil die Zahl vielleicht als 0.0000000000000000000000000001212 gespeichert ist, aber bei einer Berechnung finden Kommaverschiebungen (Mantissenanpassungen) statt, die aus der vermeitlicherweise Nicht-Null wieder eine Null machen.
Ich muss sagen, dass ich das Division-durch-Null-Problem ohnehin nie verstanden habe, denn für mich ist x/0 nicht undefiniert, sondern schließlich unendlich (bzw. -unendlich), denn teile ich einen Kuchen (theoretisch) mit einem Messer in 0 Teile, also praktisch gar nicht, dann muss ich folgerichtig unendlich viele, unendlich schmale Kuchenstücke vor mir haben, die zusammen den ganzen Kuchen ergeben. Ich hätte anstelle eines Fehlers als Ergebnis MAXFLOAT (bzw. -MAXFLOAT) des jeweiligen Zahlenbereiches zurückgeliefert.
Umgekehrt müsste x/MAXFLOAT dann natürlich wieder 0 ergeben. Dann aber die einzig richtige und echte Null.
Ist vielleicht ein Verbesserungsvorschlag für Borland. Sorry, dass ich jetzt etwas off-topic wurde.
Nein, will man sicher auf Null testen, dann sollte man die Nachkommastellen z.B. nach 10 Kommastellen abschneiden bzw. runden. Man kann auch gut mit CompareValues arbeiten, und gibt für den Parameter Epsilon einen entsprechenden Kommazahlenwert ein.
_________________ Es gibt keine Probleme - nur Lösungen!
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Fr 12.10.07 15:10
Danke für die Tipps! Aber wie berechne ich den Schnittpunkt zwischen den beiden Punkten? Wenn ich mir da jetzt was zusammenbasteln würde, wäre das so was von langsam... Ich bin in Klasse 8, wir sind noch am 2D-Koordinatensystem. Später lernt man sicher noch eine Formel für 3D, oder? Wäre echt nett, wenn einer so eine Formel posten würde. Wenn es eine Formel ist, müsste sie nicht gekürzt sein, das würde ich auch noch hinbekommen.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Fr 12.10.07 16:51
Schau Dir mal die Sources von Projekt Omorphia an. Da gibt's ne Reihe OMath*.pas, wo Du eigentlich alles nötige drin finden solltest. HTH.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Fr 12.10.07 19:40
Na prima, soll ich mir jetzt etwa alle Units runterladen und versuchen, den Grundgedanken der Funktion LineIntersection zu verstehen? Die haben da so viele Prozedurverschachtelungen, da blickt ja keiner mehr durch. Tut mir leid, aber mit diesem Link kann ich nichts anfangen.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Sa 13.10.07 12:21
Unsere Bibliothek ist schon etwas optimiert, weshalb wir dort an den Stellen schon leicht abstrahiert haben. Ein Tutorial, was wir da machen, findest Du u.a. hier.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Sa 13.10.07 14:36
Ich habe jetzt gesehen, dass dieses DelphiGL schon etwas sehr großes ist. Das wäre auch sehr hilfreich, aber leider verwende ich Delphi 3 und da müsste man schon einiges umschreiben. Und nur durch durchlesen kapiere ich nicht alles.
Aber ich habe mir jetzt ein bisschen Gedanken darüber gemacht, wie ein Schnittpunkt zweier Geraden im 3D-Koordinatensystem beschrieben wird. Und das ist dabei rausgekommen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function GSIntersectionPoint2D(V1, V2, V3, V4: TGSVector2D): TGSVector2D; var M1, M2, C1, C2: TGSValue; begin if V1.X-V2.X = 0 then Exit; if V3.X-V4.X = 0 then Exit; M1 := (V1.Y-V2.Y)/(V1.X-V2.X); M2 := (V3.Y-V4.Y)/(V3.X-V4.X); if M1-M2 = 0 then Exit; C1 := V1.Y-M1*V1.X; C2 := V3.Y-M2*V3.X; Result.X := (C2-C1)/(M1-M2); Result.Y := M1*(C2-C1)/(M1-M2)+C1; end; |
Das ist die 2D-Version. Die hat eigentlich keinen Fehler, ich habe hier ein Beispielprogramm geschrieben: Schnittpunkt
Und das ist die 3D-Ausgabe:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function GSIntersectionPoint(V1, V2, V3, V4: TGSVector): TGSVector; var M1, M2, C1, C2: TGSValue; begin if V1.X-V2.X = 0 then M1 := NAN else M1 := (V1.Y-V2.Y)/(V1.X-V2.X); if V3.X-V4.X = 0 then M2 := NAN else M2 := (V3.Y-V4.Y)/(V3.X-V4.X); C1 := V1.Y-M1*V1.X; C2 := V3.Y-M2*V3.X; if M1-M2 = 0 then Result.X := NAN else Result.X := (C2-C1)/(M1-M2); if M1-M2 = 0 then Result.Y := NAN else Result.Y := M1*(C2-C1)/(M1-M2)+C1;
if V1.X-V2.X = 0 then M1 := NAN else M1 := (V1.Z-V2.Z)/(V1.X-V2.X); if V3.X-V4.X = 0 then M2 := NAN else M2 := (V3.Z-V4.Z)/(V3.X-V4.X); C1 := V1.Z-M1*V1.X; C2 := V3.Z-M2*V3.X; if M1-M2 = 0 then Result.Z := NAN else Result.Z := M1*(C2-C1)/(M1-M2)+C1; end; |
Ich weiß nicht, ob die funktioniert, es wäre viel zu kompliziert das Schnittpunkt-Programm ins 3D umzuschreiben, aber irgendwas stimmt nicht.
So rufe ich die Methode auf:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TGSDraw.DrawLine(V1, V2: TGSVector); var D1, D2: TGSVector; P1, P2: TGSVector2D; begin V1 := RotateVector(V1); D1.X := V1.X-ViewVector.X; D1.Y := V1.Y+ViewVector.Y; D1.Z := (V1.Z-ViewVector.Z) / 500; V2 := RotateVector(V2); D2.X := V2.X-ViewVector.X; D2.Y := V2.Y+ViewVector.Y; D2.Z := (V2.Z-ViewVector.Z) / 500;
if (D1.Z < 0.01) and (D2.Z < 0.01) then Exit; if (D1.Z < 0.01) and (D2.Z > 0.01) then D1 := GSIntersectionPoint(D1, D2, GSVector(1,0,1), GSVector(1,0,1)); if (D1.Z > 0.01) and (D2.Z < 0.01) then D2 := GSIntersectionPoint(D1, D2, GSVector(1,0,1), GSVector(1,0,1));
if D1.Z < 0.01 then P1.X := NAN else P1.X := Width div 2 + Round(D1.X/D1.Z); if D1.Z < 0.01 then P1.Y := NAN else P1.Y := Height div 2 +Round(D1.Y/D1.Z); if D2.Z < 0.01 then P2.X := NAN else P2.X := Width div 2 + Round(D2.X/D2.Z); if D2.Z < 0.01 then P2.Y := NAN else P2.Y := Height div 2 +Round(D2.Y/D2.Z); PaintLine(P1, P2); end; |
Vielleicht sieht jemand, wo der Fehler liegt, ich würde mich riesig freuen, wenn ihr eine Lösung wüsstet.
Ich habe auch das komplette Programm noch mal hochgeladen, wenn ihr es testen wollt.
Gamestudio 3D, Halbsichtbare Linien fehlerhaft
|
|
Yogu 
      
Beiträge: 2598
Erhaltene Danke: 156
Ubuntu 13.04, Win 7
C# (VS 2013)
|
Verfasst: Mo 15.10.07 18:43
So, die Schnittpunktsfunktion habe ich nun auch im 3D getestet, daran liegt es nicht. Es muss also im Aufruf liegen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TGSDraw.DrawLine(V1, V2: TGSVector); var D1, D2: TGSVector; P1, P2: TGSVector2D; begin V1 := RotateVector(V1); D1.X := V1.X-ViewVector.X; D1.Y := V1.Y+ViewVector.Y; D1.Z := (V1.Z-ViewVector.Z) / 500; V2 := RotateVector(V2); D2.X := V2.X-ViewVector.X; D2.Y := V2.Y+ViewVector.Y; D2.Z := (V2.Z-ViewVector.Z) / 500;
if (D1.Z < 0.01) and (D2.Z < 0.01) then Exit; if (D1.Z < 0.01) and (D2.Z > 0.01) then D1 := GSIntersectionPoint(D1, D2, GSVector(1,0,1), GSVector(1,0,1)); if (D1.Z > 0.01) and (D2.Z < 0.01) then D2 := GSIntersectionPoint(D1, D2, GSVector(1,0,1), GSVector(1,0,1));
if D1.Z < 0.01 then P1.X := NAN else P1.X := Width div 2 + Round(D1.X/D1.Z); if D1.Z < 0.01 then P1.Y := NAN else P1.Y := Height div 2 +Round(D1.Y/D1.Z); if D2.Z < 0.01 then P2.X := NAN else P2.X := Width div 2 + Round(D2.X/D2.Z); if D2.Z < 0.01 then P2.Y := NAN else P2.Y := Height div 2 +Round(D2.Y/D2.Z); PaintLine(P1, P2); end; |
Ich weiß auch nicht, ob das so stimmen sollte, oder was da falsch ist. Ich berechne einfach den gerade noch sichtbaren Punkt auf der Gerade und nehme den statt dem unsichtbaren.
|
|
|