Schnelle Kollisionsroutinen
Verfasst: 23.05.2005 20:58
Ich bin schon ein paar Wochen an ein paar kleinen Kollisionsroutinen.
Weil wir vor ein paar Wochen auch mit der Vektorrechnung in Mathematik begonnen haben, faszinieren die Vektoren mich immer noch und ich hab gleich mal mehrere Kapitel weiter geschlagen und das wichtigste mitgenommen.
Das hier ist das Ergebnis der hauptsächlich in Musik und Geschichte entwickelten Kollisionsroutinen für 2D und 3D.
Die Kollison von Gerade mit Ebene, Parallelogramm oder Dreieck ist schon auf dem Blatt, aber noch nicht in PureBasic umgesetzt.
Daher wird sich von Zeit zu Zeit immer wieder mal was neues hier finden.
Achja: Wenn es Fehler gibt, dann bitte schnell melden. Ich habe die Procedures selbst noch nicht getestet. Ich weiß aber, dass [c]RayHitsSphere()[/c] auf jeden Fall funktioniert. Die wurde schon getestet.
Weil wir vor ein paar Wochen auch mit der Vektorrechnung in Mathematik begonnen haben, faszinieren die Vektoren mich immer noch und ich hab gleich mal mehrere Kapitel weiter geschlagen und das wichtigste mitgenommen.
Das hier ist das Ergebnis der hauptsächlich in Musik und Geschichte entwickelten Kollisionsroutinen für 2D und 3D.
Die Kollison von Gerade mit Ebene, Parallelogramm oder Dreieck ist schon auf dem Blatt, aber noch nicht in PureBasic umgesetzt.
Daher wird sich von Zeit zu Zeit immer wieder mal was neues hier finden.
Achja: Wenn es Fehler gibt, dann bitte schnell melden. Ich habe die Procedures selbst noch nicht getestet. Ich weiß aber, dass [c]RayHitsSphere()[/c] auf jeden Fall funktioniert. Die wurde schon getestet.
Code: Alles auswählen
XIncludeFile "Structures.pbi"
;{- 2D LineHitsLine
;Errechnet den Schnittpunkt zweier Linie
; [in] Line1p : Stützvektor der 1. Linie
; [in] Line1r : Richtungs- und Längenvektor der 1. Linie
; [in] Line2p : Stützvektor der 2. Linie
; [in] Line2r : Richtungs- und Längenvektor der 2. Linie
; [out] pHit : Schnittpunkt
; [out] RETURN : #True bei Schnitt
Procedure.l LineHitsLine_2D_Vector(*Line1p.Vector2D, *Line1r.Vector2D, *Line2p.Vector2D, *Line2r.Vector2D, *pHit.Vector2D)
Protected d.f, Ds.f, s.f, Dt.f, t.f
; Die Determinante d berechnen
d = *Line1r\y * *Line2r\x - *Line1r\x * *Line2r\y
; Wenn d null ist, sind die Linien parallel
If d < 0.0001 And d > -0.0001 : ProcedureReturn #False : EndIf
; Determinante Ds berechnen
Ds = (*Line2p\y - *Line1p\y) * *Line2r\x - (*Line2p\x - *Line1p\x) * *Line2r\y
; s = Ds / d berechnen und prüfen, ob s in den Grenzen liegt
s = Ds / d
If s < 0.0 Or s > 1.0 : ProcedureReturn #False : EndIf
; Jetzt berechnen wir Dt und t
Dt = (*Line2p\y - *Line1p\y) * *Line1r\x - (*Line2p\x - *Line1p\x) * *Line1r\y
t = Dt / d
If t < 0.0 Or t > 1.0 : ProcedureReturn #False : EndIf
; Die Linien schneiden sich!
; Wir tragen den Schnittpunkt ein.
If *pHit
*pHit\x = *Line1p\x + s * *Line1r\x
*pHit\y = *Line1p\y + s * *Line1r\y
EndIf
ProcedureReturn #True
EndProcedure
;Errechnet den Schnittpunkt zweier Linie
; [in] Line1 : 1. Linie mit Line2D-Struktur
; [in] Line2 : 2. Linie mit Line2D-Struktur
; [out] pHit : Schnittpunkt
; [out] RETURN : #True bei Schnitt
Procedure.l LineHitsLine_2D_Point(*Line1.Line2D, *Line2.Line2D, *pHit.Vector2D)
Protected Line1p.Vector2D, Line1r.Vector2D, Line2p.Vector2D, Line2r.Vector2D
Line1p\x = *Line1\x1
Line1p\y = *Line1\y1
Line1r\x = *Line1\x2 - *Line1\x1
Line1r\y = *Line1\y2 - *Line1\y1
Line2p\x = *Line2\x1
Line2p\y = *Line2\y1
Line2r\x = *Line2\x2 - *Line2\x1
Line2r\y = *Line2\y2 - *Line2\y1
ProcedureReturn LineHitsLine_2D_Vector(@Line1p, @Line1r, @Line2p, @Line2r, *pHit)
EndProcedure
;Errechnet den Schnittpunkt zweier Linie
; [in] Line1x1 : x-Koordinate des Anfangspunktes der 1. Linie
; [in] Line1y1 : y-Koordinate des Anfangspunktes der 1. Linie
; [in] Line1x2 : x-Koordinate des Endpunktes der 1. Linie
; [in] Line1y2 : y-Koordinate des Endpunktes der 1. Linie
; [in] Line2x1 : x-Koordinate des Anfangspunktes der 2. Linie
; [in] Line2y1 : y-Koordinate des Anfangspunktes der 2. Linie
; [in] Line2x2 : x-Koordinate des Endpunktes der 2. Linie
; [in] Line2y2 : y-Koordinate des Endpunktes der 2. Linie
; [out] pHit : Schnittpunkt
; [out] RETURN : #True bei Schnitt
Procedure.l LineHitsLine_2D_Koord(Line1x1.f, Line1y1.f, Line1x2.f, Line1y2.f, Line2x1.f, Line2y1.f, Line2x2.f, Line2y2.f, *pHit.Vector2D)
Protected Line1p.Vector2D, Line1r.Vector2D, Line2p.Vector2D, Line2r.Vector2D
Line1p\x = Line1x1
Line1p\y = Line1y1
Line1r\x = Line1x2 - Line1x1
Line1r\y = Line1y2 - Line1y1
Line2p\x = Line2x1
Line2p\y = Line2y1
Line2r\x = Line2x2 - Line2x1
Line2r\y = Line2y2 - Line2y1
ProcedureReturn LineHitsLine_2D_Vector(@Line1p, @Line1r, @Line2p, @Line2r, *pHit)
EndProcedure
;}
;{- 2D Lines and Points
;Errechnet den nächsten Punkt auf einer Linie zu einem äußeren Punkt
; [in] a : Stützverktor der Linie
; [in] b : Richtungs- und Längenvektor der Linie
; [in] P : äußerer Punkt
; [out] P_out : nächster Punkt auf der Linie
; [out] RETURN : #True, wenn der P_out-Pointer nicht Null
Procedure ClosestPointOnLine_2D_Vector(*a.Vector2D, *b.Vector2D, *P.Vector2D, *P_out.Vector2D)
Protected PMinusA.Vector2D, b.Vector2D, numerator.f, demoninator.f, M.f
PMinusA\x = *P\x - *a\x
PMinusA\y = *P\y - *a\y
numerator = PMinusA\x * b\x + PMinusA\y * *b\y
denominator = b\x * b\x + b\y * b\y
If denominator = 0
M = 0.0
Else
M = numerator / denominator
EndIf
If M < 0.0 : M = 0.0 : EndIf
If M > 1.0 : M = 1.0 : EndIf
If *P_out
*P_out\x = *a\x + M * b\x
*P_out\y = *a\y + M * b\y
ProcedureReturn #True
EndIf
EndProcedure
;Errechnet den nächsten Punkt auf einer Linie zu einem äußeren Punkt
; [in] L1 : Anfangspunkt der Linie
; [in] L2 : Endpunkt der Linie
; [in] P : aüßerer Punkt
; [out] P_out : nächster Punkt auf der Linie
; [out] RETURN : #True, wenn der P_out-Pointer nicht Null
Procedure ClosestPointOnLine_2D_Point(*L1.Vector2D, *L2.Vector2D, *P.Vector2D, *P_out.Vector2D)
Protected b.Vector2D
b\x = *L2\x - *L1\x
b\y = *L2\y - *L1\y
ProcedureReturn ClosestPointOnLine_2D_Vector(*L1, @b, *P, *P_out)
EndProcedure
;Errechnet den nächsten Punkt auf einer Linie zu einem äußeren Punkt
; [in] LX1 : x-Koordinate des Anfangspunktes der Linie
; [in] LY1 : y-Koordinate des Anfangspunktes der Linie
; [in] LX2 : x-Koordinate des Endpunktes der Linie
; [in] LY2 : y-Koordinate des Endpunktes der Linie
; [in] PX : x-Koordinate des äußeren Punktes
; [in] PY : y-Koordinate des äußeren Punktes
; [out] P_out : nächster Punkt auf der Linie
; [out] RETURN : #True, wenn der P_out-Pointer nicht Null
Procedure ClosestPointOnLine_2D_Koord(LX1.f, LY1.f, LX2.f, LY2.f, PX.f, PY.f, *P_out.Vector2D)
Protected a.Vector2D, b.Vector2D, P.Vector2D
a\x = LX1
a\y = LY1
b\x = LX2 - LX1
b\y = LY2 - LY1
P\x = PX
P\y = PY
ProcedureReturn ClosestPointOnLine_2D_Vector(@a, @b, @P, *P_out)
EndProcedure
;}
;{- 2D CircleHitsCircle (noch ohne Schnittpunkt)
; [in] M1 : Mittelpunkt des 1. Kreises
; [in] R1 : Radius des 1. Kreises
; [in] M2 : Mittelpunkt des 2. Kreises
; [in] R2 : Radius des 2. Kreises
; [out] RETURN : #True bei Schnitt
Procedure.l CircleHitsCircle_2D_Point(*M1.Vector2D, R1.f, *M2.Vector2D, R2.f)
Protected Radd.f, Mdiffx.f, Mdiffy.f, Mdiffqu.f
; Wir addieren beide Radien
Radd.f = R1 + R2
; Wir berechnen den Abstand zwischen den Mittelpunkten im Quadrat
Mdiffx = *M1\x - *M2\x
Mdiffy = *M1\y - *M2\y
Mdiffqu = Mdiffx * Mdiffx + Mdiffy * Mdiffy
; Wenn die Abstand der Mittelpunkte größer ist als die Radien zusammen, dann gibt es keine Kollision
If Mdiffqu > Radd * Radd
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
; [in] M1x : x-Koordinate des Mittelpunktes des 1. Kreises
; [in] M1y : y-Koordinate des Mittelpunktes des 1. Kreises
; [in] R1 : Radius des 1. Kreises
; [in] M2x : x-Koordinate des Mittelpunktes des 2. Kreises
; [in] M2y : y-Koordinate des Mittelpunktes des 2. Kreises
; [in] R2 : Radius des 2. Kreises
; [out] RETURN : #True bei Schnitt
Procedure.l CircleHitsCircle_2D_Koord(M1x.f, M1y.f, R1.f, M2x.f, M2y.f, R2.f)
Protected M1.Vector2D, M2.Vector2D
M1\x = M1x
M1\y = M1y
M2\x = M2x
M2\y = M2y
ProcedureReturn CircleHitsCircle_2D_Point(@M1, R1, @M2, R2)
EndProcedure
;}
;{- 2D LineHitsCircle
; [in] LineStart : Startpunkt der Linie
; [in] LineEnd : Endpunkt der Linie
; [in] M : Mittelpunkt des Kreises
; [in] Radius : Radius des Kreises
; [out] pOut : nächster Schnittpunkt vom Startpunkt der Linie
; [out] RETURN : #True bei Schnitt
Procedure.l LineHitsCircle_2D_Point(*LineStart.Vector2D, *LineEnd.Vector2D, *M.Vector2D, Radius.f, *pOut.Vector2D)
Protected RadiusSq.f, PMinusM.Vector2D, LineDir.Vector2D, UDotPMinusM.f
Protected LineDirSq.f, d.f, s.f
; r² vorberechnen
RadiusSq = Radius * Radius
; (p - m) vorberechnen
PMinusM\x = *LineStart\x - *M\x
PMinusM\y = *LineStart\y - *M\y
; Wenn der Startpunkt der Linie schon im Kreis liegt,
; dann brechen wir sofort ab.
If PMinusM\x * PMinusM\x + PMinusM\y * PMinusM\y <= RadiusSq
; als Schnittpunkt nehmen wir einfach
; den Startpunkt der Linie
If *pOut
*pOut\x = *LineStart\x
*pOut\y = *LineStart\y
EndIf
ProcedureReturn #True
EndIf
; Richtungsvektor der Linie berechnen (u)
LineDir\x = *LineEnd\x - *LineStart\x
LineDir\y = *LineEnd\y - *LineStart\y
; u * (p - m) vorberechnen
UDotPMinusM = LineDir\x * PMinusM\x + LineDir\y * PMinusM\y
; u² vorberechnen
LineDirSq = LineDir\x * LineDir\x + LineDir\y * LineDir\y
; Die Diskriminante berechnen:
; (u * (p - m))²
; -(u² * ((p - m)² - r²))
d = UDotPMinusM * UDotPMinusM
d = d - LineDirSq * (PMinusM\x * PMinusM\x + PMinusM\y * PMinusM\y - RadiusSq)
; ist die Diskriminante negativ, null oder positiv?
If d < 0.0 : ProcedureReturn #False
ElseIf d < 0.0001
; Die Diskriminante ist (ungefähr) null.
; DIe gesamte Wurzel entfällt und die Lösung ist:
; (-u * (p - m)) / u²
; wir müssen nur noch prüfen, ob der Wert
; im korrekten Bereich [0; 1] liegt.
s = -UDotPMinusM / LineDirSq
If s < 0 Or s > 1
ProcedureReturn #False
Else
; Berührpunkt!
If *pOut
*pOut\x = *LineStart\x + s * LineDir\x
*pOut\y = *LineStart\y + s * LineDir\y
ProcedureReturn #True
EndIf
EndIf
Else
; Die Gerade schneidet den Kreis zweimal.
; Uns interessiert nur die kleinere Lösung s,
; denn das ist die Stelle, wo die Linie den Kreis
; "zum ersten Mal" schneidet.
; Diese Lösung berechnen wir nun.
s = (-UDotPMinusM - Sqr(d)) / LineDirSq
If s < 0 Or s > 1
ProcedureReturn #False
Else
If *pOut
*pOut\x = *LineStart\x + s * LineDir\x
*pOut\y = *LineStart\y + s * LineDir\y
ProcedureReturn #True
EndIf
EndIf
EndIf
EndProcedure
; [in] LineStartx : x-Koordinate des Startpunktes der Linie
; [in] LineStarty : y-Koordinate des Startpunktes der Linie
; [in] LineEndx : x-Koordinate des Endpunktes der Linie
; [in] LineEndy : y-Koordinate des Endpunktes der Linie
; [in] Mx : x-Koordinate des Mittelpunktes des Kreises
; [in] My : y-Koordinate des Mittelpunktes des Kreises
; [in] Radius : Radius des Kreises
; [out] pOut : nächster Schnittpunkt vom Startpunkt der Linie
; [out] RETURN : #True bei Schnitt
Procedure.l LineHitsCircle_2D_Koord(LineStartx.f, LineStarty.f, LineEndx.f, LineEndy.f, Mx.f, My.f, Radius.f, *pOut.Vector2D)
Protected LineStart.Vector2D, LineEnd.Vector2D, M.Vector2D
LineStart\x = LineStartx
LineStart\y = LineStarty
LineEnd\x = LineEndx
LineEnd\y = LineEndy
M\x = Mx
M\y = My
ProcedureReturn LineHitsCircle_2D_Point(@LineStart, @LineEnd, @M, Radius, *pOut)
EndProcedure
;}
;{- 3D Ray, Lines and Spheres
; [in] Start : Startpunkt des Strahls
; [in] Direction : Richtungsvektor des Strahls
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] pOut : nächster Schnittpunkt vom Startpunkt aus
; [out] RETURN : #True bei Schnitt
Procedure RayHitsSphere_3D_Vector(*Start.Vector3D, *Direction.Vector3D, *M.Vector3D, Radius.f, *pOut.Vector3D)
Protected AMinusB.Vector3D, AMinusBDotU.f, USq.f, c.f, Det.f, d.f, AMinusBSq.f, P.f
USq = *Direction\x * *Direction\x + *Direction\y * *Direction\y + *Direction\z * *Direction\z
AMinusB\x = *M\x - *Start\x
AMinusB\y = *M\y - *Start\y
AMinusB\z = *M\z - *Start\z
AMinusBDotU = AMinusB\x * *Direction\x + AMinusB\y * *Direction\y + AMinusB\z * *Direction\z
c = AMinusBDotU / USq
AMinusBSq = AMinusB\x * AMinusB\x + AMinusB\y * AMinusB\y + AMinusB\z * AMinusB\z
d = (Radius * Radius - AMinusBSq) / USq
Det = c * c + d
If Det < 0.0
ProcedureReturn #False
ElseIf Det < 0.0001
P = c
Else
P = c - Sqr(Det)
EndIf
If P < 0.0
ProcedureReturn #False
EndIf
If *pOut
*pOut\x = *Start\x + P * *Direction\x
*pOut\y = *Start\y + P * *Direction\y
*pOut\z = *Start\z + P * *Direction\z
EndIf
ProcedureReturn #True
EndProcedure
;Berechnung des nächsten Schnittpunktes eines Strahls mit einer Kugel und dessen Reflektion von dieser Stelle
; [in] a : Startpunkt des Strahls
; [in] u : Richtungs- und Längenvektor des Strahls
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] a_out : Schnittpunkt des Strahls mit der Kugel und Aufpunkt des Strahls oder unverändert, falls kein Schnitt
; [out] u_out : Neuer Richtungsvektor des Strahls
; [out] RETURN : #True bei Schnitt
Procedure RayHitsSphereMirrored_3D_Vector(*a.Vector3D, *u.Vector3D, *M.Vector3D, Radius.f, *a_out.Vector3D, *u_out.Vector3D)
Protected s.Vector3D, n.Vector3D, NDotU.f, s2.Vector3D, numerator.f, lambda.f, NSq.f, a_mirror.Vector3D
If RayHitsSphere_3D_Vector(*a, *u, *M, Radius, @s)
;Normale ausrechnen
n\x = *M\x - s\x
n\y = *M\y - s\y
n\z = *M\z - s\z
NDotU = n\x * *u\x + n\y * *u\y + n\z * *u\z
If NDotU <> 0.0
numerator = n\x * (s\x - *a\x) + n\y * (s\y - *a\y) + n\z * (s\z - *a\z)
lambda = numerator / NDotU
If lambda > 0.0
s2\x = *a\x + lambda * *u\x
s2\y = *a\y + lambda * *u\y
s2\z = *a\z + lambda * *u\z
NSq = n\x * n\x + n\y * n\y + n\z * n\z
lambda = 2 * numerator / NSq
a_mirror\x = *a\x + lambda * n\x
a_mirror\y = *a\y + lambda * n\y
a_mirror\z = *a\z + lambda * n\z
If *u_out
*u_out\x = s2\x - a_mirror\x
*u_out\y = s2\y - a_mirror\y
*u_out\z = s2\z - a_mirror\z
EndIf
If *a_out
*a_out\x = s2\x
*a_out\y = s2\y
*a_out\z = s2\z
EndIf
ProcedureReturn #True
EndIf
EndIf
EndIf
If *u_out
*u_out\x = *u\x
*u_out\y = *u\y
*u_out\z = *u\z
EndIf
If *a_out
*a_out\x = *a\x
*a_out\y = *a\y
*a_out\z = *a\z
EndIf
ProcedureReturn #False
EndProcedure
;Berechnung des nächsten Schnittpunktes einer Linie mit einer Kugel
; [in] Start : Startpunkt der Linie
; [in] Direction : Richtungs- und Längenvektor der Linie
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] pOut : nächster Schnittpunkt vom Startpunkt aus
; [out] RETURN : #True bei Schnitt
Procedure LineHitsSphere_3D_Vector(*Start.Vector3D, *Direction.Vector3D, *M.Vector3D, Radius.f, *pOut.Vector3D)
Protected AMinusB.Vector3D, AMinusBDotU.f, USq.f, c.f, Det.f, d.f, AMinusBSq.f, P.f
USq = *Direction\x * *Direction\x + *Direction\y * *Direction\y + *Direction\z * *Direction\z
AMinusB\x = *M\x - *Start\x
AMinusB\y = *M\y - *Start\y
AMinusB\z = *M\z - *Start\z
AMinusBDotU = AMinusB\x * *Direction\x + AMinusB\y * *Direction\y + AMinusB\z * *Direction\z
c = AMinusBDotU / USq
AMinusBSq = AMinusB\x * AMinusB\x + AMinusB\y * AMinusB\y + AMinusB\z * AMinusB\z
d = (Radius * Radius - AMinusBSq) / USq
Det = c * c + d
If Det < 0.0
If *pOut
*pOut\x = *Start\x + *Direction\x
*pOut\y = *Start\y + *Direction\y
*pOut\z = *Start\z + *Direction\z
EndIf
ProcedureReturn #False
ElseIf Det < 0.0001
P = c
Else
P = c - Sqr(Det)
If P < 0.0 Or P > 1.0
If *pOut
*pOut\x = *Start\x + *Direction\x
*pOut\y = *Start\y + *Direction\y
*pOut\z = *Start\z + *Direction\z
EndIf
ProcedureReturn #False
EndIf
EndIf
If *pOut
*pOut\x = *Start\x + P * *Direction\x
*pOut\y = *Start\y + P * *Direction\y
*pOut\z = *Start\z + P * *Direction\z
EndIf
ProcedureReturn #True
EndProcedure
;Berechnung des nächsten Schnittpunktes einer Linie mit einer Kugel
; [in] Start : Startpunkt der Linie
; [in] Direction : Ednpunkt der Linie
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] pOut : nächster Schnittpunkt vom Startpunkt aus
; [out] RETURN : #True bei Schnitt
Procedure LineHitsSphere_3D_Point(*a1.Vector3D, *a2.Vector3D, *M.Vector3D, Radius.f, *pOut.Vector3D)
Protected u.Vector3D
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
ProcedureReturn LineHitsSphere_3D_Vector(*a1, @u, *M, Radius, *pOut)
EndProcedure
;Berechnung des nächsten Schnittpunktes einer Linie mit einer Kugel und deren Reflektion von dieser Stelle
; [in] a : Startpunkt der Linie
; [in] u : Richtungs- und Längenvektor der Linie
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] a_out : Schnittpunkt der Linie mit der Kugel und Aufpunkt der Linie oder unverändert, falls kein Schnitt
; [out] u_out : Neuer Richtungs- und Längenvektor der Linie
; [out] RETURN : #True bei Schnitt
Procedure LineHitsSphereMirrored_3D_Vector(*a.Vector3D, *u.Vector3D, *M.Vector3D, Radius.f, *a_out.Vector3D, *u_out.Vector3D)
Protected s.Vector3D, n.Vector3D, NDotU.f, s2.Vector3D, numerator.f, lambda.f, NSq.f, a_mirror.Vector3D, sigma.f
If LineHitsSphere_3D_Vector(*a, *u, *M, Radius, @s)
;Normale ausrechnen
n\x = *M\x - s\x
n\y = *M\y - s\y
n\z = *M\z - s\z
NDotU = n\x * *u\x + n\y * *u\y + n\z * *u\z
If NDotU <> 0.0
numerator = n\x * (s\x - *a\x) + n\y * (s\y - *a\y) + n\z * (s\z - *a\z)
lambda = numerator / NDotU
If lambda > 0.0 And lambda <= 1.0
s2\x = *a\x + lambda * *u\x
s2\y = *a\y + lambda * *u\y
s2\z = *a\z + lambda * *u\z
NSq = n\x * n\x + n\y * n\y + n\z * n\z
sigma = 2 * numerator / NSq
a_mirror\x = *a\x + sigma * n\x
a_mirror\y = *a\y + sigma * n\y
a_mirror\z = *a\z + sigma * n\z
lambda = 1 / lambda - 1
If *u_out
*u_out\x = lambda * (s2\x - a_mirror\x)
*u_out\y = lambda * (s2\y - a_mirror\y)
*u_out\z = lambda * (s2\z - a_mirror\z)
EndIf
If *a_out
*a_out\x = s\x
*a_out\y = s\y
*a_out\z = s\z
EndIf
ProcedureReturn #True
EndIf
EndIf
EndIf
If *u_out
*u_out\x = *u\x
*u_out\y = *u\y
*u_out\z = *u\z
EndIf
If *a_out
*a_out\x = *a\x
*a_out\y = *a\y
*a_out\z = *a\z
EndIf
ProcedureReturn #False
EndProcedure
;Berechnung des nächsten Schnittpunktes einer Linie mit einer Kugel und deren Reflektion von dieser Stelle
; [in] a : Startpunkt der Linie
; [in] u : Endpunkt der Linie
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] a_out : Schnittpunkt der Linie mit der Kugel und Aufpunkt der Linie oder unverändert, falls kein Schnitt
; [out] u_out : Neuer Richtungs- und Längenvektor der Linie
; [out] RETURN : #True bei Schnitt
Procedure LineHitsSphereMirrored_3D_Point(*a1.Vector3D, *a2.Vector3D, *M.Vector3D, Radius.f, *a_out.Vector3D, *u_out.Vector3D)
Protected u.Vector3D
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
ProcedureReturn LineHitsSphereMirrored_3D_Vector(*a1, @u, *M, Radius, *a_out, *u_out)
EndProcedure
;Berechnung des nächsten Schnittpunktes einer Linie mit einer Kugel und deren Reflektion von dieser Stelle
; [in] a : Startpunkt der Linie
; [in] u : Endpunkt der Linie
; [in] M : Mittelpunkt der Kugel
; [in] Radius : Radius der Kugel
; [out] a1_out : Schnittpunkt der Linie mit der Kugel und Aufpunkt der Linie oder unverändert, falls kein Schnitt
; [out] a2_out : Endpunkt der Linie nach Schnitt
; [out] RETURN : #True bei Schnitt
Procedure LineHitsSphereMirrored_3D_PointEx(*a1.Vector3D, *a2.Vector3D, *M.Vector3D, Radius.f, *a1_out.Vector3D, *a2_out.Vector3D)
Protected u.Vector3D, Result.l
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
Result = LineHitsSphereMirrored_3D_Vector(*a1, @u, *M, Radius, *a1_out, *a2_out)
*a2_out\x + *a1_out\x
*a2_out\y + *a1_out\y
*a2_out\z + *a1_out\z
ProcedureReturn Result
EndProcedure
;}
;{- 3D GetNormal
;Normale: Ein Normalenvektor steht immer senkrecht zu zwei anderen Vektoren
;
; -> -> ->
;Berechnung: n = u x v (Vektorprodukt)
;
; -> -> -> ->
;Später gilt: u * n = 0 und v * n = 0
;Gibt die Normale zu zwei Vektoren aus
; [in] a : 1. Richtungsvektor
; [in] b : 2. Richtungsvektor
; [out] n : Normale der beiden Richtunsgvektoren
; [out] RETURN : Immer #True
Procedure GetNormal_3D(*a.Vector3D, *b.Vector3D, *n.Vector3D)
*n\x = *a\y * *b\z - *a\z * *b\y
*n\y = *a\z * *b\x - *a\x * *b\z
*n\z = *a\x * *b\y - *a\y * *b\x
ProcedureReturn #True
EndProcedure
;}
;{- 3D Planes
; -> -> -> ->
; PRG: x = a + lambda * u + mü * v
;
; -> -> -> -> -> -> ->
; PNG: n * (x - a ) = 0 <=> (u x v ) * (x - a ) = 0
;
; -> -> -> ->
; ANG: n * x - c = 0 mit c = n * a
;'Punkt-Richtungs-Gleichung' zur 'Punkt-Normalen-Gleichung'
; [in] u : 1. Richtungsvektor der Ebene
; [in] v : 2. Richtungsvektor der Ebene
; [out] n : Normalenvektor der Ebene
; [out] RETURN : #True, wenn *u und *v nicht parallel
Procedure PRGToPNG_3D(*u.Vector3D, *v.Vector3D, *n.Vector3D) ; --> n*(x-a)=0
*n\x = *u\y * *v\z - *u\z * *v\y
*n\y = *u\z * *v\x - *u\x * *v\z
*n\z = *u\x * *v\y - *u\y * *v\x
If *n\x = 0 And *n\y = 0 And *n\z = 0 : ProcedureReturn #False : EndIf
ProcedureReturn #True
EndProcedure
;'Punkt-Richtungs-Gleichung' zur 'Allgemeinen Normalengleichung'
; [in] a : Aufpunkt der Ebene
; [in] u : 1. Richtungsvektor der Ebene
; [in] v : 2. Richtungsvektor der Ebene
; [out] n : Normalenvektor der Ebene
; [out] c : Parameter der Ebene in der ANG
; [out] RETURN : #True, wenn *u und *v nicht parallel
Procedure PRGToANG_3D(*a.Vector3D, *u.Vector3D, *v.Vector3D, *n.Vector3D, *c.FLOAT) ; --> n*x-c=0
*n\x = *u\y * *v\z - *u\z * *v\y
*n\y = *u\z * *v\x - *u\x * *v\z
*n\z = *u\x * *v\y - *u\y * *v\x
If *n\x = 0 And *n\y = 0 And *n\z = 0 : ProcedureReturn #False : EndIf
*c\f = *n\x * *a\x + *n\y * *a\y + *n\z * *a\z
ProcedureReturn #True
EndProcedure
;'Punkt-Normalen-Gleichung' zur 'Allgemeinen Normalengleichung'
; [in] a : Aufpunkt der Ebene
; [in] n : Normale der Ebene
; [out] c : Parameter der Ebene in der ANG
; [out] RETURN : Immer #True
Procedure PNGToANG_3D(*a.Vector3D, *n.Vector3D, *c.FLOAT) ; n*(x-a)=0 --> n*x-c=0
*c\f = *n\x * *a\x + *n\y * *a\y + *n\z * *a\z
ProcedureReturn #True
EndProcedure
;Errechnung der PRG aus drei Punkten
; [in] a : 1. Punkt und Aufpunkt der Ebene
; [in] b : 2. Punkt
; [in] c : 3. Punkt
; [out] u : 1. Richtungsvektor der Ebene
; [out] v : 2. Richtungsvektor der Ebene
; [out] RETURN : #True, wenn Punkte nicht auf eine Linie liegen
Procedure PointsToPRG_3D(*a.Vector3D, *b.Vector3D, *c.Vector3D, *u.Vector3D, *v.Vector3D) ; ABC --> x=a+.u+.v
Protected n.Vector3D
*u\x = *b\x - *a\x
*u\y = *b\y - *a\y
*u\z = *b\z - *a\z
*v\x = *c\x - *a\x
*v\y = *c\y - *a\y
*v\z = *c\z - *a\z
n\x = *u\y * *v\z - *u\z * *v\y
n\y = *u\z * *v\x - *u\x * *v\z
n\z = *u\x * *v\y - *u\y * *v\x
If n\x = 0 And n\y = 0 And n\z = 0 : ProcedureReturn #False : EndIf
ProcedureReturn #True
EndProcedure
;Errechnung der PNG aus dreu Punkten
; [in] p1 : 1. Punkt und Aufpunkt der Ebene
; [in] p2 : 2. Punkt
; [in] p3 : 3. Punkt
; [out] n : Normalenvektor
; [out] RETURN : #True, wenn Punkte nicht auf einer Linie liegen
Procedure PointsToPNG_3D(*p1.Vector3D, *p2.Vector3D, *p3.Vector3D, *n.Vector3D) ; ABC --> n*(x-a)=0
Protected u.Vector3D, v.Vector3D
u\x = *p2\x - *p1\x
u\y = *p2\y - *p1\y
u\z = *p2\z - *p1\z
v\x = *p3\x - *p1\x
v\y = *p3\y - *p1\y
v\z = *p3\z - *p1\z
*n\x = u\y * v\z - u\z * v\y
*n\y = u\z * v\x - u\x * v\z
*n\z = u\x * v\y - u\y * v\x
If *n\x = 0 And *n\y = 0 And *n\z = 0 : ProcedureReturn #False : EndIf
ProcedureReturn #True
EndProcedure
;Errechnung der ANG aus dreu Punkten
; [in] p1 : 1. Punkt und Aufpunkt der Ebene
; [in] p2 : 2. Punkt
; [in] p3 : 3. Punkt
; [out] n : Normalenvektor
; [out] c : Parameter der Ebene in der ANG
; [out] RETURN : #True, wenn Punkte nicht auf einer Linie liegen
Procedure PointsToANG_3D(*p1.Vector3D, *p2.Vector3D, *p3.Vector3D, *n.Vector3D, *c.FLOAT) ; ABC --> n*x-c=0
Protected u.Vector3D, v.Vector3D
u\x = *p2\x - *p1\x
u\y = *p2\y - *p1\y
u\z = *p2\z - *p1\z
v\x = *p3\x - *p1\x
v\y = *p3\y - *p1\y
v\z = *p3\z - *p1\z
*n\x = u\y * v\z - u\z * v\y
*n\y = u\z * v\x - u\x * v\z
*n\z = u\x * v\y - u\y * v\x
If *n\x = 0 And *n\y = 0 And *n\z = 0 : ProcedureReturn #False : EndIf
*c\f = *n\x * *p1\x + *n\y * *p1\y + *n\z * *p1\z
ProcedureReturn #True
EndProcedure
;Abstand der Ebene zum Ursprung
; [in] a : Aufpunkt der Ebene
; [in] n : Normale der Ebene
; [out] RETURN : Abstand
Procedure.f PlaneDistanceToOrigin_3D(*a.Vector3D, *n.Vector3D)
Protected d.f, l.f
l = Sqr(*n\x * *n\x + *n\y * *n\y + *n\z * *n\z)
d = (*a\x * *n\x + *a\y * *n\y + *a\z * *n\z) / l
ProcedureReturn d
EndProcedure
;Sind zwei Ebenen parallel?
; [in] n1 : Normalenvektor der 1. Ebene
; [in] n2 : Normalenvektor der 2. Ebene
; [out] RETURN : #True, wenn Ebenen parallel
Procedure PlaneToPlaneParallel_3D(*n1.Vector3D, *n2.Vector3D)
Protected quotient.f
quotient = *n1\x / *n2\x
If quotient = *n1\y / *n2\y And quotient = *n1\z / *n2\z
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;Sind zwei Ebenen gleich?
; [in] a1 : Aufpunkt der 1. Ebene
; [in] n1 : Normalenvektor der 1. Ebene
; [in] a2 : Aufpunkt der 2. Ebene
; [in] n2 : Normalenvektor der 2. Ebene
; [out] RETURN : #True, wenn Ebenen gleich
Procedure PlaneToPlaneSame_3D(*a1.Vector3D, *n1.Vector3D, *a2.Vector3D, *n2.Vector3D)
Protected XMinusA.Vector3D, quotient.f
XMinusA\x = *a2\x - *a1\x
XMinusA\y = *a2\y - *a1\y
XMinusA\z = *a2\z - *a1\z
If XMinusA\x * *n1\x + XMinusA\y * *n1\y + XMinusA\z * *n1\z = 0
quotient = *n1\x / *n2\x
If quotient = *n1\y / *n2\y And quotient = *n1\z / *n2\z
ProcedureReturn #True
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;}
;{- 3D Planes, Lines and Rays
;Berechnung, ob Linie parallel zu einer Ebene ist
; [in] u : Richtungsvektor der Gerade
; [in] n : Normalenvektor der Ebene
; [out] RETURN : #True, wenn Ebene und Linie parallel
; #False, wenn Linie Ebene schneidet
Procedure LineToPlaneParallel_3D_Vektor(*u.Vector3D, *n.Vector3D)
If *u\x * *n\x + *u\y * *n\y + *u\z * *n\z = 0
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
;Berechnung, ob Linie parallel zu einer Ebene ist
; [in] a1 : Startpunkt der Linie
; [in] a2 : Endpunkt der Linie
; [in] n : Normalenvektor der Ebene
; [out] RETURN : #True, wenn Ebene und Linie parallel
; #False, wenn Linie Ebene schneidet
Procedure LineToPlaneParallel_3D_Point(*a1.Vector3D, *a2.Vector3D, *n.Vector3D)
Protected u.Vector3D
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
ProcedureReturn LineToPlaneParallel_3D_Vektor(@u, *n)
EndProcedure
;Berechnung, ob Linie in einer Ebene liegt
; [in] a : Aufpunkt der Linie
; [in] u : Richtungsvektor der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] RETURN : #True, wenn Linie in Ebene liegt
Procedure LineInPlane_3D_Vector(*a.Vector3D, *u.Vector3D, *b.Vector3D, *n.Vector3D)
Protected diff.Vector3D
If *u\x * *n\x + *u\y * *n\y + *u\z * *n\z = 0
diff\x = *a\x - *b\x
diff\y = *a\y - *b\y
diff\z = *a\z - *b\z
If diff\x * *n\x + diff\y * *n\y + diff\z * *n\z = 0
ProcedureReturn #True
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;Berechnung, ob Linie in einer Ebene liegt
; [in] a1 : Startpunkt der Linie
; [in] a2 : Endpunkt der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] RETURN : #True, wenn Linie in Ebene liegt
Procedure LineInPlane_3D_Point(*a1.Vector3D, *a2.Vector3D, *b.Vector3D, *n.Vector3D)
Protected u.Vector3D
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
ProcedureReturn LineInPlane_3D_Vector(*a1, @u, *b, *n)
EndProcedure
;Berechnung des Schnittpunktes einer Linie mit einer Ebene
; [in] a : Aufpunkt der Linie
; [in] u : Richtungs- und Längenvektor der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] pHit : Schnittpunkt
; [out] RETURN : #True, wenn Linie Ebene schneidet
Procedure LineHitsPlane_3D_Vector(*a.Vector3D, *u.Vector3D, *b.Vector3D, *n.Vector3D, *pHit.Vector3D)
Protected NDotU.f, numerator.f, lambda.f
NDotU = *n\x * *u\x + *n\y * *u\y + *n\z * *u\z
If NDotU <> 0.0
numerator = *n\x * (*b\x - *a\x) + *n\y * (*b\y - *a\y) + *n\z * (*b\z - *a\z)
lambda = numerator / NDotU
If lambda => 0.0 And lambda <= 1.0
If *pHit
*pHit\x = *a\x + lambda * *u\x
*pHit\y = *a\y + lambda * *u\y
*pHit\z = *a\z + lambda * *u\z
EndIf
ProcedureReturn #True
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;Berechnung des Schnittpunktes eines Strahls mit einer Ebene
; [in] a : Aufpunkt des Strahls
; [in] u : Richtungsvektor des Strahls
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] pHit : Schnittpunkt
; [out] RETURN : #True, wenn Strahl Ebene schneidet
Procedure RayHitsPlane_3D_Vector(*a.Vector3D, *u.Vector3D, *b.Vector3D, *n.Vector3D, *pHit.Vector3D)
Protected NDotU.f, numerator.f, lambda.f
NDotU = *n\x * *u\x + *n\y * *u\y + *n\z * *u\z
If NDotU <> 0.0
numerator = *n\x * (*b\x - *a\x) + *n\y * (*b\y - *a\y) + *n\z * (*b\z - *a\z)
lambda = numerator / NDotU
If lambda => 0.0
If *pHit
*pHit\x = *a\x + lambda * *u\x
*pHit\y = *a\y + lambda * *u\y
*pHit\z = *a\z + lambda * *u\z
EndIf
ProcedureReturn #True
EndIf
EndIf
ProcedureReturn #False
EndProcedure
;Berechnung des Schnittpunktes einer Linie mit einer Ebene
; [in] a1 : Startpunkt der Linie
; [in] a2 : Endpunkt der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] pHit : Schnittpunkt
; [out] RETURN : #True, wenn Gerade Ebene schneidet
Procedure LineHitsPlane_3D_PointPNG(*a1.Vector3D, *a2.Vector3D, *b.Vector3D, *n.Vector3D, *pHit.Vector3D)
Protected u.Vector3D
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
ProcedureReturn LineHitsPlane_3D_Vector(*a1, @u, *b, *n, *pHit)
EndProcedure
;Berechnung des Schnittpunktes einer Linie mit einer Ebene
; [in] p1 : 1. Punkt für Ebene
; [in] p2 : 2. Punkt für Ebene
; [in] p3 : 3. Punkt für Ebene
; [in] a1 : Startpunkt der Linie
; [in] a2 : Endpunkt der Linie
; [out] pHit : Schnittpunkt
; [out] RETURN : #True, wenn Gerade Dreieck schneidet
Procedure LineHitsPlane_3D_Point(*p1.Vector3D, *p2.Vector3D, *p3.Vector3D, *a1.Vector3D, *a2.Vector3D, *pHit.Vector3D)
Protected n.Vector3D, w.Vector3D, u.Vector3D, v.Vector3D
w\x = *a2\x - *a1\x
w\y = *a2\y - *a1\y
w\z = *a2\z - *a1\z
u\x = *p2\x - *p1\x
u\y = *p2\y - *p1\y
u\z = *p2\z - *p1\z
v\x = *p3\x - *p1\x
v\y = *p3\y - *p1\y
v\z = *p3\z - *p1\z
n\x = u\y * v\z - u\z * v\y
n\y = u\z * v\x - u\x * v\z
n\z = u\x * v\y - u\y * v\x
ProcedureReturn LineHitsPlane_3D_Vector(*a1, @w, *p1, @n, *pHit)
EndProcedure
;Strahl trifft auf eine Ebene und wird von ihr gespiegelt
; [in] a : Anfangspunkt des Strahls
; [in] u : Richtunsgvektor des Strahls
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] a_out : Schnittpunkt des Strahls mit der Ebene und Aufpunkt des Strahls
; [out] u_out : Neuer Richtungsvektor des Strahls
; [out] RETURN : #True, wenn Schnitt
Procedure RayHitsPlaneMirrored_3D_Vector(*a.Vector3D, *u.Vector3D, *b.Vector3D, *n.Vector3D, *a_out.Vector3D, *u_out.Vector3D)
Protected NDotU.f, numerator.f, lambda.f, s.Vector3D, NSq.f, a_mirror.Vector3D
NDotU = *n\x * *u\x + *n\y * *u\y + *n\z * *u\z
If NDotU <> 0.0
numerator = *n\x * (*b\x - *a\x) + *n\y * (*b\y - *a\y) + *n\z * (*b\z - *a\z)
lambda = numerator / NDotU
If lambda > 0.0
s\x = *a\x + lambda * *u\x
s\y = *a\y + lambda * *u\y
s\z = *a\z + lambda * *u\z
NSq = *n\x * *n\x + *n\y * *n\y + *n\z * *n\z
lambda = 2 * numerator / NSq
a_mirror\x = *a\x + lambda * *n\x
a_mirror\y = *a\y + lambda * *n\y
a_mirror\z = *a\z + lambda * *n\z
If *u_out
*u_out\x = s\x - a_mirror\x
*u_out\y = s\y - a_mirror\y
*u_out\z = s\z - a_mirror\z
EndIf
If *a_out
*a_out\x = s\x
*a_out\y = s\y
*a_out\z = s\z
EndIf
ProcedureReturn #True
EndIf
EndIf
If *u_out
*u_out\x = *u\x
*u_out\y = *u\y
*u_out\z = *u\z
EndIf
If *a_out
*a_out\x = *a\x
*a_out\y = *a\y
*a_out\z = *a\z
EndIf
ProcedureReturn #False
EndProcedure
;Linie trifft auf eine Ebene und wird von ihr gespiegelt
; [in] a : Aufpunkt der Linie
; [in] u : Richtunsgs- und Längenvektor der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] a_out : Schnittpunkt der Linie mit der Ebene und Aufpunkt der Linie oder unverändert, falls kein Schnitt
; [out] u_out : Neuer Richtungs- und Längenvektor der Linie
; [out] RETURN : #True, wenn Schnitt
Procedure LineHitsPlaneMirrored_3D_Vector(*a.Vector3D, *u.Vector3D, *b.Vector3D, *n.Vector3D, *a_out.Vector3D, *u_out.Vector3D)
Protected NDotU.f, numerator.f, lambda.f, s.Vector3D, NSq.f, a_mirror.Vector3D, sigma.f
NDotU = *n\x * *u\x + *n\y * *u\y + *n\z * *u\z
If NDotU <> 0.0
numerator = *n\x * (*b\x - *a\x) + *n\y * (*b\y - *a\y) + *n\z * (*b\z - *a\z)
lambda = numerator / NDotU
If lambda > 0.0 And lambda <= 1.0
s\x = *a\x + lambda * *u\x
s\y = *a\y + lambda * *u\y
s\z = *a\z + lambda * *u\z
NSq = *n\x * *n\x + *n\y * *n\y + *n\z * *n\z
sigma = 2.0 * numerator / NSq
a_mirror\x = *a\x + sigma * *n\x
a_mirror\y = *a\y + sigma * *n\y
a_mirror\z = *a\z + sigma * *n\z
lambda = 1 / lambda - 1
If *u_out
*u_out\x = lambda * (s\x - a_mirror\x)
*u_out\y = lambda * (s\y - a_mirror\y)
*u_out\z = lambda * (s\z - a_mirror\z)
EndIf
If *a_out
*a_out\x = s\x
*a_out\y = s\y
*a_out\z = s\z
EndIf
ProcedureReturn #True
Else
If *u_out
*u_out\x = *u\x
*u_out\y = *u\y
*u_out\z = *u\z
EndIf
If *pHit
*a_out\x = *a\x
*a_out\y = *a\y
*a_out\z = *a\z
EndIf
EndIf
Else
If *u_out
*u_out\x = *u\x
*u_out\y = *u\y
*u_out\z = *u\z
EndIf
If *a_out
*a_out\x = *a\x
*a_out\y = *a\y
*a_out\z = *a\z
EndIf
ProcedureReturn #False
EndIf
ProcedureReturn #False
EndProcedure
;Linie trifft auf eine Ebene und wird von ihr gespiegelt
; [in] a1 : Anfangspunkt der Linie
; [in] a2 : Endpunkt der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] a_out : Schnittpunkt der Linie mit der Ebene und Aufpunkt der Linie
; [out] u_out : Neuer Richtungs- und Längenvektor der Linie
; [out] RETURN : #True, wenn Schnitt
Procedure LineHitsPlaneMirrored_3D_Point(*a1.Vector3D, *a2.Vector3D, *b.Vector3D, *n.Vector3D, *a_out.Vector3D, *u_out.Vector3D)
Protected u.Vector3D
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
ProcedureReturn LineHitsPlaneMirrored_3D_Vector(*a1, @u, *b, *n, *a_out, *u_out)
EndProcedure
;Linie trifft auf eine Ebene und wird von ihr gespiegelt
; [in] a1 : Anfangspunkt der Linie
; [in] a2 : Endpunkt der Linie
; [in] b : Aufpunkt der Ebene
; [in] n : Normalenvektor der Ebene
; [out] a1_out : Schnittpunkt der Linie mit der Ebene und Aufpunkt der Linie
; [out] a2_out : Endpunkt der Linie nach Schnitt
; [out] RETURN : #True, wenn Schnitt
Procedure LineHitsPlaneMirrored_3D_PointEx(*a1.Vector3D, *a2.Vector3D, *b.Vector3D, *n.Vector3D, *a1_out.Vector3D, *a2_out.Vector3D)
Protected u.Vector3D, Result.l
u\x = *a2\x - *a1\x
u\y = *a2\y - *a1\y
u\z = *a2\z - *a1\z
Result = LineHitsPlaneMirrored_3D_Vector(*a1, @u, *b, *n, *a1_out, *a2_out)
*a2_out\x + *a1_out\x
*a2_out\y + *a1_out\y
*a2_out\z + *a1_out\z
ProcedureReturn #False
EndProcedure
;}
;{- 3D Triangles and Lines
; [in] p1 : 1. Punkt des Dreiecks
; [in] p2 : 2. Punkt des Dreiecks
; [in] p3 : 3. Punkt des Dreiecks
; [in] a : Aufpunkt der Linie
; [in] w : Richtungs- und Längenvektor der Linie
; [out] pHit : Schnittpunkt oder falls kein Schnitt Endpunkt der Linie
; [out] RETURN : #True, wenn Gerade Dreieck schneidet
Procedure LineHitsTriangle_3D_Vector(*p1.Vector3D, *p2.Vector3D, *p3.Vector3D, *a.Vector3D, *w.Vector3D, *pHit.Vector3D)
Protected sigma.f, lambda.f, mue.f, n.Vector3D, u.Vector3D, v.Vector3D, NDotU.f, a.f
u\x = *p2\x - *p1\x
u\y = *p2\y - *p1\y
u\z = *p2\z - *p1\z
v\x = *p3\x - *p1\x
v\y = *p3\y - *p1\y
v\z = *p3\z - *p1\z
n\x = u\y * v\z - u\z * v\y
n\y = u\z * v\x - u\x * v\z
n\z = u\x * v\y - u\y * v\x
NDotU = n\x * *w\x + n\y * *w\y + n\z * *w\z
If NDotU <> 0.0
numerator = n\x * (*p1\x - *a\x) + n\y * (*p1\y - *a\y) + n\z * (*p1\z - *a\z)
sigma = numerator / NDotU
If sigma => 0.0 And sigma <= 1.0
a = u\x * v\y - u\y * v\x
If a <> 0
lambda = (u\x * (*a\y - *p1\y) - u\y * (*a\x - *p1\x) + sigma * (*w\y * u\x - *w\x * u\y)) / a
Else
a = u\x * v\z - u\z * v\x
If a <> 0
lambda = (u\x * (*a\z - *p1\z) - u\z * (*a\x - *p1\x) + sigma * (*w\z * u\x - *w\x * u\z)) / a
Else
a = u\y * v\z - u\z * v\y
If a <> 0
lambda = (u\y * (*a\z - *p1\z) - u\z * (*a\y - *p1\y) + sigma * (*w\z * u\y - *w\y * u\z)) / a
EndIf
EndIf
EndIf
If lambda >= 0.0 And lambda <= 1.0
If u\x <> 0
mue = ((*a\x - *p1\x) - lambda * v\x + sigma * *w\x) / u\x
ElseIf u\y <> 0
mue = ((*a\y - *p1\y) - lambda * v\y + sigma * *w\y) / u\y
ElseIf u\z <> 0
mue = ((*a\z - *p1\z) - lambda * v\z + sigma * *w\z) / u\z
EndIf
If mue >= 0.0 And mue <= 1.0
If mue + lambda <= 1
If *pHit
*pHit\x = *a\x + sigma * *w\x
*pHit\y = *a\y + sigma * *w\y
*pHit\z = *a\z + sigma * *w\z
EndIf
ProcedureReturn #True
EndIf
EndIf
EndIf
EndIf
EndIf
*pHit\x = *a\x + *w\x
*pHit\y = *a\y + *w\y
*pHit\z = *a\z + *w\z
ProcedureReturn #False
EndProcedure
Procedure LineHitsTriangle_3D_Point(*p1.Vector3D, *p2.Vector3D, *p3.Vector3D, *a1.Vector3D, *a2.Vector3D, *pHit.Vector3D)
Protected w.Vector3D
w\x = *a2\x - *a1\x
w\y = *a2\y - *a1\y
w\z = *a2\z - *a1\z
ProcedureReturn LineHitsTriangle_3D_Vector(*p1, *p2, *p3, *a1, @w, *pHit)
EndProcedure
;}
Code: Alles auswählen
Structure Vector2D
x.f
y.f
EndStructure
Structure Line2D
x1.f
y1.f
x2.f
y2.f
EndStructure
Structure Vector3d
x.f
y.f
z.f
EndStructure
Structure Line3D
x1.f
y1.f
z1.f
x2.f
y2.f
z2.f
EndStructure