Seite 1 von 1

UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 10:31
von mcq
Hallo allerseits!

Zuerst vorweg: hab versucht danach hier zu suchen - aber "UpdateSkinnedMesh" kommt angeblich zu häufig vor, nur finden tu ich es leider nicht...

Mein Problem: ich komme in Delphi mit Direct3D 9 mit den Basics ganz gut zurecht - aber: nun würd ich doch ganz gerne mal skinned Mesh Animationen erstellen - aber ich komme einfach nicht weiter.

Mein bisheriger Stand:

* erzeugen eines Meshs mit D3DXCreateMeshFVF
* füllen von VB und IB mittels der entsprechenden Get's und Lock's

Und nach diesem einmaligen Erstellen des Meshs möchte ich nun erstmal testweise EINMALIG versuchen, das Software-Skinning auszuführen. Hierzu klone ich das "mesh" zu einem "premesh", welches das nicht "deformierte" Objekt sein soll.
Hierzu bin ich so vorgegangen:

Premesh: record mit zahlreichen Daten

Code: Alles auswählen

var
   mesh, orgmesh: ID3DXMesh;
   skin_vertices: array[0..65535] of word;
   skin_weights: array[0..65535] of single;
   skin_trafos: array[0..1023] of TD3DXMatrix;
   pnt, pnt2: pointer;

---------------------------

            D3DXCreateSkinInfoFVF( premesh.num_vertices, mesh.GetFVF, length(premesh.weights) );
            mesh.CloneMeshFVF( mesh.GetOptions, mesh.GetFVF or D3DFVF_NORMAL, device, orgmesh );

            for i := 0 to high( premesh.weights ) do
                        begin
                                meshcontainer.skininfo.SetBoneName(i, pChar( premesh.weights[i].name ));
                                for j := 0 to high( premesh.weights[i].weights ) do
                                begin
                                        skin_vertices[j] := premesh.weights[i].vertices[j];
                                        skin_weights[j] := premesh.weights[i].weights[j];
                                end;
                                meshcontainer.skininfo.SetBoneInfluence( i, length(premesh.weights[i].weights), @skin_vertices, @skin_weights ;
                        end;

            orgmesh.LockVertexBuffer( D3DLOCK_READONLY, pnt );
            mesh.LockVertexBuffer( 0, pnt2 );

            // Füllen der Matrizen:

            skin_trafos[0] := D3DXMatrix(   1, 0, 0, 0,
                                                        0, 1, 0, 0,
                                                        0, 0, 1, 0,
                                                        0, 0, 0, 1 );

            skin_trafos[1] := D3DXMatrix(   1, 0, 0, 0,
                                                        0, 1, 0, 0,
                                                        0, 0, 1, 0,
                                                        0, 0, 0, 1 );

            meshcontainer.SkinInfo.UpdateSkinnedMesh( skin_trafos[0], skin_trafos[10], pnt, pnt2 );

            orgmesh.UnlockVertexBuffer;
            mesh.UnlockVertexBuffer;
So - also zunächst einmal scheinen einige Dinge an obigem Code etwas merkwürdig zu sein - zunächst einmal musste ich skin_vertices, _weights und _trafos als feste, große Arrays deklarieren, weil deren tatsächliche Anzahl schwankt, aber man ja einen pointer auf die "wohlgeordneten" Daten liefern soll. Dass das nicht elegant ist und vmtl. mit GetMem und Pointern besser geht, ist mir schon klar (oder?), aber es ist ja nur ein Test... zum zweiten ist mir nicht klar, was genau bei UpdateSkinnedMesh als Matrizen übergeben werden sollen - sind das Arrays oder nicht? Pointer oder nicht? Wozu genau dient die zweite Matrix? Das wird, finde ich, nur mäßig gut im SDK erklärt, sodass ich es nicht verstanden habe... dazu kommt, dass die d3dx9 Delphi Adaptation von Tim Baumgarten & Robert Fizimayer verlangt, dass ich da TD3DXMatrix-Variablen angebe, während das SDK dort Pointer verlangt, soweit meine C++-Kenntnisse reichen...

Und das Resultat des obigen Quellcodes: alles läuft - bis auf der entscheidende Befehl "UpdateSkinnedMesh"! Dort steigt die Direct3D-Dll mit einer AccessViolation aus...

:? :? :? HIIILLLLFFEEEE!!!! :o ;)

Also ihr seht schon - ich bewege mich in einem ziemlichen Irrgarten... es wär toll, wenn mir jemand a) Fehler im Quellcode zeigen oder b) Links zu Threads, die dieses Problem diskutieren, geben oder c) einfach nur irgend einen Tipp geben könntet, woran es grundsätzlich liegen könnte bzw. was ich die ganze Zeit übersehen habe (irgend eine Initialisierung von SkinInfo oder so...???), sodass ich vieleicht doch irgendwann das ganze hinkriege...!

VIELEN DANK!!!!!!

Marcel

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 12:51
von Dirk Schulz
Hi,

