• Bitte schaltet eure Ad Blocker aus. SLinfo kann nur betrieben werden, wenn es durch Werbung Einnahmen erzielt. Vielen Dank!!
  • Wir freuen uns, wenn du dich in unserem Forum anmeldest. Bitte beachte, dass die Freigabe per Hand durchgeführt wird (Schutz vor Spammer). Damit kann die Freigabe bis zu 24 Stunden dauern.
  • Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Sie geben Einwilligung zu unseren Cookies, wenn Sie unsere Webseite weiterhin nutzen.

Wo fand die Kollision statt?

Danziel Lane

Superstar
Meistens geb ich hier ja Antworten ... oder verusche es, aber nun will ich mich mal selbst an die Skripter-Kollegen wenden, weil mir vor der Rechnerei der Lösung, die ich mir denken kann, graust.

Problem: Ich brauch so was wie llDetectedTouchxxx für Kollisionen.

Also: ein feststehendes Prim wird getroffen von einem anderen Objekt. Ich will wissen, an welcher Stelle der Oberfläche genau.
Da gibt es die Funktion llDetectedPos.
Die allerdings gibt mir die Position des Mittelpunktes des beweglichen Objektes an, und wenn die schnell sind, dann sind sie auch sehr lang und ich kenn dummerweise deren Geometrie nicht.
Ich bekomme also eine Position, die irgendwo vor meinem Zielobjekt liegt.

Meine Idee ist: ich hab ja auch die Geschwindigkeit des einfliegenden Objektes (llDetectedVel) und könnte nun als mathematisches Objekt den Mittelpunkt weiterfliegen lassen, bis der durch die Objektoberfläche geht. Dann hab ich den fiktiven Einschlagpunkt.

Ja, ich hab mal beide Scheine in Lineare Algebra gemacht und es gab mal eine Zeit (Jahrzehnte vor heute), da konnte ich das in wenigen Minuten. Dazu kommt meine Feindschaft mit den Rotations-Quadrupeln in LSL.

Ich frag euch also: hat schon mal einer so was gelöst (Zielobjekt ist entweder ein Würfel oder eine Kugel, also relativ einfache Oberflächen) oder gibt es eine einfachere Lösung als meine Idee?

Wäre nett, wenn wir das hinbekämen ohne dass ich meine alten Bücher aus dem Keller holen muss.
 
55 Hits ... 55 haben's gelesen ... und keiner hat einen Tipp?

Ich weiß, es gibt Zielscheiben in SL, die das Einschussloch genau an der richtigen Stelle der Oberfläche rezzen, auch wenn die "Gewehrkugel" 5 Meter lang ist.

Und ich weiß, dass die Mathematik das hergibt, wenn ich's auch nicht mehr aus dem Kopf hinkriege.

Wirklich keiner da, der mir da weiterhelfen kann?
 
Wenn es für beliebe Geometrie und Bedingungen gelten soll wird es nicht einfach. detectedpos and -vel sind schon mal gute Werkzeuge.

Am besten du gibst mal ein typisches Beispiel und dann schaun wir weiter.
 
Dann will ich mal das Problem noch mal darstellen. Am einfachsten ist es als Zielscheibe beschrieben.
Die auf dem Bild hat die Abmessungen 4,0 x 0,1 x 4,0 und steht auf 28, 46, 24.

Ich hab drei Pfeile draufgeschossen und rezze erst mal dicke rote Kugeln statt der Einschusslöcher.

Nun ist es so, dass die Zielscheibe die Kollision wohl in der Regel detected bevor das der Pfeil tut. Wann das genau passiert, wird man wohl nicht vorhersagen können. Es wird also immer - auch weil der Pfeil eine gewisse Länge hat - ein Punkt als Kollisionspunkt ermittelt, der vor der Zielscheibe liegt.

