JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.phpMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Kollisionsabfrage auf Dreiecksbasis: Strahl mit Mesh
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> DirectX, OpenGL
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 19:24    Titel: Kollisionsabfrage auf Dreiecksbasis: Strahl mit Mesh Antworten mit Zitat

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 Wink)

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
Benutzer-Profile anzeigen Private Nachricht senden
Jonathan_Klein
Living Legend


Alter: 36
Anmeldedatum: 17.02.2003
Beiträge: 3431
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 19:37    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 19:39    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 19:53    Titel: Antworten mit Zitat

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 Wink

Naja, die Rücktranslation des Positionsvektors hab ich ja noch selbst hinbekommen Wink

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 Wink
Hat irgendwie nicht geklappt. Weiß auch nicht, wieso. Wink

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 Wink[/code]
_________________
Kein Rückzug! Kein Aufgeben!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 21:01    Titel: Antworten mit Zitat

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 Rolling Eyes )

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 Razz . 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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 21:20    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 21:45    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 22:07    Titel: Antworten mit Zitat

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 Wink

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
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 23:00    Titel: ° Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 23:10    Titel: Antworten mit Zitat

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? Wink

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 Wink
_________________
Kein Rückzug! Kein Aufgeben!


Zuletzt bearbeitet von LeeDiGer am 30.12.2007, 23:22, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 23:17    Titel: Antworten mit Zitat

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? Wink

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 30.12.2007, 23:27    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
DirectXer
Dark JLI'ler



Anmeldedatum: 05.02.2005
Beiträge: 1201
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 31.12.2007, 03:19    Titel: Antworten mit Zitat

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 Razz

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
LeeDiGer
Super JLI'ler



Anmeldedatum: 31.08.2003
Beiträge: 366
Wohnort: Duisburg
Medaillen: Keine

BeitragVerfasst am: 31.12.2007, 09:35    Titel: Antworten mit Zitat

Also hab ich vergessen, den Positionsvektor mit der Inversen zu multiplizieren. Das seh ich ein Wink

Aber paradoxerweise gehts immer nocht nicht Very Happy

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 Wink
Sobald ich "dir" auch transformiert übergebe, dann geht da überhaupt nichts mehr.
_________________
Kein Rückzug! Kein Aufgeben!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Jonathan_Klein
Living Legend


Alter: 36
Anmeldedatum: 17.02.2003
Beiträge: 3431
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 31.12.2007, 11:27    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> DirectX, OpenGL Alle Zeiten sind GMT
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehe zu:  
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

Impressum