|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 30.12.2007, 18:24 Titel: Kollisionsabfrage auf Dreiecksbasis: Strahl mit Mesh |
|
|
Ich bin dabei, eine Kollisionsabfrage eines Strahls mit einem 3D-Mesh zusammenzubauen. Ich habe nun folgende Funktion vor mir liegen:
Code: | INDEX einfache_kollision::kollision( D3DXVECTOR3 *point, D3DXVECTOR3 *direction, float *dist)
{
INDEX ixhit;
float u, v, d;
int i;
*dist = 1e20f;
ixhit = NOINDEX;
for( i = 0; i < nfaces; i++)
{
if( D3DXIntersectTri( vertexbuffer + indexbuffer[i].vertex[0],
vertexbuffer + indexbuffer[i].vertex[1],
vertexbuffer + indexbuffer[i].vertex[2], point, direction, &u, &v, &d))
{
if( d < *dist)
{
*dist = d;
ixhit = i;
}
}
}
return ixhit;
} |
Diese Funktion durchläuft alle Vertizes und Indizes des Mesh, welches ich zuviel im Initialisieren des Objektes zwischengespeichert habe, und prüft für jedes "Face" die Kollision mit dem Strahl.
Als Parameter übergebe ich die Startposition den Richtungsvektor des Strahls. Der 3. Parameter soll die Entfernung vom nächsten kollidierenden Dreieck wiedergeben (kann ja passieren, dass ein Strahl mehrere Dreicke des Objektes schneidet )
Problem:
Bisher funktioniert die Kollisionsabfrage nur dann, wenn das Objekt noch nicht transformiert wurde (Rotation, Translation, Skalierung).
Ich habe nur irgendwo was mit einer invertierten Worldmatrix gesehen, aber ich habs nicht hinbekommen. Weiß jemand, was man hier genau machen muss, damit die Abfrage auch bei transformierten Objekten funktioniert? _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 30.12.2007, 18:37 Titel: |
|
|
Hm, du möchtest ja wahrscheinlich nicht alle Vertexdaten transformieren um dann auf Kollision mit dem Strahl zu testen (das wäre am einfachsten und naheliegensten).
Naja, das zweite wäre einfach, den Strahl zu transformieren, das sind nur 3 Vektoren im Gegensatz zu ein paar Hundert, die deine Eckdaten haben könnten. In der Tat würde das mit einer invertierten Worldmatrix gehen. Einfacher wäre es natürlich, wenn du z.B. nur Verschiebung und Rotation hättest, dann könntest du das nämlich von Hand machen. Benutzt du die Worldmatrix, dann musst du ein wenig aufpassen, der Richtungsvektor darf ja z.b. nicht verschoben werden.
Eine spontane Idee (bin nciht sicher ob sie zu 100% stimmt) wäre aus den relativen Richtungsvektor einen absoluten Punkt auf dem Strahl zu berechnen (durch Addition) und dann diese beiden Punkte mit der invertierten Weltmatirx zu multiplizieren. Dann kannst du wieder einen relativen Richtungsvektor berechnen und hast deinen Transformierten Strahl.
am besten nimmste mal Zettel, Stift, Zirkel und Lineal und malst dir ein paar Skizzen auf (Kollision Dreieck/Strahl z.b.). Dadurch kannste recht schnell rauskriegen, was genau du machen musst. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 30.12.2007, 18:39 Titel: |
|
|
du musst entweder das Mesh selber rücktransformieren, indem du es mit seiner invertierten Transformationsmatrix (worldmatrix) multiplizierst; ist aber etwas langsam. Oder du transformierst einfach den Strahl in die Ausrichtung des Meshes(durch Multiplikation mit dessen matrix). Dabei kannst du schnell sagen, ob die Kollision stattfindet, aber nicht genau wo. Aber im Grunde müsstest du doch deinen Strahl auch transformieren? d.H. du testest den transformierten Strahl mit dem transformierten Mesh. Wozu möchtest du einen untransformierten Strahl mit einem transformierten Mesh auf Kollision testen?
Gruß DXer |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 30.12.2007, 18:53 Titel: |
|
|
Zitat: | Wozu möchtest du einen untransformierten Strahl mit einem transformierten Mesh auf Kollision testen? |
Will ich ja gar nicht. Nur muss ich ja die Vertizes ja erstmal aus dem Meshobjekt extrahieren. Und da bekommt man ja logischerweise erstmal nur untransformierte Werte. Irgendwie alle Vertizes einzeln transformieren ist auch blöd
Naja, die Rücktranslation des Positionsvektors hab ich ja noch selbst hinbekommen
Code: | du musst entweder das Mesh selber rücktransformieren, indem du es mit seiner invertierten Transformationsmatrix (worldmatrix) multiplizierst |
Hört sich einfach an, geht bei mir aber nur schwer in kopp...egal
Hat irgendwie nicht geklappt. Weiß auch nicht, wieso.
Code: | Oder du transformierst einfach den Strahl in die Ausrichtung des Meshes(durch Multiplikation mit dessen matrix). |
Die Transformation des Strahls hielt ich auch für die eleganteste Lösung. ging bei mir ja vorher schief.
Also jetzt nochmal langsam:
Ich hab ne Kamera mit einem imaginären Strahl. Zur Hand habe ich
Code: | D3DXMATRIX m_ViewMatrix; //Matrix der Kamera
D3DXMATRIX m_ProjMatrix; //Sichtkegel der Kamera |
Welche Matrizenoperationen oder Vektoren muss ich jetzt genau machen, damit das gehen kann?
Edit:
Mein Mesh benutzt folgende Vektoren und Matrizen:
Code: | //Transformationsvektoren
D3DXVECTOR3 m_vScale; //Skalierungsvektor
D3DXVECTOR3 m_vPosition; //Positionsvektor
D3DXVECTOR3 m_vRotation; //Externer Rotationsvektor
//Transformationsmatrizen
D3DXMATRIX TransMatrix;
D3DXMATRIX ScalingMatrix;
D3DXMATRIX WorldMatrix;
//Rotationsmatrizen
D3DXMATRIX RotationMatrix;
D3DXMATRIX RotationMatrixX;
D3DXMATRIX RotationMatrixY;
D3DXMATRIX RotationMatrixZ;
//Rotationsachsen
D3DXVECTOR3 RotationVektorX;
D3DXVECTOR3 RotationVektorY;
D3DXVECTOR3 RotationVektorZ; |
Naja, ich denke, die Matrizen und Vektoren sollten selbsterklärend sein, wofür sie stehen [/code] _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 30.12.2007, 20:01 Titel: |
|
|
Also du hast auf der einen Seite ein Mesh mit untransformierten Vertex Daten und sämtlichen Transformationsmatrizen die du in eine Mesh-Worldmatrix zusammenfassen kannst und auf der anderen Seite einen Strahl den du so wie du ihn in der Funktion bekommst auf Kollision mit dem transformierten Mesh test möchstest oder? (hui langer satz )
Dann könntest du entweder alle Vertices des Meshes mit seiner Worldmatrix multiplizieren und dieses Ergebnis auf Kollision mit dem Strahl testen. Das ist aber nicht schön . Oder du erstellt die inverse Mesh-Worldmatrix und multiplizierst diese mit deinem Strahl. Diesen transformierten Strahl testest du dann auf Kollision mit den Rohdaten deines Meshes aus dem Vertex Buffer.
Gruß DXer |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 30.12.2007, 20:20 Titel: |
|
|
So siehts aus:
- Vertizes bzw. Indezes sind untransformiert
- Objekt selbst soll dennoch transformiert auf Kollision getestet werden
- Strahl ist ebenfalls transformiert
Das wolltest du wohl sagen. Dann liegst du richtig.
Code: | Oder du erstellt die inverse Mesh-Worldmatrix und multiplizierst diese mit deinem Strahl. |
Bisher war ich für diesen Schritt anscheinend zu blöd.
Inverse von Mesh nehmen ist klar. Aber multiplizieren mit strahl...womit soll ich die Worldmatrix vom Mesh mit dem Strahl genau multiplizieren?
Die Kamera hat ja keine Keine Worldmatrix. Oder meinst du eine von den Achsenvektoren der Kamera?? _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 30.12.2007, 20:45 Titel: |
|
|
nein, du hast doch die Matrizen die die Transformation deines Meshes beschreiben (Rotation, Skalierung, Translation etc.) oder? Und du weißt wie du diese Multiplizieren musst um eine Weltmatrix für dein Mesh zu erhalten oder? Diese Weltmatrix musst du invertieren (z.B. mit D3DXMatrixInverse). Die Matrix die dabei rauskommt musst du mit dem Strahl multiplizieren, dann erhälst du einen etwas anderen Strahl. Den nimmst du dann für den Test. Im Pseudo-Code sieht das ungf. so aus CPP: | WorldMatrix = Mesh.SkalationsMatrix * Mesh.RotationsMatrix * Mesh.TranslationsMatrix;
InvWorldMatrix = Inverse( WorldMatrix );
NewStrahl = Strahl * InvWorldMatrix;
Kollisionstest( Mesh.VertexBuffer, NewStrahl ); | Das kommt aufs selbe hinaus wie das Transformieren jedes Vertices von deinem Mesh.
Gruß DXer |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 30.12.2007, 21:07 Titel: |
|
|
Meinst du mit "Strahl multiplizieren" jetzt eine Matrix oder Vector?
Ein Strahl ist genau genommen weder das eine noch das andere.
Das mit der Inversenmatrix anlegen ist ja klar. aber ich hab mit "mit Strahl multiplizieren" beim Verständnis ein Problem
Ich würde mit dem, was du immer als Strahl multiplizieren meinst, den LookAt Vector vermuten:
Code: | D3DXVECTOR3 m_LookAt; //Richtung der Kamera |
Wäre also ne Multiplikation von Matrix mit Vector. Geht das überhaupt?? _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 30.12.2007, 22:00 Titel: ° |
|
|
nein, "strahl multiplizieren" ist dein Direction vector und dein Point vector mit der inversen matrix multiplizieren. Eine Multiplikation von Vector und Matrix geht, das ist ja der Sinn der dahinter steckt. Das bedeutet, dass dein Vector so transformiert wird wie die Matrix es sagt. Also, wenn du eine Rot-Matrix mit 45° um x-Achse mit deinem Vector multiplizierst, dann erhälst du einen Vector der um 45° um die x-Achse gedreht ist.
Gruß DXer |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 30.12.2007, 22:10 Titel: |
|
|
Edit:
Ok, die Funktion hab ich rausgesucht. Die sollte dies bewerkstelligen. Code: | D3DXVECTOR3 * D3DXVec3TransformNormal(
D3DXVECTOR3 * pOut,
CONST D3DXVECTOR3 * pV,
CONST D3DXMATRIX * pM
); |
Und dein "Point Vector" ist dann der Positionsvektor?
Ich hab jetzt mal sowas in etwa probiert:
Code: | float iDist;
int iTrefferindex;
D3DXMATRIX invMat;
D3DXMatrixInverse(&invMat, NULL, &Mesh.WorldMatrix );
D3DXVECTOR3 tempVec;
D3DXVec3TransformNormal(&tempVec, &Camera.m_LookAt, &invMat);
D3DXVECTOR3 vTemp = Camera.m_vPosition;
iTrefferindex = Mesh.Kollision.kollision(&vTemp, &tempVec,&iDist); |
Hat aber auch nicht geklappt. Vielleicht hasse ja ne Ahnung, was da schief gegangen ist _________________ Kein Rückzug! Kein Aufgeben!
Zuletzt bearbeitet von LeeDiGer am 30.12.2007, 22:22, insgesamt 2-mal bearbeitet |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 30.12.2007, 22:17 Titel: |
|
|
LeeDiGer hat Folgendes geschrieben: | Ok, die Funktion hab ich rausgesucht. Die sollte dies bewerkstelligen. Code: | D3DXVECTOR4* D3DXVec3Transform(
D3DXVECTOR4* pOut,
CONST D3DXVECTOR3* pV,
CONST D3DXMATRIX* pM
); |
Aber da bekomm ich nen 4 dimensionalen Vektor als Rückgabe.
Zählen dann nur die ersten 3 Koordinaten?
Und dein "Point Vector" ist dann der Positionsvektor? |
nimm am besten D3DXVec3TransformCoord, die löst den 4d-vektor automatisch auf zu 3d. meine beiden vektoren sind die die du oben in deiner Funktion übergeben bekommst
Gruß DXer |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 30.12.2007, 22:27 Titel: |
|
|
Ok, hab den obigen code mit D3DXVec3TransformNormal durch D3DXVec3TransformCoord ersetzt. Hat so aber auch nicht geklappt.
Code: | float iDist;
int iTrefferindex;
D3DXMATRIX invMat;
D3DXMatrixInverse(&invMat, NULL, &Mesh.WorldMatrix );
D3DXVECTOR3 tempVec;
D3DXVec3TransformCoord (&tempVec, &Camera.m_LookAt, &invMat);
iTrefferindex = Mesh.Kollision.kollision(&Camera.m_vPosition, &tempVec,&iDist); |
_________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 31.12.2007, 02:19 Titel: |
|
|
LeeDiGer hat Folgendes geschrieben: | Ok, hab den obigen code mit D3DXVec3TransformNormal durch D3DXVec3TransformCoord ersetzt. Hat so aber auch nicht geklappt.
Code: | float iDist;
int iTrefferindex;
D3DXMATRIX invMat;
D3DXMatrixInverse(&invMat, NULL, &Mesh.WorldMatrix );
D3DXVECTOR3 tempVec;
D3DXVec3TransformCoord (&tempVec, &Camera.m_LookAt, &invMat);
iTrefferindex = Mesh.Kollision.kollision(&Camera.m_vPosition, &tempVec,&iDist); |
|
nein das kann ja auch nich klappen
nochmal von vorne: du hast einen strahl von dem punkt p in die richtung dir (ich nenn die jetzt einfach mal so weils kürzer ist). Dann hast du ein mesh m mit der world matrix m.worldMatrix = matW und den untransformierten Vertices V. Den Strahl [p,dir) möchtest du auf kollision mit m testen, dazu hast du die Funkion Mesh.Kollision.kollision. In der machst du nun folgendes:
CPP: | // bilde inverse von m's world matrix
invMat = inverse( matW );
// multipliziere den Strahl mit dieser
transP = p * invMat;
transDir = dir * invMat
// teste diesen Strahl [transP|transDir) auf Kollision mit allen Vertices von m
foreach v0,v1,v2 in mesh.vertexBuffer
IntersectTri( v0, v1, v2, transP, transDir, ...); | Alles in der Methode Kollision()
Gruß DXer |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 31.12.2007, 08:35 Titel: |
|
|
Also hab ich vergessen, den Positionsvektor mit der Inversen zu multiplizieren. Das seh ich ein
Aber paradoxerweise gehts immer nocht nicht
Der Fehler liegt jetzt nur noch irgendwie im Richtungsvektor.
Ich hab mal die Werte der Vektoren zum Startzeitpunkt angeguckt:
- Richtungsvektor des Mesh (0,0,1)
- Position des Mesh (0,0,-20)
- "dir" hat den Wert (0,0,1)
- "transDir" (0,0,21)
Oder eine weitere Stichprobe:
- "dir": (-0,0523703, -0,427568, 0.902464)
- "transdir": (-0,0523703, -0,427568, 20.9025)
Kann das erstmal so richtig sein? Sieht ja für mich erstmal richtig aus.
Wenn ja, dann kann ich mir immer noch nicht erklären, warum da jetzt gar nichts mehr geht.
Wenn ich der Kollisionsfunktion jetzt einfach nur den invers transformierten Vektor "p" und dann den untransformierten Vektor "dir" übergebe, dann gehts erstmal, wenn der Gegner sich nicht rotiert
Sobald ich "dir" auch transformiert übergebe, dann geht da überhaupt nichts mehr. _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 31.12.2007, 10:27 Titel: |
|
|
Hast du den Richtungsvektor verschoben? Hast du in erst Absolut gemacht, dann transformiert und dann wieder nach realtiv umgerechnet? So wie ich es im ersten Post geschrieben habe? _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|