Wie Kottos richtig sagt, kann man nun von diesem Punkt mit dem Geschwindigkeitsvektor weiterrechnen und den Treffpunkt mit der Oberfläche der Zielscheibe ermitteln.
Wenn die Zielscheibe wie im Bild in Nord-Süd-Richtung ausgerichtet ist, ist das reine Dreiecksmathematik, man müsste nur das Dreieck kontruieren, bei dem x = 28,05 ist.

Dafür hätte ich nicht gefragt, die Mathe kann ich auch heute noch.

Interessant wird es erst, wie auch Kottos richtig feststellt, wenn man die Zielscheibe irgendwie (schräg) in die Welt stellt.

Es wäre wunderschön, wenn jemand so ein Problem schon gelöst hätte oder noch so nah dran ist, dass das schnell aus dem Kopf geht.

Letztendlich will ich ja die roten Bälle direkt auf der Oberfläche der Zielscheibe rezzen ... und dann sollen sie aussehen wie Einschusslöcher.

So, das ist mein Problem etwas bildhafter dargestellt, und dazu gibt es auch noch ein Bild von meinem heutigen Test. Im Chat sind die Kollisionspunkte zu sehen (ermittelt von der Zielscheibe) und die ermittelte Geschwindigkeit.
 
Schnelle Idee, grob umrissen:

1) Du kennst den Mittelpunkt der Zielscheibe (llGetPos) sowie den Normalenvektor der Ebene (<0,0,1>*llGetRot()), falls die lokale z-Achse von der Scheibe wegführt. Wenn nicht, dann die 1 an die entprechende Stelle setzen.

Das gibt die Ebenengleichung in Normalenform.

2) Der Vektor des Geschosses gibt llDetectedPos()+lambda*llDetectedVel() im sensor event.

3) Dann kann man den Schnittpunkt der Ebene und des Geschossvektors berechnen. Hab ich gerade nicht im Kopf, sollte sich aber in den Weiten des Internets finden lassen.

An der Stelle kannst du dann das Einschussloch rezzen.

Die Methode ist komplett unabhängig von irgendwelchen Rotationen der Prims.

Nachtrag: Wie der Schnittpunkt berechnet wird, steht hier (erste Seite).
Wie man aus den obigen Angaben die Ebenengleichung bastelt, die in der Lösung gebraucht wird, steht in Wikipedia unter "Ebene".
 
Naja, eigentlich sollte das von der Mathe her nicht soo schwer sein, sprich Klasse 11 oder 12 oder sowas.

Alles was du tun musst ist die Zielscheibe im Raum als Ebene aufzufassen, d.h. du brauchst z.B. 3 Punkte aus dem Ebenenbereich und kannst damit dann einen Stütz- und zwei passende Richtungsvektoren (d.h. die sollten linear unabhängig sein) der Ebene bestimmen. Daraus kannst du dir eine Ebenengleichung in Parameterform basteln. also sowas E = <a1,a2,a3> + l <b1,b2,b3> + m <c1,c2,c3>, wobei eben alle an,bn,cn bekannt sind.
Alternativ kannst du dir auch den Winkel der Ebene im Raum ausrechnen, wenn du mit den Rotationen ein Problem hast hilft dir da llRot2Angle, llRot2Euler usw. Jedenfalls solltest du da eine Parameterform der Ebebengleichung haben am Ende.

Für das fliegende Prim kannst du aus dem Ort und dem Richtungsvektor eine Gerade basteln, also g = <d1,d2,d3> + o <f1,f2,f3>.

Und wenn du E = g setzt, dann kriegst du ein definiertes und eindeutiges Gleichungssystem (3 Gleichungen mit 3 unbekannten), das du lösen musst.

Da dir LSL da keine CAS-Werkzeuge mitbringt (es gibt leider kein llSolve(....) oder llApprox(...) ) musst du das dann eben mehr oder weniger "von Hand" lösen.

