Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mi Jul 16, 2025 12:08

Foren-Übersicht » Programmierung » Shader
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 13 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Do Jul 15, 2010 14:13 
Offline
DGL Member

Registriert: Mi Jul 14, 2010 13:53
Beiträge: 6
Hallo,

im Tutorial Boneanimation per Vertexshader erschien mir der gezeigte Code des Vertexshader für die Matrix-Animation zunächst sinnvoll, aber beim Ausprobieren bin ich auf ein Problem gestoßen, welches ich nicht lösen kann.

Nehmen wir an, ich möchte einen Charakter animieren. Für den linken Arm habe ich also einen einen Bone erstellt und alle Vertices des Arms mit dessen ID verknüpft. Die Gewichtung ist 1 und nimmt im Bereich der Schulter zum Körper hin auf null ab.

Da sich der Arm nicht um den Nullpunkt drehen soll, habe ich die Matrix des Joints auf die Position in die Mitte der Schulter gelegt (matrix-translations-werte 12,13,14) und ziehe diese Koordinate nach der Multiplikation der Vertices mit der Matrix wieder ab, so dass die Translation wieder Rückgängig gemacht wird, da ich nur eine Drehung um den Drehpunkt "Schulter" haben möchte.
Das funktioniert so weit.

Allerdings werden alle Vertices mit Gewichtung kleiner 1 um einen falschen Drehpunkt gedreht, da dieser in der Zeile
Zitat:
mat += Pose[int(Bones[i])] * fract(Bones[i]);

ebenfalls nur anteilig verwendet wird, d.h. der Drehpunkt ist bei einer Gewichtung 0.5 in der Mitte zwischen Schulter und Nullpunkt, also irgendwo in der Bauchgegend meines virtuellen Charakters und dies sieht nicht sehr natürlich aus...

Was mache ich falsch?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Jul 15, 2010 15:14 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Spontane Idee: Würde ein doppelter Bone funktionieren? Also quasi den Bone an der Position des Drehpunktes doppelt auslegen. Einmal mit Rotation und einmal ohne. Dazwischen sollte sich dann interpolieren lassen.

