Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

15.02.2011, 15:42

Skinning eines md5mesh auf der gpu

Hallo, ich hoffe, dass mir hier einer helfen kann mein Problem mit dem md5 Modelformat zu lösen.
Ich kann ein Md5 Model normal laden und auch (ohne Animation) anzeigen. Soweit so gut, nur stehe ich jetzt vor dem Problem, dass die Daten für ein Softwareskinning auf der cpu ausgelegt sind ich dieses haber im VertexSader machen möchte. Es gibt für jede Gewichtung der Bones eigene xyz Koordinaten woraus dann die Finalen Vertizes berechnet werden.
Die Bones sind in der Bindpose im Objectspace aber das umrechnen in den jeweiligen Bonespace bekomme ich so :link berechnen.
Ich habe auch hier genau das Problem gefunden und der letzte Post auf der ersten Seite scheint auch eine Lösung zu sein nur verstehe ich nicht was er mit den jeweiligen Matrizen mein bzw wie ich an sie gelange.

zusammengefasst : gibt es eine Möglichkeit die Vertices anhand der Bindpose und der Bones zu berechnen, sodas diese in der gpu verarbeitet werden können ?

Danke Ludwig

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

15.02.2011, 16:26

So ganz ist mir dein Problem nicht klar. Skinning funktioniert auf der GPU genau gleich wie auf der CPU. Die grundlegende Idee dabei ist folgende: Du berechnest für jeden Bone in der Bindpose die Transformation in Object Koordinaten (Bindpose absolute). Die ergibt sich als Produkt der lokalen mit allen parent Transformationen (da es sich nur um Rotationen handelt können diese über Quaternionen abgebildet werden). Die Inverse davon transformiert eine Objectspace Koordinate (Vertex) zurück in das Koordinatensystem relativ zum jeweiligen Bone. Wenn sich ein Bone nun bewegt hat kannst du die neue Position eines Vertex nun berechnen aus seiner Position relativ zum Bone transformiert mit der neuen absoluten (Produkt der neuen lokalen mit allen neuen parent Transformationen). Diese Transformationen kannst du alle zusammen in eine einzelne Quaternion bzw. Matrix konkatenieren und das passiert immer auf der CPU. Hardware Skinning bedeutet nur dass du diese Quaternionen/Matritzen dann auf die GPU packst die im VertexShader eben die Position jedes Vertex mit den entsprechenden Transformationen berechnet, was natürlich exorbitant schneller is als das alles auf der CPU zu rechnen.

3

15.02.2011, 16:46

ja, das was du schreibst ist mir mehr oder weniger klar. Mein Problem besteht darin das ein md5Mesh aber pro Vertice mehrere xyz Koordinaten und Gewichtungen hat.

vert [vertIndex] ( [texU] [texV] ) [weightIndex] [weightElem]

passend dazu :

weight [weightIndex] [jointIndex] [weightValue] ( [xPos] [yPos] [zPos] )

daher kann ich die Daten nicht einfach im Shader verarbeiten. Daher suche ich eine Möglichkeit um die Daten in die benötigte Form zu bringen.
Die Inverse davon transformiert eine Objectspace Koordinate (Vertex) zurück in das Koordinatensystem relativ zum jeweiligen Bone.
Wenn ich jetzt die Vertizes beim laden für den Objectspace berechne kann ich mit der inversen des Bonequaternion die Vertizes soweit transformieren, dass ich damit auf der Grafikkarte arbeiten kann !? Das könnte ja schon fast die Lösung sein.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

15.02.2011, 16:50

Naja, da du ja mehrere Bones gewichten willst kannst du nicht einfach die Transformation mit der Inversen vorberechnen. Aber das machst ja auch gar nix. Du kannst ja die Bindpose Objectspace Vertices in deinem VertexBuffer ablegen und einfach die Inverse Bindpose absolute noch auf die neue Transformation draufmultiplizieren und fertig!?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

15.02.2011, 17:00

