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

28.09.2014, 18:56

[Update] Skelettbasierte Animation funktioniert nicht...

EDIT: Problem teilweise gelöst, siehe Skelettbasierte Animation funktioniert nicht...

Hi,

ich weiß nicht genau, was mit der Animation nicht stimmt, aber irgendwie ist das Modell viel zu klein geworden und die Hosen sind riesig und falsch positioniert, außerdem stimmt auch der Rest nicht. Irgendetwas ist mit den Matrizen in der AnimatedModel::Animate()-Funktion falsch (zumindest sieht das aus wie ein Mensch, wenn ich aus denen Einheitsmatrizen mache), aber ich weiß nicht, was. Und die FBX-SDK-Dokumentation ist scheiße und ich weiß nicht, ob ich das, was da alles nicht erklärt ist, richtig verstanden habe. Wahrscheinlich nicht, weil ja nichts erklärt ist.

So sieht das aktuell aus:
Screenshot (11,9 MB)

animatedmodel.cpp:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void AnimatedModel::Animate(){
    if (FrameCount == Animations[0].KeyFrameCount){
        FrameCount = 0;
    }
    XMMATRIX rotateMatrixX, rotateMatrixY, rotateMatrixZ, translationMatrix, finalMatrix, scaleMatrix;
    int i;
    for (i = 0; i < BoneCount; i++){
        scaleMatrix = XMMatrixScaling(Animations[0].KeyFrameArray[i][FrameCount].Scale.x, Animations[0].KeyFrameArray[i][FrameCount].Scale.y, Animations[0].KeyFrameArray[i][FrameCount].Scale.z);

        rotateMatrixX = XMMatrixRotationX(Animations[0].KeyFrameArray[i][FrameCount].Rotate.x / 180.0f*M_PI);
        rotateMatrixY = XMMatrixRotationY(Animations[0].KeyFrameArray[i][FrameCount].Rotate.y / 180.0f*M_PI);
        rotateMatrixZ = XMMatrixRotationZ(Animations[0].KeyFrameArray[i][FrameCount].Rotate.z / 180.0f*M_PI);


        translationMatrix = XMMatrixTranslation(Animations[0].KeyFrameArray[i][FrameCount].Translate.x, Animations[0].KeyFrameArray[i][FrameCount].Translate.y, Animations[0].KeyFrameArray[i][FrameCount].Translate.z);

        finalMatrix = XMMatrixMultiply(scaleMatrix, rotateMatrixX);
        finalMatrix = XMMatrixMultiply(finalMatrix, rotateMatrixY);
        finalMatrix = XMMatrixMultiply(finalMatrix, rotateMatrixZ);
        finalMatrix = XMMatrixMultiply(finalMatrix, translationMatrix);
        finalMatrix = XMMatrixMultiply(BoneArray[i].GlobalBindposeInverse, finalMatrix);
        finalMatrix = XMMatrixTranspose(finalMatrix);

        XMStoreFloat4x4(&(BoneMatrixArray[0].Bonematrix[i]), finalMatrix);
        
        
        
    }


    FrameCount++;
}


fbxloader.h:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef _FBXLOADER_H_
#define _FBXLOADER_H_

#include <windows.h>
#include <fbxsdk.h>
#include "d3dclass.h"


#pragma comment(lib,"libfbxsdk-md.lib")

#define INDEX_ARRAY_SIZE 12582912 // max 4194304 (2^22) triangles
#define VERTEX_ARRAY_SIZE INDEX_ARRAY_SIZE //vertex count is always <= index count

class FbxLoader{
public:
    struct VertexType{
        XMFLOAT3 Position;
        XMFLOAT3 Normal;
        XMFLOAT2 Texture;
        float Weights[4];
        unsigned int BoneIDs[4];
    };

    struct KeyFrameType{
        int FrameNumber;
        XMFLOAT3 Rotate, Scale, Translate;
        XMFLOAT4X4 GlobalTransform;
    };

    struct AnimationType{
        char* Name;
        KeyFrameType* KeyFrameArray;
        int KeyFrameArrayCount;
    };


    struct BoneType{
        BoneType** Children;
        int ChildCount, ID;
        unsigned long long UniqueID;
        char* Name;
        AnimationType* AnimationArray;
        FbxAMatrix GlobalBindposeInverse;
    };

    
    struct ReturnType{
        VertexType** VertexArray; //array of pointers to vertex arrays
        int VertexArrayCount; // count of vertex and index arrays
        unsigned int* VertexCountArray; // array of vertex counts of vertex arrays
        unsigned int** IndexArray; //array of pointers to arrays of indices
        unsigned int* IndexCountArray; //array of index counts
        BoneType* RootBone;
        FbxNode** MeshArray;
        int AnimationCount, BoneCount;
    };

    struct WeightType{
        float Weights[4];
        unsigned int BoneID[4];
        int CurrID;
    };

    static void Initialize();

    static bool LoadModel(char* FileName, ReturnType* Result);
    static void EndLoading();

private:

    static void BeginLoading();
    static void ProcessNode(FbxNode* Node, ReturnType* Result);
    static void ProcessMesh(FbxNode* Node, ReturnType* Result);

    static void FindFirstSkeletonNode(FbxNode* Node, ReturnType* Result);
    static void ProcessSkeleton(FbxNode* Node, ReturnType* Result, BoneType** Bone);

    static void CopyToNewString(char** Dest, const char* Src);

    static FbxAMatrix GetGeometryTransformation(FbxNode* Node);

    static void ProcessBonesAndAnimations(FbxNode* Node, FbxScene* Scene, ReturnType* Result);

    static BoneType* FindBoneByID(unsigned long long ID, ReturnType* Result);
    static WeightType* GetWeightArray(FbxNode* Node, ReturnType* Result);