(Ich habe von Boneanimation keine Ahnung...)

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 00:20 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Hmmm, leider hast Du keinen Sourcecode gepostet. Also schaun wir mal (es ist allerdings ein Uhr morgens - möglicherweise verhack ich's)

Man nehme den Vertex und multipliziere ihn einmal mit Matrix1 und einmal mit Matrix2: das ergibt VertexNew1 und VertexNew2.

Der endgültige Vertex ergibt sich dann so:
VertexFinal = (VertexNew1 * Weight1) + (VertexNew2 * Weight2)

wobei Weight1 und Weight2 jeweils Werte zwischen 0 und 1 sein müssen und außerdem gilt
Weight1 + Weight2 = 1

Sollte eigentlich so funktionieren.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 07:45 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
@Traude:
Zitat:
Hmmm, leider hast Du keinen Sourcecode gepostet.

Der steht im verlinkten Tutorial. Und da affine Matrizen eine lineare Operation sind, kann man auch einfach die Matrizen interpolieren, wie das im Tutorial auch schon gemacht wird.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 10:33 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Coolcat hat geschrieben:
Und da affine Matrizen eine lineare Operation sind, kann man auch einfach die Matrizen interpolieren
Nein, man kann nicht. Das ist keine mathematisch korrekte Methode. Der Threadstarter hatte ja z.B. auch Schwierigkeiten damit. Google mal nach "interpolate matrices", da wirst Du von einschlägigen Informationen fast erschlagen.

Zur angesprochenen Wiki-Quelle: wenn das dort wirklich so drinsteht, macht es das auch nicht richtiger. Manchmal stehen im Wiki eben auch Dinge drin, die nicht richtig sind, das geht auch der Wikipedia so.

Ich zitiere auch eine Quelle, allerdings in Englisch, und ich kann auch keinen direkten Link angeben, sondern Du musst danach googeln, denn es ist ziemlich tief verschüttet im Citeseer(ein direkt herunterladbares PDF):
"Skinned Mesh Character Animation with Direct3D" .

Nicht mehr das Neueste, aber eine sehr gute Info, insbesondere von jemandem, der sich jeden Tag damit beschäftigt und der das Ganze nicht nur als Hobby betreibt. Siehe insbesondere der blaue Kasten auf Seite 9.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 12:00 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Nein, man kann nicht. Das ist keine mathematisch korrekte Methode.

Öh, doch? Bei einer affinen Matrix (also keine Projektion bzw. perspektivische Division) ist das durchaus möglich.

M und N sind die Matrizen
v ist der ursprüngliche Vertex, v' der transformierte und interpolierte
a,b sind die Gewichte

Du hast da folgendes:
Code:
v' = Mv * a + Nv * b
<=> v' = a * Mv + b * Nv         //erlaubt denn a,b sind Skalare
<=> v' = (aM)v + (bN)v           // nur anders geklammert
<=> v' = (aM + bN)v               // Matrix-Multiplikation erfüllt Distributivgesetz


Eine perspektivische Division macht das Distributivgesetz natürlich kaputt, aber die wird hier auch nicht benutzt. Das Problem des Fragenstellers ist das er die falsche Matrix (falscher Drehpunkt) zum interpolieren verwendet.

Auch ist die Matrix-Interpolation vielleicht nicht immer die Operation die man eigentlich haben will. Also z.B. ist die Interpolation zwischen Einheitsmatrix und einer Rotationsmatrix keine Rotation um den halben Winkel. Im Tutorial werden ja nicht grundlos die Quaternions erwähnt.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 12:48 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Zitat:
v' = Mv * a + Nv * b
<=> v' = a * Mv + b * Nv //erlaubt denn a,b sind Skalare
Das bestreit ich energisch. So hab ich das nicht geschrieben. Ich hatte zwei "Zwischen"-Vertices, die ich getrennt mit je einer Matrix multipliziert habe. Der Ergebnisvertex ist dann eine Interpolation der beiden "Zwischen"-Vertices. Genau das ist ja der springende Punkt.

Zitat:
<=> v' = (aM)v + (bN)v // nur anders geklammert
Hier machst Du etwas mathematisch Unzulässiges. Die Matrix vorher mit einem Skalar zu verändern, hat einen erheblichen Einfluss auf die zugehörige Rotationsachse, die in der Matrix drinsteckt. Anders ausgedrückt: Du zerstörst damit Deine affine Rotationsmatrix.

Wenn man das macht, wächst das transformierte Bone zu einem ungeheuren Ding an. Denselben Effekt kann man z.B. auch mit Quaternionen erzeugen, wenn es nämlich kein Einheitsquaternion ist. Sieht sehr lustig aus, aber glaub mir: so eine Transformation willst Du nicht wirklich haben.

Die Multiplikation der Matrix mit dem Vektor darf nicht auseinandergenommen werden. Ich bin kein Mathematiker, aber das ist so etwas Ähnliches als ob Du schreiben würdest: a*x² = (a*x)². Hier kann man nicht ganz einfach anders klammern.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 13:29 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
Ich stimme da Traude durchaus zu, denn wenn man zwei Matrizen jeweils um einen Faktor skaliert, und dann beide zusammen rechnet um die beiden Faktoren wieder zu '1' zusammen zu Summieren, so muss nicht automatisch gegeben sein, dass alle Spalten ebenfalls eine Länge von 1 haben nach der Addition. Das ist der springende Punkt. die Richtung der Spalten wird höchstwahrscheinlich stimmen, aber die Länge ist nicht mehr normiert, dadurch entsteht der Effekt, dass zusätzlich zur Rotation der Vertices eine Skalierung stattfindet, die die Vertices zum Ursprung wandern lässt.

_________________
Klar Soweit?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 13:58 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
@Traude & Sellmann:
Ich denke wir klären gerade mal über private Nachrichten wer den nun recht hat. Ich bin mir eigentlich verdammt sicher das ich Recht habe....aber ihr beide offensichtlich auch. Wir müssen Mandelmann ja jetzt nicht noch mehr verwirren.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 14:26 
Offline
DGL Member

Registriert: Di Okt 13, 2009 17:25
Beiträge: 365
Programmiersprache: C++
Back to Topic: Ich glaube ein doppelter Bone würde nicht zum gewünschten Ergebnis führen. Denn das Duplikat müsste dann ja die Gewichtung 1.0 - fract(Bones[0]) haben. Die würde auch für seine (nicht vorhandene) Rotation gelten. Die Gewichtung sollte ja eigentlich ein zweiter Bone mit Rotation bekommen - im Endeffekt würde ein doppelter Bone glaube ich nur zu unerwünschter Skalierung führen.

So wie ich den Vertexshader-Code verstehe, ist er wohl nicht ganz korrekt. Ich bin allerdings auch kein Pro in sowas, eigentlich müsste der Autor dieses Wiki-Artikels dir weiterhelfen können (laut History Andreas). Da der Artikel gerade offline bearbeitet wird (von wem eigentlich?), ist die Wahrscheinlichkeit gar nicht gering, dass er Fehler enthält.

Bei mir läuft die Bone-Animation noch auf der CPU. Da löse ich das so, dass ich für die Rotation grundsätzlich nur 3x3 Matrizen verwende. Vor der Multiplikation mit dieser ziehe ich vom Vertex den Drehpunkt "manuell" ab und addiere ihn danach wieder - und siehe da, es funktioniert. :wink:

Ich weiß, ich bin ein schlechter Erklärer, also einfach nachfragen, wenn hier jemand was nicht versteht. :roll:

mrtrain


Zuletzt geändert von mrtrain am Mi Aug 31, 2011 19:39, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 14:49 
Offline
DGL Member

Registriert: Mi Jul 14, 2010 13:53
Beiträge: 6
Der Tipp von Traude funktioniert: Erst die Vertices berechnen und dann gewichten. Für den Fall, dass der Drehpunkt nicht der Ursprung ist, mache ich es so wie mrtrain geschrieben hat: Den Drehpunkt abziehen, drehen und dann wieder addieren.


Im neuen Shader sieht es jetzt folgendermaßen aus:

Code:
vec4 rotationPoint0 = vec4(matBone0[3]);
vec4 rotationPoint1 = vec4(matBone1[3]);
vec4 vecBone0 = matBone0 * (gl_Vertex - rotationPoint0);
vec4 vecBone1 = matBone1 * (gl_Vertex - rotationPoint1);
      
vec4 transformedVec = (vecBone0 + rotationPoint0) * weight0)
                    + (vecBone1 + rotationPoint1) * weight1);