Einen fertigen Algorithmus hab ich dir da leider nicht, aber im Prinzip müsste sich sowas wie der Gauß-Algorithmus (bzw. eine der iterativen Methoden) ohne weiteres in LSL umsetzen lassen. D.h. du bringst dein System eben stur auf die Dreiecksform und löst dann Schritt für Schritt deine Variablen auf.

(gibt auch noch andere Methoden, aber da müsste ich auch erst das Mathebuch rauskramen. Irgendwas von Dreiecksmatrizen und einer Diagonalmatrix, die gegeneinander verrechnet werden müssen hab ich da noch im Hinterkopf... müsste aber auch erst im Buch kramen...)

Damit hast du den Schnittpunkt von Ebene und Gerade.

Und wenn der Schnittpunkt in einer bestimmten Fläche liegt (in deinem Fall innerhalb des Kreises x = Mx + r * cos(phi); y = My + r * cos(phi); x und y bzw. r an die Lage der Ebene angepasst, d.h. letztlich ist das simple Trigonometrie...und das kann LSL ja, wenn auch nicht direkt mit vektoren...), dann ist es ein Treffer.
 
Vielen Dank euch beiden.

Klar, sooooo schwer ist die Mathe nicht, und es gab eine Zeit, da hätte ich das alles auswendig hingeschrieben ...

Vielleicht macht es Sinn, mal über eine Sammlung von Funktionen nachzudenken, die Vektoroperationen nachbilden, damit man Aufgaben wie diese demnächst schneller lösen kann.

Oder ich warte auf M Linden's Versprechen, dass bald schon C # in SL machbar ist, dann stehen mehr Funktionen zur Verfügung.

So richtig interessant wird diese Aufgabe ja auch erst, wenn die Zielscheibe nicht einfach ne Box ist oder sich vielleicht selbst noch bewegt.

Ich werd mal übers Wochenende (ich Fauler!) weiter machen mit den Skripten für dieses Projekt. Falls noch jemand hilfreiche Ideen hat, mag man die getrost posten.
 
Eine Bibliothek klingt sehr gut. Unter GPL etwa damit sie offen aber verwendbar bleibt. Ich habe immer noch ein Projekt vor zu entwickeln (auf Bestellung, daher nichts näheres), der mathematische Teil besteht darin, für primitive geometrische Bereiche auszurechnen

* ob ein Punkt innerhalb des Bereichs liegt
* der nächstliegende Punkt auf jeder Seitenfläche
* Projektion eines Vectors auf jede Seitenfläche
* Schnittpunkt einer Linie mit jeder Seitenfläche
* Abstand zu jeder oder zur nächsten Seitenfläche

Als primitiver Bereich musste man Quader, Sphere, Zylinder und Torus nehmen, zunächst nicht hohl, aber mit allen Transformationen die man in SL per Editor macht. Ausrichtung müsste natürlich auch beliebig sein. Auf Torsion könnte zunächst auch verzichtet werden.

Ich habe zwar für einen Quader angefangen, aber wegen Zeitmangels dann abgebrochen. Es wäre wirklich interessant wenn soetwas verfügbar wäre. Leider kann ich keine Beteiligung versprechen.

Vielleicht macht es Sinn, eine kleine Projektgruppe zu diesem Thema zu eröffnen die das Entwickelt, oder zumindest ein Thread (oder soll dieser bleiben?). Weil evtl muss auch entschieden werden in welcher Form die Bibliothek ansprechbar ist, ob man ein getrenntes Skript macht der per Linkmessage die Aufgabe und Ergebnis übermittelt (bekommt) oder in Form von Funktionen, die man in die Skripte aufnimmt. Wie soll die Eingabe der Funktionen aussehen usw.
 
Meine Überlegungen vorerst

Am besten sollte eine Reihe von Funktionen zur Verfügung stehen. Diese kann man nach Bedarf in den eigenen Skript übernehmen oder falls sie viel am Skriptspicher verbrauchen in einen Skript auslagern. Der umgekehrt Weg könnte schwieriger werden.