    static void SetWeight(WeightType* WeightPtr, float Weight, int BoneID);

    //static void LoadAnimations(FbxScene* Scene, ReturnType* Result);

    static FbxManager* SdkManager;
    static unsigned int* IndexArray;
    static VertexType* vertices;
    static int BoneCount;
    static WeightType** WeightArray;
};

#endif


fbxloader.cpp:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
#include "fbxloader.h"
#include "macros.h"

#include <queue>

FbxManager* FbxLoader::SdkManager;
unsigned int* FbxLoader::IndexArray;
FbxLoader::VertexType* FbxLoader::vertices;
FbxLoader::WeightType** FbxLoader::WeightArray;

void FbxLoader::Initialize(){
    SdkManager = 0;
    IndexArray = 0;
    vertices = 0;
    WeightArray = 0;
}

void FbxLoader::BeginLoading(){
    if (!SdkManager){
        SdkManager = FbxManager::Create();
        FbxIOSettings *ios = FbxIOSettings::Create(SdkManager, IOSROOT);
        SdkManager->SetIOSettings(ios);
    }
    if (!IndexArray){
        IndexArray = new unsigned int[INDEX_ARRAY_SIZE];
    }
    if (!vertices){
        vertices = new VertexType[VERTEX_ARRAY_SIZE];
    }
    
}

bool FbxLoader::LoadModel(char* FileName, ReturnType* Result){
    
    if (Result==0){
        return false;
    }

    BeginLoading();

    Result->VertexArrayCount = 0;

    Result->AnimationCount = 0;

    
    Result->BoneCount = 0;
    

    FbxIOSettings *ios = FbxIOSettings::Create(SdkManager, IOSROOT);
    SdkManager->SetIOSettings(ios);

    FbxImporter* Importer = FbxImporter::Create(SdkManager, "");

    if (!Importer->Initialize(FileName, -1, SdkManager->GetIOSettings())) {
        return false;
    }

    FbxScene* Scene = FbxScene::Create(SdkManager, "myScene");

    Importer->Import(Scene);

    Importer->Destroy();

    FbxNode* Node=Scene->GetRootNode();

    int NodeCount = Scene->GetNodeCount();

    if (NodeCount == 0){
        Scene->Destroy();
        return false;
    }

    Result->IndexCountArray = new unsigned int[NodeCount];
    Result->VertexCountArray = new unsigned int[NodeCount];
    
    Result->MeshArray = new FbxNode*[NodeCount];
    memset(Result->MeshArray, 0, sizeof(FbxNode*)*NodeCount);
    
    Result->IndexArray = new unsigned int*[NodeCount];
    Result->VertexArray = new VertexType*[NodeCount];

    
    WeightArray = new WeightType*[NodeCount];
    memset(WeightArray, 0, sizeof(WeightType*)*NodeCount);

    FindFirstSkeletonNode(Node, Result);

    int MeshCount = 0;

    std::queue<FbxNode*> NodeQueue;

    FbxNode* CurrNode = Node;

    while (CurrNode){

        FbxNodeAttribute* Attribute = CurrNode->GetNodeAttribute();
        if (Attribute){
            if (Attribute->GetAttributeType() == FbxNodeAttribute::EType::eMesh){
                Result->MeshArray[MeshCount] = CurrNode;
                WeightArray[MeshCount] = new WeightType[CurrNode->GetMesh()->GetControlPointsCount()];
                memset(WeightArray[MeshCount], 0, sizeof(WeightType)*CurrNode->GetMesh()->GetControlPointsCount());
                MeshCount++;
            }
        }

        int j, ChildCount = CurrNode->GetChildCount();
        for (j = 0; j < ChildCount; j++){
            NodeQueue.push(CurrNode->GetChild(j));
        }
        if (!NodeQueue.empty()){
            CurrNode = NodeQueue.front();
            NodeQueue.pop();
        }
        else{
            CurrNode = 0;
        }

    }


    

    int i;
    for (i = 0; i < MeshCount; i++){
        ProcessBonesAndAnimations(Result->MeshArray[i], Scene, Result);
    }

    Result->VertexArrayCount = 0;
    ProcessNode(Node, Result);

    

    
    
    for (i = 0; i < NodeCount; i++){
        SAFE_ARRAY_DELETE(WeightArray[i]);
    }

    SAFE_ARRAY_DELETE(WeightArray);

    Scene->Destroy();

    

    return true;
    
}

void FbxLoader::ProcessNode(FbxNode* Node, ReturnType* Result){
    if (!Node){
        return;
    }

    //Processing all child nodes
    int i, ChildCount = Node->GetChildCount();
    for (i = 0; i < ChildCount; i++){
        ProcessNode(Node->GetChild(i), Result);
    }


    FbxNodeAttribute* Attribute = Node->GetNodeAttribute();
    if (!Attribute){
        return;
    }

    FbxNodeAttribute::EType Type = Attribute->GetAttributeType();

    switch (Type){
    case FbxNodeAttribute::EType::eMesh:
        ProcessMesh(Node, Result);
        break;

    default:
        break;
    }

}

void FbxLoader::FindFirstSkeletonNode(FbxNode* Node, ReturnType* Result){
    if (!Node){
        return;
    }

    FbxNodeAttribute* Attribute = Node->GetNodeAttribute();
    if (!Attribute){


        //Processing all child nodes
        int i, ChildCount = Node->GetChildCount();
        for (i = 0; i < ChildCount; i++){
            FindFirstSkeletonNode(Node->GetChild(i), Result);
        }
    }
    else{
        FbxNodeAttribute::EType Type = Attribute->GetAttributeType();

        if (Type == FbxNodeAttribute::EType::eSkeleton){
            ProcessSkeleton(Node, Result,&Result->RootBone);
        }
        else{
            int i, ChildCount = Node->GetChildCount();
            for (i = 0; i < ChildCount; i++){
                FindFirstSkeletonNode(Node->GetChild(i), Result);
            }
        }
    }
}