Was ich aber noch nicht verstehe: Ich hätte erwartet, dass durch die Multiplikation mit den Bone-Matrixen die Vertices wieder zum Drehpunkt hin verschoben werden, da die Translation in den Matrixen enthalten ist?
Da dies aber nicht der Fall ist, addiere ich den Drehpunkt bei der Gewichtung einfach nochmal.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jul 16, 2010 16:09 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Zitat:
Ich hätte erwartet, dass durch die Multiplikation mit den Bone-Matrixen die Vertices wieder zum Drehpunkt hin verschoben werden, da die Translation in den Matrixen enthalten ist?

Sowohl gl_Vertex als auch rotationPoint0 sind vierdimensional, bei beiden steht eine Eins in der letzten Komponente. Diese beiden Einsen ziehst du von einander ab, das gibt eine Null. Wegen dieser Null wird die Translation nicht angewendet.

Also so müsste es gehen:
Code:
vec4 vecBone0 = matBone0 * (gl_Vertex - vec4(rotationPoint0.xyz, 0.0));

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jul 17, 2010 15:46 
Offline
DGL Member

Registriert: Mi Jul 14, 2010 13:53
Beiträge: 6
Richtig, danke sehr.
Jetzt werde ich noch dasselbe prozedere für die Normalen-Vektoren einfügen und dann sollte mein Bone-Animation-Vertexshader fertig sein.

Danke an alle für die aufschlussreichen Kommentare!


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 13 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 16 Queries | GZIP : On ]