Alle Berechnungen sollten in lokalen Koordinaten des Bereichs (etwa die Zielscheibe) durchgeführt werden, d.h. Funktionensparameter und -Ergebnis ist im lokalen Koordinatensystem. Zum Umrechnen in/aus globalen Weltkoordinaten können zwei Funktionen helfen.

Punkt-Im-Bereich-Problem ist einfach zu lösen indem man Schnittpunkte einer Linie vom Testpunkt zu Bereichsmitte mit den Bereichswänden zählt, bei einer ungeraden Anzahl ist der Testpunkt draußen.

Der Quader scheint die einfacste Form zu sein, für die die erste Formeln zu schreiben sind, hinterher kommen weitere Formen. Torsion habe ich vergessen auszuschließen, vorerst braucht man sie nicht, sollte aber später hinzukommen. Genauso wie Holigkeit, wenn man schon eine allgemein nutzbare bibliothek zusammenstellt. Ebenso die Ringform hinzunehmen.

Abstand zur Oberfläche könnte man z.B. aus Distanz zum nächsten Punkt der Flächen berechnen, also kann sein dass die Werte in der Aufgabe aufeinander aufbauend zu berehnen sind. Evtl macht es Sinn, an die Fuktionen auch eine Liste von Zwischenrechnungen weitergeben, damit die Mehrfachberechnung von Werten vermieden werden kann. Kommt auf die verwendete Mathe an.

Eine Projektgruppe für diese Bibliothek könnte zu viel sein, aber wir haben bald Skriptlimits, also muss einiges an schon verfügbaren freien Skripten überarbeitet und optimiert werden, evtl macht es da Sinn eine PG darüber zu eröffnen.
 
Eigentlich ist die Idee nicht schlecht, denn so wie es aussieht wird LSL nicht mehr erweitert werden. Allerdings soll (wenn alles gut geht) demnächst C# in SL einzug halten, und da gibts schon jede Menge freie Codeschnippsel, die man z.B. für eine numerische Approximation benutzen könnte.
Und es gibt schon jede Menge Bibliotheken, die man für Vektor- bzw. Matrizenberechnungen nutzen könnte.

Alles, was man dabei im Prinzip machen muss ist ein einfaches CAS (ComputerAlgebraSystem) in SL zusammenzubasteln mit dem man eben wie erwähnt einfache Gleichungen lösen kann und das man dann in Funktionen wie llSolve() verwenden kann um Probleme wie den Abstand Punkt-Ebene schnell zu lösen. Da kann man dann z.B. einfach die gegebene Mathe Ausnutzen (Stichwort Hesseche Normalenform) und mit wenig Aufwand über einfache, lineare Gleichungssysteme schnell zu einer Lösung kommen.

Das schöne am PC ist nämlich, dass der zwar eigentlich nicht besonders gut ist wenn es drum geht mathematische Muster zu erkennen (ein Mensch sieht einfach, dass 20 mod 5 = 0 ist, ein PC muss das ausrechnen oder nachschlagen...) , aber der PC kann dafür verdammt schnell rechnen.

D.h. wenn einem genäherte Ergebnisse reichen, dann sind auch nichtlineare Gleichungssystem und Differentialgleichungen kein Problem mehr.
 
Und wenn du E = g setzt, dann kriegst du ein definiertes und eindeutiges Gleichungssystem (3 Gleichungen mit 3 unbekannten), das du lösen musst.

Mir erschliesst sich gerade nicht, warum man ein Gleichungssystem erhaelt und für die Lösung den Gaußalgorithmus oder so etwas benötigt.

Der gängige Weg berechnet den Parameter, den du mit "o" bezeichnet hast. Den in die Geradengleichung eingesetzt, liefert den Vektor zum Durchstosspunkt Gerade-Ebene.
 