void FbxLoader::ProcessMesh(FbxNode* Node, ReturnType* Result){
        int i, j, PolygonSize;
    int index=0;
    if (!Node){
        return;
    }

    FbxMesh* Mesh = Node->GetMesh();
    WeightType* Weights = GetWeightArray(Node, Result);
    if (!Mesh){
        return;
    }
    int ControlPointCount = Mesh->GetControlPointsCount();
    int PolygonCount = Mesh->GetPolygonCount();


    FbxGeometryElementNormal* Normal;
    FbxGeometryElementUV* UV;
    int index0, VertexCounter=0, ControlPointIndex;

    int* VertexUsedArray = new int[ControlPointCount];
    memset(VertexUsedArray, 0, sizeof(int)*ControlPointCount);


    FbxVector4* ControlPoints = Mesh->GetControlPoints();
    
    for (i = 0; i < PolygonCount; i++){ //TBD concave polygons
        PolygonSize = Mesh->GetPolygonSize(i)-1;
        for (j = 1; j < PolygonSize; j++){ //only works for convex polygons and some concave polygons
            if (index == INDEX_ARRAY_SIZE){
                goto IndexLoadingEnded;
            }
            IndexArray[index] = VertexCounter;
            index++;
            IndexArray[index] = VertexCounter + j;
            index++;
            IndexArray[index] = VertexCounter + j + 1;
            index++;
        }
        for (j = 0; j <= PolygonSize; j++){
            ControlPointIndex = Mesh->GetPolygonVertex(i, j);
            vertices[VertexCounter].Position.x = static_cast<float>(ControlPoints[ControlPointIndex].mData[0]);
            vertices[VertexCounter].Position.y = static_cast<float>(ControlPoints[ControlPointIndex].mData[1]);
            vertices[VertexCounter].Position.z = static_cast<float>(ControlPoints[ControlPointIndex].mData[2]);
            
            memcpy(vertices[VertexCounter].Weights, Weights[ControlPointIndex].Weights, sizeof(float) * 4);
            memcpy(vertices[VertexCounter].BoneIDs, Weights[ControlPointIndex].BoneID, sizeof(unsigned int) * 4);

            ///////////////////////
            /// LOADING NORMALS ///
            ///////////////////////

            Normal = Mesh->GetElementNormal(0);
            if (Normal){

                switch (Normal->GetMappingMode())
                {
                case FbxGeometryElement::eByControlPoint:
                    switch (Normal->GetReferenceMode())
                    {
                    case FbxGeometryElement::eDirect:
                    {
                        vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(ControlPointIndex).mData[0]);
                        vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(ControlPointIndex).mData[1]);
                        vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(ControlPointIndex).mData[2]);
                    }
                        break;

                    case FbxGeometryElement::eIndexToDirect:
                    {
                        index0 = Normal->GetIndexArray().GetAt(ControlPointIndex);
                        vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[0]);
                        vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[1]);
                        vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[2]);
                    }
                        break;

                    default:
                        break; //TBD error
                    }
                    break;

                case FbxGeometryElement::eByPolygonVertex:
                    switch (Normal->GetReferenceMode())
                    {
                    case FbxGeometryElement::eDirect:
                    {
                        vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(VertexCounter).mData[0]);
                        vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(VertexCounter).mData[1]);
                        vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(VertexCounter).mData[2]);
                    }
                        break;

                    case FbxGeometryElement::eIndexToDirect:
                    {
                        index0 = Normal->GetIndexArray().GetAt(VertexCounter);
                        vertices[VertexCounter].Normal.x = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[0]);
                        vertices[VertexCounter].Normal.y = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[1]);
                        vertices[VertexCounter].Normal.z = static_cast<float>(Normal->GetDirectArray().GetAt(index0).mData[2]);
                    }
                        break;

                    default:
                        break; //TBD error
                    }
                    break;
                }
            }
            else{
                vertices[VertexCounter].Normal = XMFLOAT3(0.0f, 0.0f, 0.0f);

            }

            //////////////////////////////
            /// LOADING TEXTURE COORDS ///
            //////////////////////////////

            UV = Mesh->GetElementUV(0);
            if (UV){

                switch (UV->GetMappingMode())
                {
                case FbxGeometryElement::eByControlPoint:
                    switch (UV->GetReferenceMode())
                    {
                    case FbxGeometryElement::eDirect:
                    {
                        vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(ControlPointIndex).mData[0]);
                        vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(ControlPointIndex).mData[1]);
                    }
                        break;

                    case FbxGeometryElement::eIndexToDirect:
                    {
                        index0 = UV->GetIndexArray().GetAt(ControlPointIndex);
                        vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[0]);
                        vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[1]);
                    }
                        break;

                    default:
                        break; //TBD error
                    }
                    break;

                case FbxGeometryElement::eByPolygonVertex:
                    switch (UV->GetReferenceMode())
                    {
                    case FbxGeometryElement::eDirect:
                    {
                        vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(VertexCounter).mData[0]);
                        vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(VertexCounter).mData[1]);
                    }
                        break;

                    case FbxGeometryElement::eIndexToDirect:
                    {
                        index0 = UV->GetIndexArray().GetAt(VertexCounter);
                        vertices[VertexCounter].Texture.x = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[0]);
                        vertices[VertexCounter].Texture.y = static_cast<float>(UV->GetDirectArray().GetAt(index0).mData[1]);
                    }
                        break;

                    default:
                        break; //TBD error
                    }
                    break;
                }
            }
            else{
                vertices[VertexCounter].Texture = XMFLOAT2(0.0f, 0.0f);

            }





            VertexCounter++;
        }
    }

    IndexLoadingEnded:
    
    
    Result->IndexArray[Result->VertexArrayCount] = new unsigned int[index]; //index is now the count of indices
    memcpy(Result->IndexArray[Result->VertexArrayCount], IndexArray, sizeof(unsigned int)*index);
    
    Result->VertexArray[Result->VertexArrayCount] = new VertexType[VertexCounter];
    memcpy(Result->VertexArray[Result->VertexArrayCount], vertices, sizeof(VertexType)*VertexCounter);

    Result->IndexCountArray[Result->VertexArrayCount] = index;
    Result->VertexCountArray[Result->VertexArrayCount] = VertexCounter;

    SAFE_ARRAY_DELETE(VertexUsedArray)

    Result->VertexArrayCount++;

}


