Strahl Dreieck Kollision

  • Hallo zusammen,

    ist irgendjemand so gut in Mathe das er mir helfen kann, die Kollision von einem Strahl mit einem Dreieck im 3D Raum zu berechnen bzw eine funktion zu schreiben. Die Eingangsparameter sind die 3 Koordinaten Punkte des Dreicks(A,B,C). Sowie ein Strahl bestehend aus einem Startpunkt (P) und einem Vektor(V)?

    Danke :)

  • Also Dreiecke im 3D-Raum gibt es nicht. Dreiecke sind 2D-Formen. Ansonsten würde ich sagen, Einfallswinkel ist gleich Ausfallswinkel.

  • Mit dem Dreieck kannst du eine Ebene definieren mit dem Startpunkt A und den Vektoren AB und AC.
    Der Strahl definiert eine Gerade mit dem Startpunkt Y und dem Bewegungsvektor YZ.

    Um den Durchstoßpunkt zu berechnen muss man beide gleichsetzen. Anschließend schauen ob der Punkt auch wirklich im Dreieck liegt.
    In autoit bekomme ich das so schnell nicht hin, aber vielleicht hilft dir ja ein Ansatz?

  • Scheiterts an der Mathe (kannst du doch viel besser als ich ... :whistling: ) oder an der Programmumsetzung?

    Zur Mathe:

    A (0|0|0) ; B (1|1|1) ; C(2|2|2) => Dreieck
    Bewegunsvektor AB = (1|1|1) minus (0|0|0) = (1|1|1) -> AC geht genauso
    => Ebenengleichung: (0|0|0) + r * (1|1|1) + s * (2|2|2)

    Y (5|5|5) Strahl- bzw. Geradenstartpunkt + Bewgungsvektor YZ (3|3|3)
    Geradengleichung: (5|5|5) + t * (3|3|3)

    Gleichsetzen:

    Code
    0 + r *1 + s*2 = 5 + t*3
    0 + r *1 + s*2 = 5 + t*3
    0 + r *1 + s*2 = 5 + t*3


    => auflösen nach t
    => in Geradengleichung einsetzen
    => ergibt den Durchstoßpunkt

    P.S. So ca. Matheabi ist schon 5 Jahre her 8o

  • Naja sagen wir mal so, ich kann das was ich kann sehr gut, aber der sprung von 2 zu 3d ist doch enorm. Ich schreibe gerade an einer kleinen biblihothek, vekotren sind schon enthalten, und matrixen und ebenen auch(zwar nur translationen und rotationen aber noch nicht mehr :S ). Deshalb wollte ich jetzt noch die kollisionen berechnen können. Aber das ist schonmal gut.

    Wäre super wenn du restlichen schritte auch noch "verbeispielen" könntest :)

    Mit der Geradengleichung meinst du: Kollisionspunkt(x,y,z) = StartpunktdesStrahl(_, _, _,) + VektordesStrahl(_, _, _)*t?

    Achja nochwas, wie berechen ich den ob die Position in dreieck ist?

    Einmal editiert, zuletzt von moritz1243 (20. April 2010 um 18:10)


  • Mit der Geradengleichung meinst du: Kollisionspunkt(x,y,z) = StartpunktdesStrahl(_, _, _,) + VektordesStrahl(_, _, _)*t?


    Genau und t bekommen wir aus den 3 Gleichungen mit den 3 unbekannten.
    Per Software wäre das imho über das Gauß' sche Eliminationsverfahren machbar. http://de.wikipedia.org/wiki/Gau%C3%9F…ationsverfahren


    Achja nochwas, wie berechen ich den ob die Position in dreieck ist?


    Bin ich auch noch am überlegen :wacko:

    edit \ ähm den Durchstoßpunkt muss man dann wohl mit den 3 Gerade (AB, AC und BC -> Punkte vom Dreeick) vergleichen?
    Muss ich mir aber erst nochmal genau überlegen :whistling:
    Wo steckt denn UEZ? :D

    Einmal editiert, zuletzt von nuts (20. April 2010 um 18:29)

  • stimmt ich habe mir jetzt diesen artikel zuende durchgelesen, da muss man noch viel umstellen etc. Hier steht was das schein einfacher zu sein:
    http://softsurfer.com/Archive/algori…orithm_0105.htm

    hab was gefunden:

    Spoiler anzeigen
    [autoit]

    bool TrimeshFace::intersectLocal( const ray& r, isect& i ) const
    {

    // retrieve the vertices
    const Vec3d& v0 = parent->vertices[ids[0]];
    const Vec3d& v1 = parent->vertices[ids[1]];
    const Vec3d& v2 = parent->vertices[ids[2]];

    Vec3d e1 = Vec3d(v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]);
    Vec3d e2 = Vec3d(v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]);


    Vec3d h = Vec3d(r.getDirection()[2] * e2[3] - r.getDirection()[3] * e2[2],
    r.getDirection()[3] * e2[1] - r.getDirection()[1] * e2[3],
    r.getDirection()[1] * e2[2] - r.getDirection()[2] * e2[1]);



    double a = (e1[0] * h[0]) + (e1[1] * h[1]) + (e1[2] * h[2]);


    if (a > -0.00001 && a < 0.00001)
    return false;

    double f = 1/a;

    Vec3d s = Vec3d(r.getPosition()[2] * v0[3] - r.getPosition()[3] * v0[2],
    r.getPosition()[3] * v0[1] - r.getPosition()[1] * v0[3],
    r.getPosition()[1] * v0[2] - r.getPosition()[2] * v0[1]);



    double u = f * ((s[0] * h[0]) + (s[1] * h[1]) + (s[2] * h[2]));



    if (u < 0.0 || u > 1.0) {
    return false;
    }

    Vec3d q = Vec3d(s[2] * e1[3] - s[3] * e1[2],
    s[3] * e1[1] - s[1] * e1[3],
    s[1] * e1[2] - s[2]* e1[1]);

    double v = f * ((r.getDirection()[0] * q[0]) +
    (r.getDirection()[1] * q[1]) +
    (r.getDirection()[2] * q[2]));

    if (v < 0.0 || u + v > 1.0)
    return false;

    // at this stage we can compute t to find out where
    // the intersection point is on the line
    double t = f * ((e2[0] * q[0]) + (e2[1] * q[1]) + (e2[2] * q[2]));


    if (t > 0.00001) // ray intersection
    {
    i.obj = this;
    i.t = t;
    i.N = Vec3d(e1[2] * e2[3] - e1[3] * e2[2],
    e1[3] * e2[1] - e1[1] * e2[3],
    e1[1] * e2[2] - e1[2]* e2[1]);;
    return true;
    }

    [/autoit]

    hier noch besser das letzt bei opimasation:
    http://www.devmaster.net/wiki/Ray-triangle_intersection

  • Schau mal hier rein: http://www.delphigl.com/forum/viewtopic.php?f=30&t=8346
    Mein vorgeschlagener Weg scheint zum Ziel zu führen. 8o

    Ob der Punkt im Dreieck liegt prüft man mit folgenden Bedingungen:

    Code
    0<= s <=1
    0<= t <=1
    0<= s+t <=1


    s und t sind dabei die Parameter vor den Bewegungsvektoren der Ebenengleichung.
    s und t wird durch einsetzen des Durchstoßpunktes und lösen des Gleichungssystem bestimmt und anschließend auf die Bedingungen geprüft.

    P.S. Auf Papier kann ich dir das gern mal vorrechnen und zuschicken, per Autoit fehlt mir Zeit und Können :(

    2 Mal editiert, zuletzt von nuts (21. April 2010 um 14:07)

  • Die ganze algebraische Lösung mit Variablen - kannst ja mal Werte einsetzen!

    Dreieck: (ABC)
    Startpunkt A = (A1 | A2 | A3)
    B = (B1 | B2 | B3)
    C = (C1 | C2 | C3)

    Bewegungsvektor AB = (AB1 | AB2 | AB3)
    AB1 = B1 - A1
    AB2 = B2 - A2
    AB3 = B3 - A3
    Bewegungsvektor AC = (AC1 | AC2 | AC3)
    AC1 = C1 - A1
    AC2 = C2 - A2
    AC3 = C3 - A3

    Gerade:
    Startpunkt X = (X1 | X2 | X3)
    Bewegungsvektor XY = (XY1 | XY2 | XY3)

    Ebenengleichung:
    A + r* AB + s* AC = (A1 | A2 | A3) + r * (AB1 | AB2 | AB3) + s *(AC1 | AC2 | AC3)

    Geradengleichung:
    X + t* XY = (X1 | X2 | X3) + t* (XY1 | XY2 | XY3)


    Gleichungssystem aufstellen und gleichsetzen:

    A1 + r* AB1 + s*AC1 = X1 + t* XY1
    A2 + r* AB2 + s*AC2 = X2 + t* XY2
    A3 + r* AB3 + s*AC3 = X3 + t* XY3

    Gleichungssystem lösen => t = …


    Einsetzen in die Geradengleichung ergibt den Durchstoßpunkt D (D1 | D2 | D3):

    D1 = X1 + t* XY1
    D2 = X2 + t* XY2
    D3 = X3 + t* XY3


    r und s der Ebenengleichung ausrechnen durch Einsetzen von D in die Ebenengleichung oder über das zuvor aufgestellte Gleichungssystem: (keine Ahnung was programmtechnisch einfacher ist)

    D1 =A1 + r* AB1 + s*AC1
    D2 =A2 + r* AB2 + s*AC2
    D3 =A3 + r* AB3 + s*AC3

    Gleichungssystem lösen => r = … & s= …


    r und s prüfen auf:

    0 <= s <= 1
    0 <= t <= 1
    0 <= s+t <= 1

    (den letzten Schritt könnte ich sogar in Autoit umsetzen :D )

    Einmal editiert, zuletzt von nuts (21. April 2010 um 17:32)