Registriert: Do Mär 05, 2009 20:17 Beiträge: 284 Wohnort: Kaiserslautern
Hallo,
ich möchte durch meine Dreiecksflächen eine Schnittlinie berechnen. Habe aber keine Ahnung, wie ich kenne die Vertices meiner Fläeche und würde gern erstmal durch eine yz parallele Ebene zb. bei x=10 schneiden.
ich dachte ich schaue mir die 3 x Werte meiner 3 Vertices der Dreiecksfläche an und sehe ja dann ob einer davon <= 10 und 2 >= 10 sind. Ist dies der Fall wollte ich die beiden Schnittpunkte berechnen und diese dann per Linie verbinden.
Leider weiss ich aber nicht wie ich den Schnittpunkt von Ebene und Strecke berechne, und googeln hat mich mehr verwirrt als zu helfen. Hat jemand vielleicht einen Tipp für mich?
Dank
Wölfchen!
Zuletzt geändert von Wölfchen am Di Okt 19, 2010 07:57, insgesamt 1-mal geändert.
Schnittpunkt von Ebene und Strecke: Nimm an, deine Strecke sei eine Gerade. Bestimm den Schnittpunkt, dann prüfe, ob er auf der Strecke liegt. Also angenommen, du willst die Strecke von A nach B. Dann brauchst du erst mal eine Gerade, die durch beide Punkte durchgeht, idealerweise in Parameterdarstellung (also ursprung und Richtung)
Code:
Ursprung:= A; Richtung:= B - A;
Die Ebene brauchst du in Normalvektordarstellung(also ax + by + cz - d = 0) Mathemathisch betrachtet setzt du in x, y, z jetzt die Daten aus deiner Geraden ein: a*(Ursprung.x + t*Richtung.x) + b*(Ursprung.y + t*Richtung.y) + c*(Ursprung.z + t*Richtung.z) - d = 0 So. Eine Gleichung in einer (skalaren) Unbekannten (t). Diese lässt sich umformen zu: vector3(a, b, c) dot Ursprung + t * (vector3(a, b, c) dot Richtung) - d = 0 weiter zu: t * (vector3(a, b, c) dot Richtung) = d - vector3(a, b, c) dot Ursprung und wird schließlich zu: t = (d - vector3(a, b, c) dot Ursprung) / (vector3(a, b, c) dot Richtung)
Das letzte sieht doch schon ziemlich brauchbar aus. Jetzt muss nur noch erwähnt werden, dass der Schnittpunkt Ursprung + t * Richtung ist. Wenn t zwischen 0 und 1 liegt, gibt es einen Schnittpunkt zwischen deiner Strecke und der Ebene.
Code:
function SchnittpunktBestimmen( Ebene: TVector4; Ursprung, Richtung: TVector3; out Schnittpunkt: TVector3): boolean; var t: single; function Dot3(a: TVector4; b: TVector3): single; begin result:= a.x * b.x + a.y * b.y + a.z * b.z; end; begin t:= (Ebene.w - Dot3(Ebene, Ursprung)) / Dot3(Ebene, Richtung); if (t<0) or (t>1) then begin result:= false; exit; end; Schnittpunkt:= Ursprung + t * Richtung; result:= true; end;
Hoffe, das war verständlich. Wenn nicht, der code SOLLTE trotzdem funktionieren. Vorraussetzung natürlich, dass er an die zugrundeliegenden Vektortypen angepasst wird. Ach, ja: Ich nehme einfach an, dass single * Vector3 den Vector skaliert. Wüsste auch nicht, was man sonst mit so ner Multiplikation machen sollte.
mfg
shark
ps: Wenn du das Dreieck clippen willst, kanns sein, dass du dabei ein Quad bekommst. Dass muss wahrscheinlich noch in 2 Dreiecke zerlegt werden. Je nachdem, was du damit vorhast.
Nein. Das ist nur a. x steht dann in deinen Vectoren, Geraden, sonstwas. Ist halt eine Variable (im mathematischen Sinn)
Zitat:
was ich nicht kapiere ist, was ich zum beispiel eintragen muss wenn ich das teil an x=1, 2 oder 16,4 clippen will...
Ich glaube einmal erwähnt zu haben, dass die Ebene in Normalvektorform gegeben ist. Hab angenommen, das sei bekannt, muss aber zugeben, dass ich selber auch nicht gleich verstanden hab, was das heißt (damals vor zwei Jahren).
Also, in der Mathemathik sieht die Ebenengleichung so aus: a*x + b*y + c*z = d Dabei ist der Vector (a, b, c) der Normalvektor auf die Ebene (daher Normalvektorform). d ist der Abstand vom Nullpunkt. Der Vector (x, y, z) liegt genau dann auf der Ebene, wenn er die Gleichung erfüllt.
Wenn du zum Beispiel bei x = 1 clippen willst, dann sieht deine Ebenengleichung so aus: 1*x + 0*y + 0*z = 1 oder so -1*x + 0*y + 0*z = -1 Je nachdem, in welche Richtung du clippen willst.
Code:
Schnittebene:= [1, 0, 0, 1];
Weil x,y, z steht nur für die Mathematiker da.
Bei x = 2 wärs zB
Code:
Schnittebene:= [1, 0, 0, 2]
und NICHT
Code:
Schnittebene:= [2, 0, 0, 1]
das ist nämlich gleichbedeutend mit
Code:
Schnittebene:= [1, 0, 0, 0.5]
schneidet also bei x = 0.5 ab
d ist nämlich genau dann wirklich der Abstand vom Nullpunkt, wenn der Normalvektor die Länge 1 hat.
Also zur erklärung des ganzen: Wenn du bei x = was_auch_immer abschneiden willst, dann interessiert dich die y und z Koordinate nicht. Deswegen brauchst du da in der Ebene (bei b und c) eine 0. Die x koordinate interessiert dich aber. deswegen brauchst du bei der Ebene da was anderes als eine 0 (halt idealerweise eine Zahl, die insgesamt die Länge 1 ergibt, also in diesem Berspiel entweder 1 oder -1). Ob 1 oder -1 macht aber auch einen großen Unterschied, weil das entscheidet, welche Seite der Ebene er abschneidet.
d ist dann (idealerweise) der Abstand vom Nullpunkt. Un zwar immer in Richtung des Normalvektors. Wenn du also das Vorzeichen vom Normalvektor umdrehst (um die andere Seite abzuschneiden), dann musst du auch das Vorzeichen von d umdrehen, weil sonst verschiebt sich die Ebene.
Hoffe, das war einigermaßen verständlich. Ansonsten noch mal nachfragen, weil vielleicht kann wer anders es ja besser erklären Wobei ich jetzt auch nicht weiß, wieviel Vorwissen über Vektorrechnung da ist. Von da wirds schwer, genau beim richtigen Punkt anzusetzen.
Also, in der Mathemathik sieht die Ebenengleichung so aus: a*x + b*y + c*z = d
Ich bin mir nicht sicher was OpenGL verwendet, aber eigentlich benutzt man normalerweise a*x + b*y + c*z + d = 0, also beim d muss man ggf. das Vorzeichen umkehren.
Hab mir mal gedacht, fürs Verständnis ist ein Bild vielleicht nicht schlecht
Dateianhang:
Plane_Equation.png
Also, das Bild beschreibt so ziemlich den umständlichsten Weg, zu prüfen, auf welcher Seite der Ebene ein Punkt liegt, aber es geht dabei auch eher darum, zu erklären, wie eine Ebenengleichung funktioniert. Also beim Bild siehts so aus, als würde man zuerst eine Gerade durch den Nullpunkt, die normal auf die Ebene steht, aufstellen, den Punkt (hab ihn mal A genannt) auf die Gerade projizieren, und dann die Länge vom Vektor, der dabei rauskommt ausrechnen. Das ist mathemathisch gesehen zwar nicht falsch, es ist aber tatsächlich wesentlich einfacher. Dadurch, dass die Gerade (die wir uns nur denken) durch den Nullpunkt geht, und die EbenenNormale die Länge 1 hat kann man nämlich diese drei sachen mit einem einzelnen dot product berechnen. Das Dot product sieht nämlich so aus: a*x + b*y + c*z, wobei (a, b, c) der Normalvektor auf die Ebene ist, und (x, y, z) der Punkt. erinnert doch irgendwie an die Ebenengleichung, nicht?
Jetzt haben wir nämlich (durch das Dot product) den "Projizierten Abstand von A zum Ursprung (Nullpunkt)" Wenn wir wissen wollen, auf welcher Seite der Ebene A liegt, müssen wir jetzt nur noch diesen Abstand mit dem Abstand der Ebene vom Nullpunkt vergleichen. Der Mathematiker schreibt das so a*x + b*y + c*z = d
[unwichtig] So erfahren wir aber nur, ob der Punkt auf der Ebene liegt Deswegen berechnen wir stattdessen a*x + b*y + c*z - d, weil dann können wir prüfen, ob das > 0 ist (liegt auf der sichtbaren Seite), = 0 ist (liegt genau auf der Ebene), oder < 0 ist (liegt auf der unsichtbaren Seite) [/unwichtig]
So. ich hoffe, das erklärt einigermaßen, wie so eine Ebenengleichung funktioniert, und sorgt nicht nur für zusätzliche Verwirrung.
[edit]hast recht, coolcat. gegebenenfalls sind die Vorzeichen von d in meinen Beiträgen falsch. [/edit] [edit2]deine Variante ist sogar sinnvoller, weils sich mit SIMD besser berechnen lasst, und das benutzen die graphikkarten immerhin[/edit2]
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
Registriert: Do Mär 05, 2009 20:17 Beiträge: 284 Wohnort: Kaiserslautern
sharkman hat geschrieben:
...
Wenn du zum Beispiel bei x = 1 clippen willst, dann sieht deine Ebenengleichung so aus: 1*x + 0*y + 0*z = 1 oder so -1*x + 0*y + 0*z = -1 Je nachdem, in welche Richtung du clippen willst.
Code:
Schnittebene:= [1, 0, 0, 1];
Weil x,y, z steht nur für die Mathematiker da.
Bei x = 2 wärs zB
Code:
Schnittebene:= [1, 0, 0, 2]
... mfg
okay, erstmal danke für die antwort(en)...
soweit hatte ich es mir eigentlich auch zusammengereimt...
leider funktioniert es nicht.
wenn ich für meine schnittebene 1,0,0,1 eingebe passiert überhaupt nichts... wenn ich
Code:
Schnittebene:= [0, 1, 0, 0]
setze, dann schneidet er bei x=0, setze ich nun für den letzten wert also schnittebene[3] zahlen zwischen -0,5 und -1 sowie 0,5 und 1 schneidet er irgendwie schräg um die z achse so als würde die schnittebene um die z achse rotieren.
Ähm... grad bei den Clipping planes will OpenGL glaub ich double. Wenn du ihm single gibst kommt komisches Zeug raus. Oder wars umgekehrt? Naja, jedenfals könnte da das Problem liegen. Zumindest hatte ich mal diesen Fehler, und hab Tage gebraucht, um dann zufällig draufzukommen.
Zitat:
setze ich nun für den letzten wert also schnittebene[3] zahlen zwischen -0,5 und -1 sowie 0,5 und 1 schneidet er irgendwie schräg um die z achse so als würde die schnittebene um die z achse rotieren.
komisch. das müsste eigentlich die y achse betreffen, wenn das Problem wirklich der Datentyp ist. Ansonsten müsste genau dieses Phänomen bei Schnittebene[2] auftreten.
ansonsten heißts eigentlich
Code:
glClipPlane(GL_CLIP_PLANE1, @schnittebene[0]);
und nicht
Code:
glClipPlane(GL_CLIP_PLANE1, @schnittebene);
, obwohl das eigentlich keinen Unterschied machen dürfte sofern schnittebene ein statisches Array ist. Bei Dynamischen Arrays hast du halt gegebenenfalls einen Pointer zu viel.
Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.