void FbxLoader::EndLoading(){

    if (SdkManager){
        SdkManager->Destroy();
    }
    SAFE_ARRAY_DELETE(IndexArray)
    SAFE_ARRAY_DELETE(vertices)
}



void FbxLoader::ProcessSkeleton(FbxNode* Node, ReturnType* Result, BoneType** Bone){
    
    FbxSkeleton* Skeleton=Node->GetSkeleton();
    if (!Skeleton){
        *Bone = 0;
        return;
    }
    const char* Name=Skeleton->GetInitialName();
    *Bone = new BoneType;
    
    (*Bone)->UniqueID = Node->GetUniqueID();
    (*Bone)->AnimationArray = 0;
    CopyToNewString(&((*Bone)->Name), Name);


    
    int i, ChildCount = Node->GetChildCount();
    if (ChildCount != 0){
        (*Bone)->Children = new BoneType*[ChildCount];
        for (i = 0; i < ChildCount; i++){
            ProcessSkeleton(Node->GetChild(i), Result, &((*Bone)->Children[i]));
        }
    }
    else{
        (*Bone)->Children = 0;
    }
    (*Bone)->ChildCount = ChildCount;
    (*Bone)->ID = Result->BoneCount;
    Result->BoneCount++;
}

FbxAMatrix FbxLoader::GetGeometryTransformation(FbxNode* Node)
{
    if (!Node)
    {
        throw std::exception("Null for mesh geometry");
    }

    const FbxVector4 lT = Node->GetGeometricTranslation(FbxNode::eSourcePivot);
    const FbxVector4 lR = Node->GetGeometricRotation(FbxNode::eSourcePivot);
    const FbxVector4 lS = Node->GetGeometricScaling(FbxNode::eSourcePivot);

    return FbxAMatrix(lT, lR, lS);
}