also mit Delphi-Programmierung kenn ich mich nicht so gut aus, vorallem nicht mit der DirectX-Version davon, aber das scheint ja recht ähnlich zur C++-Version zu sein.

Die UpdateSkinnedMesh-Funktion will als zweiten Parameter die inverse, transponierte Bone-Matrix haben (laut Doku).
Keine Ahnung, ob es die Funktionen auch unter DelphiDirectX gibt, aber das könntest du mit D3DXMatrixInverse und D3DXMatrixTranspose berechnen lassen.

Da deine Matrix aber eine EinheitsMatrix ist, sollte die inverse transponierte auch die Einheitmatrix sein.

Was mir aufgefallen ist, ist das du als zweiten Parameter skin_trafos[10] angegeben hast, diese aber garnicht initialisiert ist. Meintest du dort vielleicht skin_trafos[1] ?

Deine Matrizen sind vom Typ D3DXMatrix, du meintest als Parameter will die Funktion aber TD3DXMatrix haben ... ist das dasselbe, oder ist das ein Pointer auf eine D3DXMatrix? Zur Not versuch einfach mal, die Matrizen als Pointer anzugeben, schlechter als jetzt kanns ja nicht werden ;)

Dirk Schulz

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 13:11
von Zudomon
Wiso geht das mit dynamischen Arrays nicht?

Einfach die Arrays dynamisch deklarieren und wenn du einen Pointer auf die Daten geben sollst, dann mit:
@TestArray[0]
Also wichtig ist dabei, auf das erste Element des dynamischen Arrays zu zeigen.

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 13:35
von mcq
Also schonmal vielen Dank für eure Mühe, meinen Beitrag zu verstehen... ;-)

* TD3DX... ist einfach die "normale" Type, die heißt unter Delphi dann T... - also nicht der Pointer. Hab da aber auch schon alle Kombinationen durch.
* Die Matrizen: das mit [10] hab ich gemacht, weil ich nicht sicher war, ob man eventuell zwingenderweise unterschiedliche Bereiche bzw. Matrizen angeben muss, die sich also nicht überschneiden. Aber ich kann natürlich nochmal explizit die Inv/Transp.-Matrizen einbauen...
* das mit dynamischen Arrays: als ich anfangs mit der Belegung des VB/IB gespielt habe, hat das nie geklappt - aber ich werd es natürlich dann (WENN es läuft) auch wieder testen... jetzt aber erscheint mir diese Methode sicherer.

Also - habe ich keine GRUNDSÄTZLICHEN Fehler gemacht...? Meint ihr, der Fehler steckt wirklich irgendwo im Detail...?

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 14:08
von Dirk Schulz
Hi,

also du kannst als zweiten Parameter auch Null angeben, brauch man nur, wenn die Vertices zwei Positionen gespeichert haben.

Was mir aufgefallen ist, als ich deinen Code durchgesehen habe, ist dass du die D3DXCreateSkinInfoFVF aufrufst, aber nirgendwo ein Parameter angegeben ist, wo die skininfo denn gespeichert werden soll. Bei C++ wäre das ein vierter Parameter, wie ist das bei Delphi?

Kann ja sein, dass er noch keine ordentliche Referenz auf ne SkinInfo hat und dann bei der UpdateSkinnedMesh-Funktion aussteigt, ist aber nur ne Vermutung!

Dirk Schulz

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 17:45
von mcq
Hallo!

Nee, das war nur ein Abschreibefehler: eigentlich heißt das (auch bei mir und auch Fehler ausgebend): D3DXCreateSkinInfoFVF( premesh.num_vertices, mesh.GetFVF, length(premesh.weights) , meshcontainer.skininfo ), d.h. das letzte ist der Übergabeparameter.

Er akzeptiert ja auch alle anderen skininfo-Befehle wie den SetBoneInfluence-Befehl... Erst ganz am Ende beim Update-Befehl liefert er eine Access-Violation

Marcel

Edit: Immerhin scheine ich ja wohl keine grundsätzlichen Fehler gemacht haben - sehe ich das richtig?

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 27.05.2009, 19:58
von mcq
Statt der riesigen Arrays verwende ich jetzt Pointer, welche auf das erste Element zeigen aber genug Speicher für alle Elemente haben.

Das Ergebnis ist dasselbe: sobald der Update-Befehl aufgerufen wird: AccessViolation.

Jetzt wollte ich mal was anderes testen nämlich das IndexedSkinning - und interessanterweise: sobald ich auch nur den ersten wichtigen Befehl aufrufe, nämlich:
skinInfo.GetMaxFaceInfluences(ib, NumFaces, skinning_maxfaceinfluences )

...bekomme ich AUCH eine AccessViolation! Alle anderen Befehle macht er ja problemlos...

ib ist der Indexbuffer, den ich vorher mal gegettet habe (der ist aber hier NICHT gelockt!), NumFaces ist ne word und skinning_maxfaceinfluences ist ein word-pointer, den ich vorher auf NumFaces * sizeof(word) reserviert habe. Trotzdem: wieder ein Absturz!