Ok, ich denk jetzt versteh ich dein Problem (hab mir mal das MD5 Format angeschaut). Spontan würd ich das so machen dass ich von einer fixen (maximalen) Anzahl an weights pro Vertex ausgehe. Wenn das z.B. 5 sind packst du einfach die 5 Positionen + Joint indices in jeden Vertex und fertig. Alternativ könntest du zuerst die Objectspace Position des Vertex für die Bindpose berechnen und dann einfach nur die verwenden, was natürlich evtl. zu nicht ganz korrekten Ergebnissen führt wenn ein Model diese Eigenheit des MD5 Formats irgendwie ausnutzt. Tbh kann ich da mangels Erfahrung mit MD5 nicht viel dazu sagen...

6

16.02.2011, 15:50

danke erstmal!

wenn ich das Modelformat jetzt erstmal außen vor lasse.

Mal angenommen ich habe ein Model wo jedes Vertize nur einen Bone als Einfluss hat.

1) die Bonematrizen werden absolut zu den Parents an den Shader übergeben?
2) die Vertizes liegen relativ zu den Bones im VertexBuffer ?
3) wenn ich die Vertizes absolut vorliegen habe bekomme ich diese mit der inversen der absoluten Bonematix in Form von Punkt 2 ?
4) auf dem shader würde dann "nur" relatives Vertize mit absoluter Bonematirx multipliziert und ich hätte die neue Position in Abhängigkeit des Bones ?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

16.02.2011, 20:47

Wenn du nur einen Bone pro Vertex hast kannst du die Vertices schon relativ zu den Bones in den VertexBuffer packen (also Vertex * InverseBindPoseAbsolute). Für den Fall hätte man folgenden Ablauf (angenommen du rechnest mit Zeilenvektoren):
  1. CPU Berechnet neue absolute Matrix für jeden Bone (JointTransform = Absolute)
  2. GPU berechnet im VertexShader einfach

    Quellcode

    1
    
    Vertex * JointTransform[BoneIndex] * WorldViewProjection

Falls du mehrere Bones pro Vertex hast kannst du die Vertices nichtmehr einfach relativ zum Joint in den Buffer packen. In dem Fall tust du einfach ganz normal die Vertices wie sie sind im Objectspace in den Buffer und packst die InverseBindPoseAbsolute noch vorne auf jede JointTransform drauf, also so:
  1. CPU Berechnet neue absolute Matrix für jeden Bone (JointTransform = InverseBindPoseAbsolute * Absolute)
  2. GPU berechnet im VertexShader

    Quellcode

    1
    
    (Vertex * JointTransform[BoneIndex0] * Weight[BoneIndex0] + Vertex * JointTransform[BoneIndex1] * Weight[BoneIndex1] + ... ) * WorldViewProjection

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dot« (16.02.2011, 20:55)


8

16.09.2011, 16:22

ich muss nach langer Pause dieses Thema leider nocheinmal reaktivieren : (
CPU Berechnet neue absolute Matrix für jeden Bone (JointTransform = InverseBindPoseAbsolute * Absolute)
GPU berechnet im VertexShader

Quellcode
1
(Vertex * JointTransform[BoneIndex0] * Weight[BoneIndex0] + Vertex * JointTransform[BoneIndex1] * Weight[BoneIndex1] + ... ) * WorldViewProjection

was geschrieben wurde funktioniert ohne Probleme! Nur steht in der Literatur immer die Formel V = Absolute * InverseBindPoseAbsolute * Vertex.

Da Matrizen im Allgemeinen nicht kommutativ sind vertehe ich nicht, wieso die oben geschriebene Lösung Funktioniert

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

16.09.2011, 19:24

Vermutlich weil die Matritzen in deiner Literatur für Spaltenvektoren gedacht sind, du aber mit Zeilenvektoren arbeitest, was genau dazu führt, dass die Multiplikationsreihenfolge sich umgekehrt.

Werbeanzeige