void FbxLoader::ProcessBonesAndAnimations(FbxNode* Node, FbxScene* Scene, ReturnType* Result)
{
    int AnimStackCount = Scene->GetSrcObjectCount<FbxAnimStack>();
    Result->AnimationCount = AnimStackCount;

    FbxMesh* currMesh = Node->GetMesh();
    unsigned int numOfDeformers = currMesh->GetDeformerCount();
    
    FbxAMatrix geometryTransform = FbxLoader::GetGeometryTransformation(Node);

    WeightType* Weights = GetWeightArray(Node, Result);

    
    for (unsigned int deformerIndex = 0; deformerIndex < numOfDeformers; ++deformerIndex)
    {
        
        FbxSkin* currSkin = reinterpret_cast<FbxSkin*>(currMesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
        if (!currSkin)
        {
            continue;
        }

        unsigned int numOfClusters = currSkin->GetClusterCount();
        for (unsigned int clusterIndex = 0; clusterIndex < numOfClusters; clusterIndex++)
        {
            FbxCluster* currCluster = currSkin->GetCluster(clusterIndex);   
            BoneType* currBone = FindBoneByID(currCluster->GetLink()->GetUniqueID(), Result);
            FbxAMatrix transformMatrix;
            FbxAMatrix transformLinkMatrix;
            FbxAMatrix globalBindposeInverseMatrix;

            currCluster->GetTransformMatrix(transformMatrix);   // The transformation of the mesh at binding time
            currCluster->GetTransformLinkMatrix(transformLinkMatrix);   // The transformation of the cluster(joint) at binding time from joint space to world space
            globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;

            
            currBone->GlobalBindposeInverse = globalBindposeInverseMatrix;


            
            unsigned int numOfIndices = currCluster->GetControlPointIndicesCount();
            int* ControlPointIndices = currCluster->GetControlPointIndices();
            for (unsigned int i = 0; i < numOfIndices; ++i)
            {

                SetWeight(&(Weights[ControlPointIndices[i]]), currCluster->GetControlPointWeights()[i], currBone->ID);
            }

            if (!currBone->AnimationArray){
                currBone->AnimationArray = new AnimationType[AnimStackCount];
            }

            for (int i = 0; i < AnimStackCount; i++)
            {


                FbxAnimStack* lAnimStack = Scene->GetSrcObject<FbxAnimStack>(i);


                FbxTakeInfo* takeInfo = Scene->GetTakeInfo(lAnimStack->GetName());
                FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
                FbxTime end = takeInfo->mLocalTimeSpan.GetStop();




                FbxLongLong AnimationLength = end.GetFrameCount(FbxTime::eFrames24) - start.GetFrameCount(FbxTime::eFrames24) + 1;
                currBone->AnimationArray[i].KeyFrameArrayCount = AnimationLength;
                currBone->AnimationArray[i].KeyFrameArray = new KeyFrameType[AnimationLength];
                CopyToNewString(&(currBone->AnimationArray[i].Name), lAnimStack->GetName());

                int k = 0;
                for (FbxLongLong j = start.GetFrameCount(FbxTime::eFrames24); j <= end.GetFrameCount(FbxTime::eFrames24); j++)
                {
                    FbxTime currTime;
                    currTime.SetFrame(j, FbxTime::eFrames24);

                    currBone->AnimationArray[i].KeyFrameArray[k].FrameNumber = k;

                    FbxVector4 Rotate, Scale, Translate;
                    
                    FbxAMatrix currentTransformOffset = Node->EvaluateGlobalTransform(currTime) * GetGeometryTransformation(Node);
                    FbxAMatrix GlobalTransform = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(currTime);
                    
                    Rotate = GlobalTransform.GetR();
                    
                    currBone->AnimationArray[i].KeyFrameArray[k].Rotate.x = -Rotate.mData[0];
                    currBone->AnimationArray[i].KeyFrameArray[k].Rotate.y = -Rotate.mData[1];
                    currBone->AnimationArray[i].KeyFrameArray[k].Rotate.z = Rotate.mData[2];
                    
                    Scale = GlobalTransform.GetS();
                    
                    currBone->AnimationArray[i].KeyFrameArray[k].Scale.x = Scale.mData[0];
                    currBone->AnimationArray[i].KeyFrameArray[k].Scale.y = Scale.mData[1];
                    currBone->AnimationArray[i].KeyFrameArray[k].Scale.z = Scale.mData[2];

                    Translate = GlobalTransform.GetT();
                    
                    currBone->AnimationArray[i].KeyFrameArray[k].Translate.x = Translate.mData[0];
                    currBone->AnimationArray[i].KeyFrameArray[k].Translate.y = Translate.mData[1];
                    currBone->AnimationArray[i].KeyFrameArray[k].Translate.z = -Translate.mData[2];

                    currBone->AnimationArray[i].KeyFrameArray[k].GlobalTransform=XMFLOAT4X4(
                        GlobalTransform.mData[0].mData[0], GlobalTransform.mData[1].mData[0], GlobalTransform.mData[2].mData[0], GlobalTransform.mData[3].mData[0],
                        GlobalTransform.mData[0].mData[1], GlobalTransform.mData[1].mData[1], GlobalTransform.mData[2].mData[1], GlobalTransform.mData[3].mData[1],
                        GlobalTransform.mData[0].mData[2], GlobalTransform.mData[1].mData[2], GlobalTransform.mData[2].mData[2], GlobalTransform.mData[3].mData[2],
                        GlobalTransform.mData[0].mData[3], GlobalTransform.mData[1].mData[3], GlobalTransform.mData[2].mData[3], GlobalTransform.mData[3].mData[3]);

                    k++;
                }
            }
        }
    }

    
}




void FbxLoader::CopyToNewString(char** Dest, const char* Src){
    if (Src == 0){
        *Dest = 0;
        return;
    }
    *Dest = new char[strlen(Src) + 1];
    memcpy(*Dest, Src, strlen(Src) + 1);
}



FbxLoader::BoneType* FbxLoader::FindBoneByID(unsigned long long ID, ReturnType* Result){
    
    BoneType* tempBone = Result->RootBone;
    std::queue < BoneType* > BoneQueue;

    while (tempBone){

        if (ID==tempBone->UniqueID){
            return tempBone;
        }


        for (int i = 0; i < tempBone->ChildCount; i++)
        {
            BoneQueue.push(tempBone->Children[i]);
        }

        if (BoneQueue.size() > 0)
        {
            tempBone = BoneQueue.front();
            BoneQueue.pop();
        }
        else
        {
            tempBone = NULL;
        }


    }
    return 0;
}


FbxLoader::WeightType* FbxLoader::GetWeightArray(FbxNode* Node, ReturnType* Result){
    //assuming that count of meshes is smaller than count of nodes
    int i=0;
    while (Result->MeshArray[i]){
        if (Result->MeshArray[i] == Node){
            return WeightArray[i];
        }
        i++;
    }
    return 0;
}

void FbxLoader::SetWeight(WeightType* WeightPtr, float Weight, int BoneID){
    if (WeightPtr->CurrID > 3){
        return;
    }
    WeightPtr->Weights[WeightPtr->CurrID] = Weight;
    WeightPtr->BoneID[WeightPtr->CurrID] = BoneID;
}

animatedmodel.vs:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
////////////////////////////////////////////////////////////////////////////////
// Filename: model.vs
////////////////////////////////////////////////////////////////////////////////


struct BoneMatrixType{
    matrix BoneMatrix[64];
};


cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

cbuffer BoneMatrixBuffer{
    BoneMatrixType BoneMatrices[16];
};



struct VertexInputType
{
    float4 position : POSITION;
    float4 normal : NORMAL;
    float2 tex : TEXCOORD;
    float4 boneWeights : BONEWEIGHT;
    uint4 boneIDs : BONEID;
    uint instanceID : SV_InstanceID;
    row_major matrix instanceWorld : WORLD;
    row_major matrix instanceRotate : ROTATE;
    float alpha : ALPHA;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float3 normal : NORMAL;
    float4 worldPosition: WORLDPOSITION;
    float2 tex : TEXCOORD0;
    float alpha : ALPHA;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType AnimatedModelVertexShader(VertexInputType input)
{
    PixelInputType output;
    

    // Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;
    input.normal.w=0.0f;

    float4 positions[4];

    
    positions[0]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.x]);
    positions[1]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.y]);
    positions[2]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.z]);
    positions[3]=mul(input.position,BoneMatrices[input.instanceID%16].BoneMatrix[input.boneIDs.w]);
    

    if(input.boneWeights.x!=0.0f || input.boneWeights.y!=0.0f || input.boneWeights.z!=0.0f || input.boneWeights.w!=0.0f){
        output.position=input.boneWeights.x*positions[0] + input.boneWeights.y*positions[1] + input.boneWeights.z*positions[2] + input.boneWeights.w*positions[3];
    }
    else{
        output.position=input.position;
    }
    // Calculate the position of the vertex against the world, view, and projection matrices.
    
    output.position = mul(output.position, input.instanceWorld);
    output.worldPosition=output.position;
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
    
    output.alpha=input.alpha;

    output.normal=normalize(mul(input.normal,input.instanceRotate).xyz);

    output.tex=input.tex;
    
    return output;
}