Das bestärkt mich natürlich in dem Gefühl, dass ich irgendwie nicht richtig die skininfo initialisiert habe. Oder muss man was beim Mesh beachten? Irgendwelche Spezialitäten??

Achja: der "meshcontainer" war auch so ein Test - erst hab ich ihn gar nicht verwendet, sondern einfach die entsprechenden Variablen "so" gespeichert. Geht das auch? Oder braucht man zwingend den "Meshcontainer"? (er ist mir nämlich nicht wirklich recht, weil ich die meisten Inhalte schon anders speichere und das mir alles durcheinander bringen würde)

Re: UpdateSkinnedMesh liefert Access Violation??

Verfasst: 19.01.2010, 22:19
von mcq
Ich habe mich nach längerer Zeit mal wieder mit dem Thema beschäftigt... aber leider komme ich absolut nicht weiter! Es ist wie eine Mauer!

Ich bräuchte dringend Hilfe:

* ich WILL NICHT die X-Datei-Import-Funktion für Skinned Meshs verwenden (D3DXLoadMeshHierarchyFromX und Konsorten)
* ich WILL KEINE ANIMATION verwenden! Jedenfalls keine in der X-Datei gespeicherte mit Keyframes!

Ich will doch einfach nur ein Skinned Mesh erstellen - ganz per Hand und ohne Verwendung des X-Dateiformates... warum geht das nicht?!? :cry: :cry: :cry:

Das SDK gibt eine völlig unzureichende Dokumentation des Befehles, das Sample ist extrem allgemein erklärt. KENNT KEINER EIN TUTORIAL HIERZU?? EIN PAAR BROCKEN QUELLCODE??? KANN JA RUHIG C++ SEIN! NUR HAUPTSACHE IRGENDWAS!?

Hier nochmal die relevanten Quellcode-Brocken - "premesh" ist die Quelle meiner 3D-Daten inkl. Bone-Weights.

Code: Alles auswählen

                        meshcontainer.Name := 'Test';
                        meshcontainer.MeshData._Type := D3DXMESHTYPE_MESH;
                        meshcontainer.MeshData.ID3DXMesh := @mesh;
                        meshcontainer.Materials := nil;
                        meshcontainer.NumMaterials := 0;
                        meshcontainer.Adjacency := nil;

                        mesh.GetDeclaration( vertexdeclaration );
                        D3DXCreateSkinInfoFVF( premesh.num_vertices, mesh.GetFVF, length(premesh.weights) , meshcontainer.skininfo );

                        mesh.CloneMeshFVF( mesh.GetOptions, mesh.GetFVF, device, orgmesh );

                        for i := 0 to high( premesh.weights ) do
                        begin
                                meshcontainer.skininfo.SetBoneName(i, pChar( premesh.weights[i].name ));

                                // Anzahl der der Weights:

                                n := length( premesh.weights[i].weights );

                                // Speicher für skin_vertices und skin_weights reservieren:

                                GetMem( skin_vertices, sizeof(word) * n );
                                GetMem( skin_weights, sizeof(single) * n );

                                cursor_skin_vertices := skin_vertices;
                                cursor_skin_weights := skin_weights;

                                for j := 0 to n-1 do
                                begin
                                        cursor_skin_vertices^ := premesh.weights[i].vertices[j];
                                        cursor_skin_weights^ := premesh.weights[i].weights[j];
                                        inc(cursor_skin_vertices);
                                        inc(cursor_skin_weights);
                                end;
                                LOG_check3Dproc(meshcontainer.skininfo.SetBoneInfluence( i, length(premesh.weights[i].weights), @skin_vertices, @skin_weights ), 'Skinning: Zuweisen der Weights', 1 );

                                FreeMem( skin_vertices, sizeof(word) * n );
                                FreeMem( skin_weights, sizeof(single) * n );

                                skin_vertices := nil;
                                cursor_skin_vertices := nil;
                                skin_weights := nil;
                                cursor_skin_weights := nil;

                                LOG_check3Dproc(meshcontainer.skininfo.SetBoneOffsetMatrix( i,  D3DXMatrix(   1, 0, 0, 0,
                                                        0, 1, 0, 0,
                                                        0, 0, 1, 0,
                                                        0, 0, 0, 1 ) ), 'Skinning: Set Matrix', 1 );
                        end; 

                        orgmesh.LockVertexBuffer( D3DLOCK_READONLY, pnt );
                        mesh.LockVertexBuffer( 0, pnt2 );                  

                        // Füllen der Matrizen:

                        n := length(premesh.weights);

                        for i := 0 to n-1 do
                                skin_trafos[i] := D3DXMatrixIdentity;


                        meshcontainer.SkinInfo.UpdateSkinnedMesh( skin_trafos[0], skin_trafos[0], pnt, pnt2 );

                        orgmesh.UnlockVertexBuffer;
                        mesh.UnlockVertexBuffer;

Und beim Befehl "UpdateSkinnedMesh" wirft er mir eine Exception aus!!! WARUM??? Wie kann ich denn damit auf einen grünen Zweig kommen? Alle Welt verwendet skinned Meshs nur mir bleibt es verwehrt, das finde ich gemein! ;)