Mir erschliesst sich gerade nicht, warum man ein Gleichungssystem erhaelt und für die Lösung den Gaußalgorithmus oder so etwas benötigt.

Das Gleichungssystem ergibt sich aus der Gleichsetzung der Ebene mit der Gerade.

<a1,a2,a3> + l * <b1,b2,b3> + m * <c1,c2,c3> = <d1,d2,d3> + o <e1,e2,e3>,

Das ist so u.A. ein Gleichungssytem mit 3 Gleichungen und 3 Unbekannten d.h. du hast lediglich l,m und o als unbekannte. Und damit kannst du o ausrechnen.

Natürlich kann man auch über die Normale einer Ebene arbeiten, aber dann hast du eben ein System aus 2 Gleichungen mit 2 Variablen, das du eben auch wieder lösen musst.

Der gängige Weg berechnet den Parameter, den du mit "o" bezeichnet hast. Den in die Geradengleichung eingesetzt, liefert den Vektor zum Durchstosspunkt Gerade-Ebene.
Genau das passiert da oben. Man berechnet o und kriegt den Punkt.

Und den Gauß (oder eine iterative Abwandlung mit einem beliebigen Startwert) nimmt man deswegen, weil man das leicht in einem Algorithmus umsetzen kann...
 
Kleine Anmerkung noch:
Parameterform deswegen, weil man die Ebene leicht durch 3 Punkte bestimmten kann.

Z.B. liegt dein (1x1x1m) Würfel mit den Koordinaten 150/160/32, dann hast du eine Ecke bei (149.5/160/31.5) und du hast ausgehend davon dann spannvektoren von z.B. (0/0/1) und (0/1/0), d.h. du hast schon die Ebenengleichung E = <149.5/160/31.5> + k <0,0,1> + l <0,1,0>

natürlich kann man das einfach in die Normalenform schreiben, d.h. du kriegst:
(<E1,E2,E3>-<149.5/160/31.5>)*<1,0,0>=0 und kannst das dann
ein klein wenig einfacher/schneller lösen. Das ist, wenn man das von Hand machen muss, klar einfacher, zumal man da nicht mal was umrechnen muss sondern den Normalenvektor ja schon "sieht".

Nur wenn du eben einmal einen solver für Gleichungssysteme programmiert hast, dann kannst du den auch nutzen um z.B. auch die Schnittpunkte von Geraden zu berechnen. Und wenn du 2 Ebenen schneiden willst, dann kriegst du auch ein lin. Gleichungssystem, das du am PC am besten mit dem vorhandenen Algorithmus lösen kannst, der dafür jeweils nur wenig modifiziert werden muss.
 
Lange Rede, kurzer Sinn :)

Das sollte es tun. Auch ohne Solver für Gleichungssysteme.

Code:
collision_start(integer num)
{
    float d = llVecMag(llGetPos());
    vector n = <0,0,1>*llGetRot(); // wenn Trefferflaeche x-y-Ebene
    vector p = llDetectedPos(0);
    vector v = llDetectedVel(0);
    vector t = p + ((d - p*n)/(v*n))*v;
    llRezObject("Treffer",t,ZERO_VECTOR,ZERO_ROTATION,1);
}
 
Das weiß ich eben nicht, was als Treffermarkierung vorgesehen ist, so dass ich es mal freigelassen habe. Aber stimmt schon, für alles was keine Kugel ist, müsste dort llGetRot rein.
 
Ihr seid richtig lieb, ich werde nun übers Wochenende weitermachen an dem Projekt.

Richtig, die Rotation muss am Schluss auch noch übernommen werden, aber ich hab erst mal mit Kugeln als Treffermarkierung gearbeitet, später sollen auf das Produkt Zielscheibe Zylinder mit einem schönen Einschussloch placiert werden.
Das ist aber ein ziemlich kleines und späteres Problem.
 

Users who are viewing this thread

Zurück
Oben Unten