Was zur Hölle ist falsch mit den Animationen, abgesehen davon, dass sie aktuell noch nicht in der richtigen Geschwindigkeit abgespielt werden, wenn man nicht gerade nur 24 FPS hat (das kann ich immer noch implementieren, wenn die erstmal überhaupt richtig dargestellt werden)?

Wie kann ich die Größe und Position der Kleidung anpassen? Irgendetwas Wichtiges muss ich da wohl übersehen haben oder nicht in der SDK-Dokumentation gefunden haben...

Ich weiß auch nicht, ob der FbxLoader korrekt ist, in der Dokumentation zum FBX SDK ist ja praktisch nichts erklärt...

Ich weiß nicht mehr, wo ich noch nach Fehlern suchen sollte oder wie ich eine Lösung finden kann, deswegen hoffe ich, dass sich hier jemand damit auskennt.

Grüße,
Magogan

Edit: Ich hab "funktioniert" ernsthaft mit c geschrieben Oo
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »Magogan« (26.10.2014, 18:39)


CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

2

28.09.2014, 22:15

Hallo Magogan,

vielleicht wäre es hilfreich, wenn du deinen Quellcode kommentiertst und mal ein wenig erklärst, was der machen soll. Außerdem ist es glaube ich besser, wenn du nur den Teil des Codes postest, der relevant ist, bzw. wenn du das nicht weiß, den Teil, der das Skelett verändert oder die Objekte positioniert, denn da muss ja mit der Fehlersuche angefangen werden! Ich und die anderen Forenmitglieder haben, denke ich, jetzt keinen Bock den gesamten Code x-Mal durchzulesen um ihn dann doch nicht zu verstehen! Vielleicht hast du ja auch schon ein wenig Fehlersuche betrieben und kannst uns mitteilen, was du versucht hast oder was du für Vermutungen hast, was falsch laufen könnte - unabhängig davon, ob du eine Lösung dafür hast.

Desweiteren wäre es hilfreich, wenn du dein Bild beschreibst und erklärst, was darauf genau zu sehen ist (was ist zum Beispiel dieser weiße Ring im Hindergrund).
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

3

28.09.2014, 22:32

Der weiße Ring im Hintergrund ist eigentlich weder Ring noch im Hintergrund, sondern die Hose des Models und im Vordergrund... Und ich hab absolut keine Ahnung, wieso die erstens zu groß, zweitens an der falschen Position und drittens auch noch falsch ausgerichtet ist... Die ist auch keinem Knochen zugeordnet, sonst würde sie mit dem Modell transformiert werden und irgendwo sein...

Das Problem ist, dass ich keine Ahnung habe, ob ich die Vertizen, Vertexe oder was auch immer davon die Mehrzahl ist, korrekt aus der FBX-Datei lade oder ob den Vertizen nicht noch mehr Attribute (Transformation etc.) zugeordnet sind, die ich nicht bedacht habe. Ebenso hab ich vermutlich irgendetwas beim Laden der Animationen vergessen. Dazu kommt, dass das Koordinatensystem nicht mit dem aus Direct3D übereinstimmt und das Modell standardmäßig auf dem Bauch liegt...
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

FSA

Community-Fossil

  • Private Nachricht senden

4

28.09.2014, 22:53

Hatte mit soetwas ähnlichem auch ziemlich Probleme. Das hier bedacht: ?
http://download.autodesk.com/us/fbx/2011…cNumber=d0e7429

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

5

28.09.2014, 23:56

Systematisches testen ist oft hilfreich:

- Such dir ein 3D Modelling Tool, mit dem du FBX-Dateien exportieren willst. Zum Beispiel Blender, oder eben irgend ein anderes.
- Teste ob das Exportieren wirklich funktioniert. Lade dir verschiedene FBX-Viewer (es gibt sogar einen offiziellen) herunter und schau ob das Modell und die Animation auch wirklich funktioniert.
- baue ein einfaches Testmodell. Kein Mensch. Vielleicht einfach ein Mesh mit 2 Knochen und die Animation besteht aus einer simplen Rotation des Knochens. Baue das Mesh unbedingt so, dass du siehst, ob es sich um die richtige Achse dreht.
- teste auch so Dinge wie die Größe. Wenn du ein Lowpoly-Mesh hast (z.B. 2 Dreiecke) kannst du sogar die Koordinaten einzelner Punkte überprüfen und sehen, ob sie an der Richtigen Stelle sind.
- Visualisiere das Skelett. Ich hatte manchmal das Problem, dass das Skelett richtig animiert war, die Vertex-Weights aber falsch waren. In diesem Fall will man wissen, dass die Matrizen Stimmen und man nur noch die Vertexe untersuchen muss.
- Bau nach und nach kompliziertere Modelle und teste immer mehr Features aus. Komplexere Bonehierarchien, fortgeschrittene Animationstechniken (mit Constraints und so), bis du alles hast, was du benutzen willst.

Animationen sind halt schwierig und nervig und du wirst einfach viel testen müssen. Und manchmal auch einfach für ne Woche aufgeben und dich später nochmal damit befassen. Aber du wirst den Großteil alleine machen müssen, da kein Mensch bei so viel Code und so einem komplexen Thema direkt sehen kann, was falsch ist (ok, außer es ist ein sehr offensichtlicher Fehler). Es geht also nichts über ausführliche Tests, die ganz unten anfangen.
Lieber dumm fragen, als dumm bleiben!

6

29.09.2014, 07:04

Zuerst die Verschiebung und dann die Rotation... Ja da soll man drauf kommen Oo Das werde ich mal testen, vielleicht hilft das. Und das mit der Matrix vom Parent Node auch.

So wirklich schlau werde ich aus dem Beispielprogramm vom SDK auch noch nicht... Also das zum Darstellen des Modells. Mal abgesehen davon, dass ich es nicht einmal kompilieren kann, weil immer irgendetwas fehlt (unter anderem die Projektdatei) und ich gerade zu faul bin xD

Immerhin hab ich jetzt ein paar Körperteile, aber die sind noch ineinander...
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Magogan« (29.09.2014, 14:54)


7

29.09.2014, 14:17

Also, die Körperteile werden jetzt vermutlich korrekt dargestellt, abgesehen von der Tatsache, dass sie sich alle im Nullpunkt des Modells befinden.

Das Modell steht Kopf (warum auch immer), aber immerhin ist die Hose schon an der richtigen Position (wenn man das Modell umdrehen würde). Hab jetzt eine GlobalTransformMatrix für jeden Mesh (Vertex-Buffer) hinzugefügt und diese im Shader berücksichtigt.

Diese Funktion wird für jeden Mesh aufgerufen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
void FbxLoader::ProcessBonesAndAnimations(FbxNode* Node, FbxScene* Scene, ReturnType* Result)
{
    int AnimStackCount = Scene->GetSrcObjectCount<FbxAnimStack>();
    Result->AnimationCount = AnimStackCount;

    FbxMesh* currMesh = Node->GetMesh();
    unsigned int numOfDeformers = currMesh->GetDeformerCount();
    
    FbxAMatrix geometryTransform = FbxLoader::GetGeometryTransformation(Node);

    WeightType* Weights = GetWeightArray(Node, Result);

    
    for (unsigned int deformerIndex = 0; deformerIndex < numOfDeformers; ++deformerIndex)
    {
        
        FbxSkin* currSkin = reinterpret_cast<FbxSkin*>(currMesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
        if (!currSkin)
        {
            continue;
        }

        unsigned int numOfClusters = currSkin->GetClusterCount();
        for (unsigned int clusterIndex = 0; clusterIndex < numOfClusters; clusterIndex++)
        {
            FbxCluster* currCluster = currSkin->GetCluster(clusterIndex);   
            BoneType* currBone = FindBoneByID(currCluster->GetLink()->GetUniqueID(), Result);
            FbxAMatrix transformMatrix;
            FbxAMatrix transformLinkMatrix;
            FbxAMatrix globalBindposeInverseMatrix;

            currCluster->GetTransformMatrix(transformMatrix);   // The transformation of the mesh at binding time
            currCluster->GetTransformLinkMatrix(transformLinkMatrix);   // The transformation of the cluster(joint) at binding time from joint space to world space
            globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;

            
            currBone->GlobalBindposeInverse = globalBindposeInverseMatrix;


            
            unsigned int numOfIndices = currCluster->GetControlPointIndicesCount();
            int* ControlPointIndices = currCluster->GetControlPointIndices();
            for (unsigned int i = 0; i < numOfIndices; ++i)
            {

                SetWeight(&(Weights[ControlPointIndices[i]]), currCluster->GetControlPointWeights()[i], currBone->ID);
            }

            if (!currBone->AnimationArray){
                currBone->AnimationArray = new AnimationType[AnimStackCount];
            }

            for (int i = 0; i < AnimStackCount; i++)
            {


                FbxAnimStack* lAnimStack = Scene->GetSrcObject<FbxAnimStack>(i);


                FbxTakeInfo* takeInfo = Scene->GetTakeInfo(lAnimStack->GetName());
                FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
                FbxTime end = takeInfo->mLocalTimeSpan.GetStop();




                FbxLongLong AnimationLength = end.GetFrameCount(FbxTime::eFrames24) - start.GetFrameCount(FbxTime::eFrames24) + 1;
                currBone->AnimationArray[i].KeyFrameArrayCount = AnimationLength;
                currBone->AnimationArray[i].KeyFrameArray = new KeyFrameType[AnimationLength];
                CopyToNewString(&(currBone->AnimationArray[i].Name), lAnimStack->GetName());

                int k = 0;
                for (FbxLongLong j = start.GetFrameCount(FbxTime::eFrames24); j <= end.GetFrameCount(FbxTime::eFrames24); j++)
                {
                    FbxTime currTime;
                    currTime.SetFrame(j, FbxTime::eFrames24);

                    currBone->AnimationArray[i].KeyFrameArray[k].FrameNumber = k;

                    FbxVector4 Rotate, Scale, Translate;
                    
                    FbxAMatrix currentTransformOffset = Node->EvaluateGlobalTransform(currTime) * GetGeometryTransformation(Node);
                    FbxAMatrix GlobalTransform = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(currTime);
                    

                    Rotate = GlobalTransform.GetR();
                    
                    currBone->AnimationArray[i].KeyFrameArray[k].Rotate.x = Rotate.mData[0];
                    currBone->AnimationArray[i].KeyFrameArray[k].Rotate.y = Rotate.mData[1];
                    currBone->AnimationArray[i].KeyFrameArray[k].Rotate.z = Rotate.mData[2];
                    
                    Scale = GlobalTransform.GetS();
                    
                    currBone->AnimationArray[i].KeyFrameArray[k].Scale.x = Scale.mData[0];
                    currBone->AnimationArray[i].KeyFrameArray[k].Scale.y = Scale.mData[1];
                    currBone->AnimationArray[i].KeyFrameArray[k].Scale.z = Scale.mData[2];

                    Translate = GlobalTransform.GetT();
                    
                    currBone->AnimationArray[i].KeyFrameArray[k].Translate.x = Translate.mData[0];
                    currBone->AnimationArray[i].KeyFrameArray[k].Translate.y = Translate.mData[1];
                    currBone->AnimationArray[i].KeyFrameArray[k].Translate.z = Translate.mData[2];

                    currBone->AnimationArray[i].KeyFrameArray[k].GlobalTransform=GlobalTransform;

                    k++;
                }
            }
        }
    }

    
}


Und diese Funktion wird einmal pro Frame aufgerufen, um das Modell zu animieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void AnimatedModel::Animate(){
    if (FrameCount == Animations[0].KeyFrameCount){
        FrameCount = 0;
    }
    XMMATRIX rotateMatrixX, rotateMatrixY, rotateMatrixZ, translationMatrix, finalMatrix, scaleMatrix;
    int i;
    for (i = 0; i < BoneCount; i++){
        scaleMatrix = XMMatrixScaling(Animations[0].KeyFrameArray[i][FrameCount].Scale.x, Animations[0].KeyFrameArray[i][FrameCount].Scale.y, Animations[0].KeyFrameArray[i][FrameCount].Scale.z);

        rotateMatrixX = XMMatrixRotationX(Animations[0].KeyFrameArray[i][FrameCount].Rotate.x / 180.0f * M_PI);
        rotateMatrixY = XMMatrixRotationY(Animations[0].KeyFrameArray[i][FrameCount].Rotate.y / 180.0f * M_PI);
        rotateMatrixZ = XMMatrixRotationZ(Animations[0].KeyFrameArray[i][FrameCount].Rotate.z / 180.0f * M_PI);


        translationMatrix = XMMatrixTranslation(Animations[0].KeyFrameArray[i][FrameCount].Translate.x, Animations[0].KeyFrameArray[i][FrameCount].Translate.y, Animations[0].KeyFrameArray[i][FrameCount].Translate.z);

        finalMatrix = XMMatrixMultiply(rotateMatrixX, rotateMatrixY);
        finalMatrix = XMMatrixMultiply(finalMatrix, rotateMatrixZ);
        finalMatrix = XMMatrixMultiply(finalMatrix, translationMatrix);
        finalMatrix = XMMatrixMultiply(finalMatrix, scaleMatrix);
        finalMatrix = XMMatrixMultiply(XMLoadFloat4x4(&BoneArray[i].GlobalBindposeInverse), finalMatrix);
        finalMatrix = XMMatrixTranspose(finalMatrix);

        XMStoreFloat4x4(&(BoneMatrixArray[0].Bonematrix[i]), finalMatrix);
        
        
        
    }


    FrameCount++;
}


Das sind die wichtigsten Änderungen. Hoffentlich habe ich keine vergessen.

Hat vielleicht jemand eine Idee, was ich übersehen haben könnte?

Muss ich die Transformation vom ParentNode des Bones berücksichtigen? Und wenn ja, wie? Ich habe alles Mögliche probiert, aber immer ist Müll rausgekommen.

So sieht es momentan aus:
Screenshot (410 KB)
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Magogan« (29.09.2014, 15:58)


David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

8

29.09.2014, 14:59

Muss ich die Transformation vom ParentNode des Bones berücksichtigen? Und wenn ja, wie? Ich habe alles Mögliche probiert, aber immer ist Müll rausgekommen.

Natürlich musst du das. Die Frage allein zeigt, dass du einen zentralen Aspekt der skelettbasierten Animation nicht verstanden hast, nämlich dass die Bones in einer Hierarchie angeordnet sind.
Etwas zu implementieren, was man nicht versteht, ist keine gute Idee ...
Am besten mal hier lesen: http://en.wikipedia.org/wiki/Skeletal_animation
Die Information, die du suchst, steckt im Text drin.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

29.09.2014, 15:40

Sind diese UHD-Screenshots wirklich notwendig?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

10

29.09.2014, 15:43

Muss ich die Transformation vom ParentNode des Bones berücksichtigen? Und wenn ja, wie? Ich habe alles Mögliche probiert, aber immer ist Müll rausgekommen.

Natürlich musst du das. Die Frage allein zeigt, dass du einen zentralen Aspekt der skelettbasierten Animation nicht verstanden hast, nämlich dass die Bones in einer Hierarchie angeordnet sind.
Etwas zu implementieren, was man nicht versteht, ist keine gute Idee ...
Am besten mal hier lesen: http://en.wikipedia.org/wiki/Skeletal_animation
Die Information, die du suchst, steckt im Text drin.

Ist mir auch klar, dass das keine gute Idee ist, aber ich versuche das ja irgendwie zu verstehen, nur ist die Dokumentation vom FBX SDK einfach schlecht und ich habe keine Ahnung, wie ich jetzt die Transformation der Bones an die richtige Stelle hinbekommen soll. Kann ich nicht irgendwie pro Keyframe beim Importieren ausrechnen, wo der Knochen sein muss? Wenn ich das einfach mit der GlobalTransformMatrix vom Parent-Knochen multipliziere, kommt Müll bei raus :(

"The full transform of a child node is the product of its parent transform and its own transform."
Und welche Matrix ist das jetzt in diesem blöden SDK?

Parent->EvaluateGlobalTransform(currTime)*Current->EvaluateLocalTransform(currTime) klappt jedenfalls nicht.

@BlueCobold: Ich war zu faul, die zu skalieren xD Ich pack die mal als Link rein, dann werden die nicht immer geladen.
Cube Universe
Entdecke fremde Welten auf deiner epischen Reise durchs Universum.

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Magogan« (29.09.2014, 15:57)


Werbeanzeige