framework2

Форк
0
1498 строк · 71.2 Кб
1
//
2
//  ofxFBXSrcMesh.cpp
3
//  ConnectionsWall-Nick
4
//
5
//  Created by Nick Hardeman on 7/11/19.
6
//
7

8
#include "ofxFBXSrcMesh.h"
9
#include "ofxFBXUtils.h"
10

11
using namespace ofxFBXSource;
12

13
//--------------------------------------------------------------
14
Mesh::Mesh() {
15
    fbxMesh = NULL;
16
    mNormalsArray = NULL;
17
}
18

19
//--------------------------------------------------------------
20
Mesh::~Mesh() {
21
    if( mNormalsArray != NULL ) {
22
        delete [] mNormalsArray;
23
        mNormalsArray = NULL;
24
    }
25
}
26

27
//--------------------------------------------------------------
28
void Mesh::setup( FbxNode *pNode ) {
29
    ofxFBXSource::Node::setup( pNode );
30
    setFBXMesh( pNode->GetMesh() );
31
}
32

33
//--------------------------------------------------------------
34
void Mesh::setFBXMesh( FbxMesh* lMesh ) {
35
    fbxMesh = lMesh;
36
    mesh.clear();
37
    
38
    // from ViewScene Example included with the FBX SDK //
39
    if (!lMesh->GetNode()) {
40
        ofLogError("ofxFBXMesh") << " error setFBXMesh, lMesh->GetNode failed" << endl;
41
        return;
42
    }
43
    
44
    ofLogVerbose() << "** ofxFBXMesh :: " << getName() << " attempting to parse ******* ";
45
    
46
    vector< string > eMappingModeNames = {"eNone", "eByControlPoint", "eByPolygonVertex", "eByPolygon", "eByEdge", "eAllSame"};
47
    vector<string> eRefModes = {"eDirect", "eIndex", "eIndexToDirect" };
48
    
49
    const int lPolygonCount = lMesh->GetPolygonCount();
50
    
51
    // Count the polygon count of each material
52
    FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
53
    FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
54
    if (lMesh->GetElementMaterial()) {
55
        lMaterialIndice = &lMesh->GetElementMaterial()->GetIndexArray();
56
        lMaterialMappingMode = lMesh->GetElementMaterial()->GetMappingMode();
57
        if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
58
            FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
59
            if (lMaterialIndice->GetCount() == lPolygonCount) {
60
                
61
                // make sure the vector is setup and we have the proper amount of materials ready //
62
                for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
63
                    const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
64
                    if(lMaterialIndex >= 0) {
65
                        if(subMeshes.size() < lMaterialIndex + 1) {
66
                            subMeshes.resize(lMaterialIndex + 1);
67
                        }
68
                    }
69
                }
70
            }
71
        }
72
    }
73
    
74
    // split the vertices based on the materials //
75
    // so that it renders properly //
76
    //    if( subMeshes.size() > 1 ) {
77
    fbxMesh->SplitPoints();
78
    //    }
79
    
80
    if(subMeshes.size() == 0) {
81
        subMeshes.resize(1);
82
    }
83
    
84
    // add in the vertices //
85
    const FbxVector4 * lControlPoints = lMesh->GetControlPoints();
86
    int controlPointCount = lMesh->GetControlPointsCount();
87
    mesh.getVertices().resize( controlPointCount );
88
    
89
    ofLogVerbose() << "ofxFBXMesh :: number of vertices: " << mesh.getNumVertices() << " sub meshes: " << subMeshes.size();
90
    
91
    // INDICES /////
92
    mesh.clearIndices();
93
    // populate the indices //
94
    for( int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; lPolygonIndex++ ) {
95
        int faceSize = fbxMesh->GetPolygonSize( lPolygonIndex );
96
        for( int lVerticeIndex = 0; lVerticeIndex < faceSize; lVerticeIndex++ ) {
97
            const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
98
            mesh.getVertices()[ lControlPointIndex ] = glm::vec3(lControlPoints[lControlPointIndex][0],
99
                                                                 lControlPoints[lControlPointIndex][1],
100
                                                                 lControlPoints[lControlPointIndex][2] );
101
            mesh.addIndex( lControlPointIndex );
102
        }
103
    }
104
    
105
    ofLogVerbose() << "ofxFBXMesh :: number of indices: " << mesh.getNumIndices() << " number of polygons: " << lPolygonCount;
106
    
107
    
108
    // TODO: Account for if all mapping modes are not by control point //
109
    
110
    // Normals //
111
    if( lMesh->GetElementNormalCount() > 0 && lMesh->GetElementNormal() ) {
112
        const FbxGeometryElementNormal * lNormalElement     = lMesh->GetElementNormal(0);
113
        mNormalMappingMode = lNormalElement->GetMappingMode();
114
        
115
        ofLogVerbose() << "ofxFBXMesh :: normals detected. mapping mode: " << eMappingModeNames[ mNormalMappingMode ];
116
        
117
        mesh.getNormals().resize( controlPointCount );
118
        
119
        FbxVector4 lCurrentNormal;
120
        if( mNormalMappingMode == FbxGeometryElement::eByControlPoint ) {
121
            for(int i = 0; i < controlPointCount; i++ ) {
122
                int lNormalIndex = i;
123
                if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
124
                    lNormalIndex = lNormalElement->GetIndexArray().GetAt(i);
125
                }
126
                lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
127
                mesh.getNormals()[i] = glm::vec3( lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2] );
128
            }
129
        } else if( mNormalMappingMode == FbxGeometryElement::eByPolygonVertex ) {
130
            for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
131
                int faceSize = fbxMesh->GetPolygonSize( lPolygonIndex );
132
                for( int lVerticeIndex = 0; lVerticeIndex < faceSize; lVerticeIndex++ ) {
133
                    const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
134
                    if(fbxMesh->GetPolygonVertexNormal( lPolygonIndex, lVerticeIndex, lCurrentNormal )) {
135
                        mesh.getNormals()[ lControlPointIndex ] = glm::vec3( lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2] );
136
                    }
137
                }
138
            }
139
        } else {
140
            ofLogVerbose() << "ofxFBXMesh :: clearing normals, only eByControlPoint and eByPolygonVertex supported.";
141
            mNormalMappingMode = FbxGeometryElement::eNone;
142
            mesh.clearNormals();
143
        }
144
    }
145
    
146
    
147
    if( fbxMesh->GetElementUVCount() ) mesh.getTexCoords().resize( mesh.getNumVertices() );
148
    
149
    // TEX COORDS CODE BASED ON CODE FROM FBX SDK 2016.1 example //
150
    //iterating over all uv sets
151
    for (int lUVSetIndex = 0; lUVSetIndex < fbxMesh->GetElementUVCount(); lUVSetIndex++) {
152
        const FbxGeometryElementUV* lUVElement = fbxMesh->GetElementUV( lUVSetIndex );
153
        
154
        if(!lUVElement)
155
            continue;
156
        
157
        FbxGeometryElement::EMappingMode lUVMappingMode = lUVElement->GetMappingMode();
158
        ofLogVerbose() << "ofxFBXMesh :: uv mapping mode: " << eMappingModeNames[ lUVMappingMode ];
159
        // only support mapping mode eByPolygonVertex and eByControlPoint
160
        if(lUVElement->GetMappingMode() != FbxGeometryElement::eByPolygonVertex &&
161
           lUVElement->GetMappingMode() != FbxGeometryElement::eByControlPoint ) {
162
            continue;
163
        }
164
        
165
        //index array, where holds the index referenced to the uv data
166
        const bool lUseIndex = lUVElement->GetReferenceMode() != FbxGeometryElement::eDirect;
167
        const int lIndexCount= (lUseIndex) ? lUVElement->GetIndexArray().GetCount() : 0;
168
        
169
        //iterating through the data by polygon
170
        const int lPolyCount = fbxMesh->GetPolygonCount();
171
        
172
        if( lUVElement->GetMappingMode() == FbxGeometryElement::eByControlPoint ) {
173
            for( int lPolyIndex = 0; lPolyIndex < lPolyCount; ++lPolyIndex ) {
174
                // build the max index array that we need to pass into MakePoly
175
                const int lPolySize = fbxMesh->GetPolygonSize(lPolyIndex);
176
                for( int lVertIndex = 0; lVertIndex < lPolySize; ++lVertIndex ) {
177
                    FbxVector2 lUVValue;
178
                    //get the index of the current vertex in control points array
179
                    int lPolyVertIndex = fbxMesh->GetPolygonVertex(lPolyIndex,lVertIndex);
180
                    //the UV index depends on the reference mode
181
                    int lUVIndex = lUseIndex ? lUVElement->GetIndexArray().GetAt(lPolyVertIndex) : lPolyVertIndex;
182
                    lUVValue = lUVElement->GetDirectArray().GetAt(lUVIndex);
183
                    mesh.getTexCoords()[ lPolyVertIndex ] = glm::vec2( lUVValue[0], lUVValue[1] );
184
                }
185
            }
186
        } else if (lUVElement->GetMappingMode() == FbxGeometryElement::eByPolygonVertex) {
187
            int lIndexByPolygonVertex = 0;
188
            FbxVector2 lUVValue;
189
            //Let's get normals of each polygon, since the mapping mode of normal element is by polygon-vertex.
190
            for(int lPolygonIndex = 0; lPolygonIndex < fbxMesh->GetPolygonCount(); lPolygonIndex++) {
191
                //get polygon size, you know how many vertices in current polygon.
192
                int lPolygonSize = fbxMesh->GetPolygonSize(lPolygonIndex);
193
                ofLogVerbose() << "ofxFBXMesh :: polygon size: " << lPolygonSize << " ref mode " << eRefModes[lUVElement->GetReferenceMode()];
194
                //retrieve each vertex of current polygon.
195
                for(int i = 0; i < lPolygonSize; i++) {
196
                    int lNormalIndex = 0;
197
                    //reference mode is direct, the normal index is same as lIndexByPolygonVertex.
198
                    if( lUVElement->GetReferenceMode() == FbxGeometryElement::eDirect )
199
                        lNormalIndex = lIndexByPolygonVertex;
200
                    
201
                    //reference mode is index-to-direct, get normals by the index-to-direct
202
                    if( lUVElement->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
203
                        lNormalIndex = lUVElement->GetIndexArray().GetAt(lIndexByPolygonVertex);
204
                    
205
                    //Got normals of each polygon-vertex.
206
                    lUVValue = lUVElement->GetDirectArray().GetAt(lNormalIndex);
207
                    const int lControlPointIndex = fbxMesh->GetPolygonVertex( lPolygonIndex, i );
208
                    mesh.getTexCoords()[ lControlPointIndex ] = glm::vec2( lUVValue[0], lUVValue[1] );
209
                    
210
                    lIndexByPolygonVertex++;
211
                }//end for i //lPolygonSize
212
            }//end for lPolygonIndex //PolygonCount
213
        }
214
        
215
        ofLogVerbose( "ofxFBXMesh : num verts: " ) << mesh.getNumVertices() << " tcoords: " << mesh.getNumTexCoords();
216
    }
217
    
218
    
219
    // VERTEX COLORS ////
220
    if( lMesh->GetElementVertexColorCount() > 0 && lMesh->GetElementVertexColor() ) {
221
        const FbxLayerElementVertexColor* pVertexColorElement   = lMesh->GetElementVertexColor();
222
        FbxGeometryElement::EMappingMode lVertexColorMappingMode = pVertexColorElement->GetMappingMode();
223
        
224
        mesh.getColors().resize( controlPointCount );
225
        
226
        ofLogVerbose() << "ofxFBXMesh :: vertex colors detected: mapping mode: " << eMappingModeNames[ lVertexColorMappingMode ];
227
        
228
        FbxColor lVertexColor;
229
        if( lVertexColorMappingMode == FbxGeometryElement::eByControlPoint ) {
230
            int lVertexColorIndex = 0;
231
            for(int i = 0; i < controlPointCount; i++ ) {
232
                lVertexColorIndex = i;
233
                if ( pVertexColorElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
234
                    lVertexColorIndex = pVertexColorElement->GetIndexArray().GetAt(i);
235
                }
236
                lVertexColor = pVertexColorElement->GetDirectArray().GetAt(lVertexColorIndex);
237
                mesh.getColors()[i].set( ofFloatColor(lVertexColor.mRed, lVertexColor.mGreen, lVertexColor.mBlue, lVertexColor.mAlpha ) );
238
            }
239
        } else {
240
            ofLogVerbose() << "ofxFBXMesh :: clearing vertex colors, only eByControlPoint supported.";
241
            mesh.clearColors();
242
            mesh.disableColors();
243
            lVertexColorMappingMode = FbxGeometryElement::eNone;
244
        }
245
    } else {
246
        mesh.clearColors();
247
        mesh.disableColors();
248
    }
249
    
250
    
251
    // update the meshes offsets and indices counts //
252
    for( int i = 0; i < subMeshes.size(); i++ ) {
253
        subMeshes[i].triangleCount = 0;
254
        subMeshes[i].totalIndices = 0;
255
    }
256
    
257
    // update the sub meshes with the proper amount of indices //
258
    for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
259
        // The material for current face.
260
        int lMaterialIndex = 0;
261
        if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
262
            lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
263
            if(lMaterialIndex < 0) {
264
                lMaterialIndex = 0;
265
            }
266
        }
267
        
268
        subMeshes[lMaterialIndex].triangleCount += 1;
269
        subMeshes[lMaterialIndex].totalIndices += lMesh->GetPolygonSize( lPolygonIndex );
270
    }
271
    
272
    int toffset = 0;
273
    for( int i = 0; i < subMeshes.size(); i++ ) {
274
        subMeshes[i].indexOffset = toffset;
275
        toffset += subMeshes[i].totalIndices;
276
    }
277
    
278
    
279
    
280
    //    cout << "--------------------------------------- " << endl << endl;
281
    
282
    //ofLogVerbose("ofxFBXMesh") << "sub meshes: " <<   subMeshes.size();
283
    for( int i = 0; i < subMeshes.size(); i++ ) {
284
        ofLogVerbose("ofxFBXMesh") << i << " submesh totalindicies = " << subMeshes[i].totalIndices << " index offset: " << subMeshes[i].indexOffset << " total verts = " << mesh.getNumVertices() << " polygonos = " << (lPolygonCount*3);
285
    }
286
    ofLogVerbose("ofxFBXMesh") << getName() << " parse complete." << endl;
287
    //ofLogVerbose("ofxFBXMesh ") << "verts: " << mesh.getNumVertices() << " indices: " << mesh.getNumIndices() << " normals: " << mesh.getNumNormals() << " tex coords: " << mesh.getNumTexCoords();
288
    
289
    veebs.setMesh( mesh, GL_STREAM_DRAW );
290
    original = mesh;
291
    
292
    if( mesh.hasNormals() ) {
293
        if(fbxMesh->GetControlPointsCount()) {
294
            mNormalsArray = new FbxVector4[ fbxMesh->GetControlPointsCount() ];
295
            populateNormals( mNormalsArray );
296
        }
297
    }
298
    
299
    // associate the materials with the sub meshes //
300
    int lSubMeshCount = subMeshes.size();
301
    for (int lIndex = 0; lIndex < lSubMeshCount; ++lIndex) {
302
        const FbxSurfaceMaterial * lMaterial = fbxMesh->GetNode()->GetMaterial(lIndex);
303
        if(lMaterial) {
304
            subMeshes[ lIndex ].materialPtr = static_cast<ofxFBXSource::MeshMaterial *>(lMaterial->GetUserDataPtr());
305
        }
306
    }
307
    
308
}
309

310
//--------------------------------------------------------------
311
void Mesh::configureMesh( ofMesh& aMesh ) {
312
    aMesh = mesh;
313
}
314

315
#pragma mark - Update
316
//--------------------------------------------------------------
317
void Mesh::update( FbxTime& pTime, FbxPose* pPose ) {
318
    
319
//    cout << "ofxFBXSource :: Mesh : update : " << getName() << " has parent: " << ( mFbxNode->GetParent() ? "yes":"no") << endl;
320
    if( fbxMesh->GetNode() && mFbxNode ) {
321
        if( !mFbxNode->GetParent() ) {
322
            FbxAMatrix lGlobalPosition = GetGlobalPosition(fbxMesh->GetNode(), pTime, NULL );
323
            setLocalTransformMatrix(lGlobalPosition);
324
        } else {
325
            FbxAMatrix lLocalPosition = GetLocalPositionForNode(fbxMesh->GetNode(), pTime, NULL );
326
            setLocalTransformMatrix(lLocalPosition);
327
        }
328
    }
329
    
330
//    FbxAMatrix lGlobalPosition = GetGlobalPosition( fbxMesh->GetNode(), pTime, NULL );
331
//    //    FbxAMatrix lGlobalPosition = GetLocalPosition( fbxMesh->GetNode(), pTime, NULL );
332
//    setLocalTransformMatrix(lGlobalPosition);
333
//    //    setTransformMatrix(lGlobalPosition);
334
//    //    glm::mat4 ofgpos = fbxToOf(lGlobalPosition);
335
//    //    setTransformMatrix( ofgpos );
336
}
337

338
//--------------------------------------------------------------
339
void Mesh::update( int aAnimIndex, signed long aMillis ) {
340
    ofxFBXSource::Node::update( aAnimIndex, aMillis );
341
}
342

343
//--------------------------------------------------------------
344
void Mesh::update( int aAnimIndex1, signed long aAnim1Millis, int aAnimIndex2, signed long aAnim2Millis, float aMixPct ) {
345
    ofxFBXSource::Node::update( aAnimIndex1, aAnim1Millis, aAnimIndex2, aAnim2Millis, aMixPct );
346
}
347

348
//--------------------------------------------------------------
349
void Mesh::_configureMeshFromSrcMesh( ofMesh* aSrcMesh, ofMesh* amesh ) {
350
    if(aSrcMesh == nullptr || amesh == nullptr) return;
351
    if( aSrcMesh->getNumVertices() < 3 ) return;
352
//    ofMesh* srcMesh = &akey.mesh;
353
    
354
    if( aSrcMesh != nullptr ) {
355
        if( aSrcMesh->getNumColors() != amesh->getNumColors() ) {
356
            std::copy( aSrcMesh->getColors().begin(), aSrcMesh->getColors().end(), amesh->getColors().begin());
357
        }
358
        if( aSrcMesh->getNumTexCoords() != amesh->getNumTexCoords() ) {
359
            std::copy( aSrcMesh->getTexCoords().begin(), aSrcMesh->getTexCoords().end(), amesh->getTexCoords().begin());
360
        }
361
        if( aSrcMesh->getNumIndices() != amesh->getNumIndices() ) {
362
            std::copy( aSrcMesh->getIndices().begin(), aSrcMesh->getIndices().end(), amesh->getIndices().begin());
363
        }
364
        
365
        if( aSrcMesh->getNumNormals() != amesh->getNumNormals() && amesh->usingNormals() ) {
366
            std::copy( aSrcMesh->getNormals().begin(), aSrcMesh->getNormals().end(), amesh->getNormals().begin());
367
        }
368
        
369
        if( aSrcMesh->getNumVertices() != amesh->getNumVertices() ) {
370
            std::copy( aSrcMesh->getVertices().begin(), aSrcMesh->getVertices().end(), amesh->getVertices().begin());
371
        }
372
    }
373
}
374

375
//--------------------------------------------------------------
376
void Mesh::_updateMeshFromKeyMesh( ofMesh* aSrcMesh, ofMesh* amesh ) {
377
    if(aSrcMesh == nullptr || amesh == nullptr) return;
378
    _configureMeshFromSrcMesh( aSrcMesh, amesh );
379
    
380
    if( aSrcMesh->getNumNormals() > 0 && amesh->usingNormals() ) {
381
        std::copy( aSrcMesh->getNormals().begin(), aSrcMesh->getNormals().end(), amesh->getNormals().begin());
382
    }
383
    
384
    std::copy( aSrcMesh->getVertices().begin(), aSrcMesh->getVertices().end(), amesh->getVertices().begin());
385
}
386

387
//--------------------------------------------------------------
388
void Mesh::updateMeshFromKeyframes( ofMesh* amesh, int aAnimIndex, signed long aMillis ) {
389
    if(amesh == nullptr) return;
390
    
391
    auto& meshKey = getMeshAnimKey( aAnimIndex,aMillis );
392
    if( meshKey.mesh.getNumVertices() < 3 ) return;
393
    
394
    _updateMeshFromKeyMesh( &meshKey.mesh, amesh );
395
}
396

397
//--------------------------------------------------------------
398
void Mesh::updateMeshFromKeyframesBlended( ofMesh* amesh, int aAnimIndex, signed long aMillis ) {
399
    if(amesh == nullptr) return;
400
    
401
    bool bUpdatedMesh = false;
402
    MeshAnimKeyCollection& tcollection = mMeshKeyCollections[aAnimIndex];
403
    auto& keys = tcollection.meshKeys;
404
    size_t numkeys = keys.size();
405
    for( int i = 0; i < numkeys; i++) {
406
        if(keys[i].millis == aMillis) {
407
            _updateMeshFromKeyMesh( &keys[i].mesh, amesh );
408
            bUpdatedMesh = true;
409
        } else if(keys[i].millis > aMillis) {
410
            if(i > 0) {
411
                _configureMeshFromSrcMesh( &keys[i].mesh, amesh );
412
                bUpdatedMesh = true;
413
                
414
                signed long delta = aMillis - keys[i-1].millis;
415
                float pct = double(delta) / double(keys[i].millis - keys[i-1].millis);
416
                // should we lerp all of the mesh vertices //
417
                //                return keys[i];
418
                //                srcMesh = &keys[i].mesh;
419
                //return ofLerp(keys[i-1].value,keys[i].value,pct);
420
                ofMesh& mesh1 = keys[i-1].mesh;
421
                ofMesh& mesh2 = keys[i].mesh;
422
                
423
                // mix the vertices //
424
                auto& tverts = amesh->getVertices();
425
                auto& srcVerts1 = mesh1.getVertices();
426
                auto& srcVerts2 = mesh2.getVertices();
427
                
428
                bool bUpdateNormals = amesh->usingNormals() && amesh->getNumNormals() > 0 && (amesh->getNumVertices() == amesh->getNumNormals());
429
                size_t tnumvs = tverts.size();
430
                pct = ofClamp(pct, 0.0, 1.0);
431
                float invpct = 1.0 - pct;
432
                
433
                for( int i = 0; i < tnumvs; i++ ) {
434
                    tverts[i] = srcVerts1[i] * invpct + srcVerts2[i] * pct;
435
                }
436
                
437
                // calling getNormals flags them as dirty, so lets run through a separate loop //
438
                if(bUpdateNormals) {
439
                    auto& tnormals = amesh->getNormals();
440
                    auto& srcNormals1 = mesh1.getNormals();
441
                    auto& srcNormals2 = mesh2.getNormals();
442
                    for( int i = 0; i < tnumvs; i++ ) {
443
                        tnormals[i] = srcNormals1[i] * invpct + srcNormals2[i] * pct;
444
                    }
445
                }
446
                
447
            } else {
448
                _updateMeshFromKeyMesh( &keys[0].mesh, amesh );
449
                bUpdatedMesh = true;
450
            }
451
        }
452
    }
453
    
454
    if(!keys.empty() && !bUpdatedMesh) {
455
        _updateMeshFromKeyMesh( &keys.back().mesh, amesh );
456
    }
457
    
458
    
459
}
460

461
//--------------------------------------------------------------
462
void Mesh::updateMeshFromKeyframes( ofMesh* amesh, int aAnimIndex1, signed long aAnim1Millis, int aAnimIndex2, signed long aAnim2Millis, float aMixPct ) {
463
    if(amesh == nullptr) return;
464
    auto& key1 = getMeshAnimKey( aAnimIndex1, aAnim1Millis );
465
    auto& key2 = getMeshAnimKey( aAnimIndex2, aAnim2Millis );
466
    if( key1.mesh.getNumVertices() < 3 || key2.mesh.getNumVertices() < 3 ) {
467
        ofLogError("ofxFBXSource::Mesh::updateMeshFromKeyframes: key1.mesh.getNumVertices(): ") << key1.mesh.getNumVertices() << " key2: " << key2.mesh.getNumVertices();
468
        return;
469
    };
470
    
471
    // set the verts based on the first animation //
472
    updateMeshFromKeyframes( amesh, aAnimIndex1, aAnim1Millis );
473
    
474
    // mix the vertices //
475
    auto& tverts = amesh->getVertices();
476
    auto& srcVerts = key2.mesh.getVertices();
477
    bool bUpdateNormals = amesh->usingNormals() && amesh->getNumNormals() > 0 && (amesh->getNumVertices() == amesh->getNumNormals());
478
    size_t tnumvs = tverts.size();
479
    aMixPct = ofClamp(aMixPct, 0.0, 1.0);
480
    float invpct = 1.0 - aMixPct;
481
    
482
    for( int i = 0; i < tnumvs; i++ ) {
483
        tverts[i] = tverts[i] * invpct + srcVerts[i] * aMixPct;
484
    }
485
    // calling getNormals flags them as dirty, so lets run through a separate loop //
486
    if(bUpdateNormals) {
487
        auto& tnormals = amesh->getNormals();
488
        auto& srcNormals = key2.mesh.getNormals();
489
        for( int i = 0; i < tnumvs; i++ ) {
490
            tnormals[i] = tnormals[i] * invpct + srcNormals[i] * aMixPct;
491
        }
492
    }
493
    
494
}
495

496
//--------------------------------------------------------------
497
void Mesh::updateMesh( ofMesh* aMesh, FbxTime& pTime, FbxAnimLayer * pAnimLayer, FbxPose* pPose ) {
498
    const bool lHasShape    = fbxMesh->GetShapeCount() > 0;
499
    const bool lHasSkin     = fbxMesh->GetDeformerCount(FbxDeformer::eSkin) > 0;
500
    const bool lHasVertexCache = fbxMesh->GetDeformerCount(FbxDeformer::eVertexCache);
501
    const bool lHasDeformation = lHasShape || lHasSkin;
502
    
503
    const int lVertexCount = fbxMesh->GetControlPointsCount();
504
    
505
    //    cout << "ofxFBXMesh :: " << getName() << " vertices: " << lVertexCount << " has blend shape: " << lHasShape << " has skin: " << lHasSkin << " has def: " << lHasDeformation << " has vertex cache: " << lHasVertexCache << " | " << ofGetFrameNum() << endl;
506
    
507
    if(!lHasDeformation || lVertexCount < 3) return;
508
    
509
    FbxAMatrix lGlobalPosition = GetGlobalPosition( fbxMesh->GetNode(), pTime, pPose );
510
    // Geometry offset.
511
    // it is not inherited by the children.
512
    FbxAMatrix lGeometryOffset = GetGeometry( fbxMesh->GetNode() );
513
    FbxAMatrix lGlobalOffPosition = lGlobalPosition * lGeometryOffset;
514
    
515
    FbxVector4* lVertexArray = NULL;
516
    lVertexArray = new FbxVector4[ lVertexCount ];
517
    memcpy( lVertexArray, fbxMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4) );
518
    
519
    FbxVector4* lNormalArray = NULL;
520
    if( aMesh->hasNormals() && aMesh->usingNormals() ) {
521
        if( mNormalsArray != NULL ) {
522
            //            cout << "updateMesh :: aMesh " << aMesh->hasNormals() << " using: " << aMesh->usingNormals() << endl;
523
            lNormalArray = new FbxVector4[ lVertexCount ];
524
            memcpy( lNormalArray, mNormalsArray, lVertexCount * sizeof(FbxVector4) );
525
        }
526
    }
527
    
528
    
529
    if(lHasShape) {
530
        computeBlendShapes( aMesh, pTime, pAnimLayer );
531
    }
532
    if(lHasSkin) {
533
        //we need to get the number of clusters. which are controlled by bones //
534
        const int lSkinCount = fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
535
        int lClusterCount = 0;
536
        for (int lSkinIndex = 0; lSkinIndex < lSkinCount; ++lSkinIndex) {
537
            lClusterCount += ((FbxSkin *)(fbxMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin)))->GetClusterCount();
538
        }
539
        if (lClusterCount) {
540
            computeSkinDeformation( lGlobalOffPosition, pTime, pAnimLayer, lVertexArray, lNormalArray, pPose );
541
        }
542
    }
543
    //    cout << "Calling update mesh lHasShape = " << lHasShape << " skin = " << lHasSkin << " lHasDeformation = " << lHasDeformation << endl;
544
    
545
    
546
    vector< glm::vec3 >& amverts      = aMesh->getVertices();
547
    vector< glm::vec3 >& amnormals    = aMesh->getNormals();
548
    
549
    bool bUpdateNormals = lNormalArray != NULL && amnormals.size() > 1;
550
    
551
    const int controlPointCount = fbxMesh->GetControlPointsCount();
552
    // update the vertices //
553
    for(int i = 0; i < controlPointCount; i++ ) {
554
        amverts[i] = glm::vec3( lVertexArray[i][0], lVertexArray[i][1], lVertexArray[i][2] );
555
    }
556
    
557
    if( bUpdateNormals ) {
558
        if( mNormalMappingMode == FbxGeometryElement::eByControlPoint ) {
559
            for(int i = 0; i < controlPointCount; i++ ) {
560
                amnormals[i] = glm::vec3( lNormalArray[i][0], lNormalArray[i][1], lNormalArray[i][2] );
561
                //                amnormals[i].normalize();
562
            }
563
        } else if( mNormalMappingMode == FbxGeometryElement::eByPolygonVertex ) {
564
            const int lPolygonCount = fbxMesh->GetPolygonCount();
565
            int polysize = 3;
566
            
567
            for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
568
                polysize = fbxMesh->GetPolygonSize( lPolygonIndex );
569
                for (int lVerticeIndex = 0; lVerticeIndex < polysize; ++lVerticeIndex) {
570
                    
571
                    const int lControlPointIndex = fbxMesh->GetPolygonVertex( lPolygonIndex, lVerticeIndex );
572
                    //                    amverts[lControlPointIndex].set(lVertexArray[lControlPointIndex][0],
573
                    //                                                    lVertexArray[lControlPointIndex][1],
574
                    //                                                    lVertexArray[lControlPointIndex][2]);
575
                    //                    if( bUpdateNormals ) {
576
                    amnormals[lControlPointIndex] = glm::vec3(lNormalArray[ lControlPointIndex ][0],
577
                                                              lNormalArray[ lControlPointIndex ][1],
578
                                                              lNormalArray[ lControlPointIndex ][2] );
579
                    //                        amnormals[lControlPointIndex].normalize();
580
                    //                    }
581
                }
582
            }
583
        }
584
    }
585
    
586
    //    if(bAllMappedByControlPoint) {
587
    ////        cout << "updateMesh :: bAllMappedByControlPoint : " << endl;
588
    //        for(int i = 0; i < fbxMesh->GetControlPointsCount(); i++ ) {
589
    //            amverts[i].set( lVertexArray[i][0], lVertexArray[i][1], lVertexArray[i][2] );
590
    //            if( bUpdateNormals ) {
591
    //                amnormals[i].set( lNormalArray[i][0], lNormalArray[i][1], lNormalArray[i][2] );
592
    //                amnormals[i].normalize();
593
    //            }
594
    //        }
595
    //    } else {
596
    ////        cout << "updateMesh :: !bAllMappedByControlPoint : normals: " << bUpdateNormals << endl;
597
    //        const int lPolygonCount = fbxMesh->GetPolygonCount();
598
    //        int tvertcount = 0;
599
    //        for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
600
    //            for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) {
601
    //
602
    //                const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
603
    //                amverts[lControlPointIndex].set(lVertexArray[lControlPointIndex][0],
604
    //                                        lVertexArray[lControlPointIndex][1],
605
    //                                        lVertexArray[lControlPointIndex][2]);
606
    //                if( bUpdateNormals ) {
607
    //                    amnormals[lControlPointIndex].set(lNormalArray[ lControlPointIndex ][0],
608
    //                                              lNormalArray[ lControlPointIndex ][1],
609
    //                                              lNormalArray[ lControlPointIndex ][2] );
610
    //                    amnormals[lControlPointIndex].normalize();
611
    //                }
612
    ////                ++tvertcount;
613
    //
614
    //                //  WORKING ////////////
615
    ////                const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
616
    ////                amverts[tvertcount].set(lVertexArray[lControlPointIndex][0],
617
    ////                                        lVertexArray[lControlPointIndex][1],
618
    ////                                        lVertexArray[lControlPointIndex][2]);
619
    ////                if( bUpdateNormals ) {
620
    ////                    amnormals[tvertcount].set(lNormalArray[ lControlPointIndex ][0],
621
    ////                                              lNormalArray[ lControlPointIndex ][1],
622
    ////                                              lNormalArray[ lControlPointIndex ][2] );
623
    ////                    amnormals[tvertcount].normalize();
624
    ////                }
625
    ////                ++tvertcount;
626
    //                // !-- WORKING ///////////////
627
    //            }
628
    //        }
629
    //    }
630
    
631
    delete [] lVertexArray;
632
    if( lNormalArray != NULL ) {
633
        delete [] lNormalArray;
634
    }
635
    
636
}
637

638
#pragma mark - Draw
639
//--------------------------------------------------------------
640
void Mesh::draw( ofMesh* aMesh ) {
641
    //    cout << "ofxFBXMesh :: " << getName() << " verts: " << aMesh->haveVertsChanged() << " indices: " << aMesh->haveIndicesChanged() << " normals: " << aMesh->haveNormalsChanged() << " tex coords: " << aMesh->haveTexCoordsChanged() << " colors: " << aMesh->haveColorsChanged() << " | " << ofGetFrameNum() << endl;
642
    veebs.updateMesh( *aMesh );
643
    if( aMesh->getNumColors() < 1 || !aMesh->usingColors() ) {
644
        veebs.disableColors();
645
    } else {
646
        veebs.enableColors();
647
    }
648
    
649
    const int lSubMeshCount = subMeshes.size();
650
    glEnable( GL_NORMALIZE );
651
    
652
    if(veebs.getIsAllocated()) {
653
        if(lSubMeshCount > 0) {
654
#ifndef TARGET_OPENGLES
655
            // GLES does not support glPolygonMode
656
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL );
657
#endif
658
            
659
            veebs.bind();
660
        }
661
        for (int lIndex = 0; lIndex < lSubMeshCount; ++lIndex) {
662
            GLsizei lOffset = subMeshes[lIndex].indexOffset * sizeof(unsigned int);
663
            //            const GLsizei lElementCount = meshMaterials[lIndex].triangleCount * 3;
664
            const GLsizei lElementCount = subMeshes[lIndex].totalIndices;
665
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, veebs.getIndexId() );
666
            //            cout << "lElementCount = " << lElementCount << " mesh is using indices = " << mesh.hasIndices() << endl;
667
            
668
#ifdef TARGET_OPENGLES
669
            glDrawElements(GL_TRIANGLES, lElementCount, GL_UNSIGNED_SHORT,
670
                           (void*)(sizeof(ofIndexType) * subMeshes[lIndex].indexOffset));
671
#else
672
            glDrawElements( GL_TRIANGLES, lElementCount, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(lOffset));
673
#endif
674
            
675
        }
676
        if(lSubMeshCount > 0) veebs.unbind();
677
    }
678
}
679

680
//--------------------------------------------------------------
681
void Mesh::draw( ofMesh* aMesh, vector< shared_ptr<ofxFBXMeshMaterial> >& aMats, bool bUpdateTheVeeeeebs ) {
682
    if( aMats.size() == 0 ) {
683
        draw( aMesh );
684
        return;
685
    }
686
    
687
//    cout << "ofxFBXSrcMesh :: aMesh num verts: " << aMesh->getNumVertices() << " num tcoords: " << aMesh->getNumTexCoords() << " update veebs: " << bUpdateTheVeeeeebs << " veebs num verts: " << veebs.getNumVertices() << " | " << ofGetFrameNum() << endl;
688
//        cout << "ofxFBXMesh :: " << getName() << " verts: " << aMesh->haveVertsChanged() << " indices: " << aMesh->haveIndicesChanged() << " normals: " << aMesh->haveNormalsChanged() << " tex coords: " << aMesh->haveTexCoordsChanged() << " colors: " << aMesh->haveColorsChanged() << " | " << ofGetFrameNum() << endl;
689
//    veebs.updateMesh( *aMesh );
690
    
691
    
692
    if(bUpdateTheVeeeeebs || veebs.getNumVertices() < 1) {
693
        if( aMesh->hasVertices() ) {
694
            veebs.updateVertexData( aMesh->getVerticesPointer(), aMesh->getNumVertices() );
695
        }
696
        
697
        if( aMesh->hasColors() && aMesh->usingColors() ) {
698
            veebs.updateColorData( aMesh->getColorsPointer(), aMesh->getNumColors() );
699
        }
700
        
701
        if( aMesh->hasNormals() && aMesh->usingNormals() ) {
702
            veebs.updateNormalData(aMesh->getNormalsPointer(),aMesh->getNumNormals());
703
        }
704
        
705
        if( aMesh->hasTexCoords() && aMesh->usingTextures() ) {
706
            veebs.updateTexCoordData( aMesh->getTexCoordsPointer(), aMesh->getNumTexCoords() );
707
        }
708
    }
709
    
710
//    if(haveIndicesChanged()){
711
//        if(getNumIndices()==0){
712
//            vbo.clearIndices();
713
//            vboNumIndices = getNumIndices();
714
//        }else if(vboNumIndices<getNumIndices()){
715
//            vbo.setIndexData(getIndexPointer(),getNumIndices(),usage);
716
//            vboNumIndices = getNumIndices();
717
//        }else{
718
//            vbo.updateIndexData(getIndexPointer(),getNumIndices());
719
//        }
720
//    }
721
    
722
    
723
    if( aMesh->getNumColors() < 1 || !aMesh->usingColors() ) {
724
        veebs.disableColors();
725
    } else {
726
        veebs.enableColors();
727
    }
728
    
729
    const int lSubMeshCount = subMeshes.size();
730
    if( veebs.getIsAllocated() && lSubMeshCount > 0 ) {
731
//        glEnable( GL_NORMALIZE ); // <-- dont think we need this anymore //
732
        
733
//        #ifndef TARGET_OPENGLES
734
////          // GLES does not support glPolygonMode
735
//            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL );
736
//        #endif
737
        
738
        // check to see if all have materials and are enabled so that OF can set the attributes //
739
        // the setAttributes in Programmable renderer is a private method, so the vbo has to bind and unbind
740
        // per sub mesh so we can call that method via ofVbo.drawElements :(
741
        bool bAllMaterialsEnabled = true;
742
        int tnumMatsEnabled = 0;
743
        for( int i = 0; i < aMats.size(); i++ ) {
744
            if( !aMats[i]->isEnabled() ) {
745
                bAllMaterialsEnabled = false;
746
            } else {
747
                tnumMatsEnabled++;
748
            }
749
        }
750
        if( tnumMatsEnabled < 1 ) {
751
            // just draw the whole thing //
752
            veebs.drawElements( GL_TRIANGLES, veebs.getNumIndices() );
753
        } else {
754
        
755
            if(bAllMaterialsEnabled) {
756
                veebs.bind();
757
            }
758
            
759
            for( int lIndex = 0; lIndex < lSubMeshCount; ++lIndex ) {
760
                if( lIndex < aMats.size() ) {
761
                    aMats[lIndex]->begin();
762
                    
763
                    const GLsizei lElementCount = subMeshes[lIndex].totalIndices;
764
                    
765
                    if( bAllMaterialsEnabled ) {
766
//                        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, veebs.getIndexId() );
767
        //            cout << "lElementCount = " << lElementCount << " mesh is using indices = " << mesh.hasIndices() << endl;
768

769
                        #ifdef TARGET_OPENGLES
770
                            glDrawElements( GL_TRIANGLES, lElementCount, GL_UNSIGNED_SHORT, (void*)(sizeof(ofIndexType) * subMeshes[lIndex].indexOffset));
771
                        #else
772
                            GLsizei lOffset = subMeshes[lIndex].indexOffset * sizeof(unsigned int);
773
                            glDrawElements( GL_TRIANGLES, lElementCount, GL_UNSIGNED_INT, reinterpret_cast<const GLvoid *>(lOffset));
774
                        #endif
775
                    } else {
776
                        veebs.drawElements( GL_TRIANGLES, lElementCount, subMeshes[lIndex].indexOffset );
777
                    }
778

779
                    aMats[lIndex]->end();
780
                }
781
            }
782
            
783
            if(bAllMaterialsEnabled) veebs.unbind();
784
        }
785
    }
786
}
787

788
//--------------------------------------------------------------
789
void Mesh::drawMeshKeyframe( int aAnimIndex, signed long aMillis, vector< shared_ptr<ofxFBXMeshMaterial> >& aMats, bool bUpdateTheVeeeeebs ) {
790
    auto& meshKey = getMeshAnimKey( aAnimIndex,aMillis );
791
    if( meshKey.mesh.getNumVertices() < 3 ) return;
792
    draw( &meshKey.mesh, aMats, bUpdateTheVeeeeebs );
793
}
794

795
//--------------------------------------------------------------
796
int Mesh::getNumSubMeshes() {
797
    return (int)subMeshes.size();
798
}
799

800
//--------------------------------------------------------------
801
bool Mesh::hasClusterDeformation() {
802
    if(fbxMesh == NULL) {
803
        ofLogWarning("ofxFBSMesh :: Set the Node before calling hasClusterDeformation");
804
        return false;
805
    }
806
    return fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
807
}
808

809
#pragma mark - Materials + Textures
810
//--------------------------------------------------------------
811
int Mesh::getNumMaterials() {
812
    return getMaterials().size();
813
}
814

815
//--------------------------------------------------------------
816
vector< ofxFBXSource::MeshMaterial* > Mesh::getMaterials() {
817
    vector< ofxFBXSource::MeshMaterial* > rMaterials;
818
    int lSubMeshCount = subMeshes.size();
819
    for (int lIndex = 0; lIndex < lSubMeshCount; ++lIndex) {
820
        const FbxSurfaceMaterial * lMaterial = fbxMesh->GetNode()->GetMaterial(lIndex);
821
        ofxFBXSource::MeshMaterial* lMaterialCache = NULL;
822
        if(lMaterial && lMaterial->GetUserDataPtr() ) {
823
            lMaterialCache = static_cast<ofxFBXSource::MeshMaterial *>(lMaterial->GetUserDataPtr());
824
            rMaterials.push_back( lMaterialCache );
825
        }
826
        
827
    }
828
    return rMaterials;
829
}
830

831
//--------------------------------------------------------------
832
bool Mesh::hasTexture() {
833
    return ( getTextures().size() > 0 );
834
}
835

836
//--------------------------------------------------------------
837
vector< shared_ptr<ofxFBXSource::MeshTexture> > Mesh::getTextures() {
838
    auto tmats = getMaterials();
839
    vector< shared_ptr<ofxFBXSource::MeshTexture> > ttexs;
840
    if( tmats.size() == 0 ) return ttexs;
841
    for( auto& tmat : tmats ) {
842
        if( tmat && tmat->hasTexture() ) {
843
            ttexs.push_back( tmat->getTexturePtr() );
844
        }
845
    }
846
    return ttexs;
847
}
848

849
//--------------------------------------------------------------
850
ofVbo& Mesh::getVbo() {
851
    return veebs;
852
}
853

854
//--------------------------------------------------------------
855
ofMesh& Mesh::getOFMesh() {
856
    return mesh;
857
}
858

859
#pragma mark - Keyframes
860
//----------------------------------------
861
ofxFBXSource::MeshAnimKeyCollection& Mesh::getMeshKeyCollection( int aAnimIndex ) {
862
    if( mMeshKeyCollections.count(aAnimIndex) < 1 ) {
863
        MeshAnimKeyCollection temp;
864
        mMeshKeyCollections[ aAnimIndex ] = temp;
865
    }
866
    return mMeshKeyCollections[aAnimIndex];
867
}
868

869
//----------------------------------------
870
bool Mesh::hasMeshKeyCollection( int aAnimIndex ) {
871
    if( mMeshKeyCollections.count(aAnimIndex) < 1 ) return false;
872
    return true;
873
}
874

875
//----------------------------------------
876
void Mesh::clearKeyFrames() {
877
    mMeshKeyCollections.clear();
878
    ofxFBXSource::Node::clearKeyFrames();
879
    setUsingCachedMeshes( false );
880
}
881

882
//----------------------------------------
883
void Mesh::setUsingCachedMeshes( bool ab ) {
884
    bUsingCachedMeshes = ab;
885
}
886

887
//----------------------------------------
888
bool Mesh::isUsingCachedMeshes() {
889
    return bUsingCachedMeshes;
890
}
891

892
//----------------------------------------
893
MeshAnimKey& Mesh::getMeshAnimKey( int aAnimIndex, signed long aMillis ) {
894
    MeshAnimKeyCollection& tcollection = mMeshKeyCollections[aAnimIndex];
895
    auto& keys = tcollection.meshKeys;
896
    size_t numkeys = keys.size();
897
    for(int i=0; i < numkeys; i++) {
898
        if(keys[i].millis == aMillis) {
899
            return keys[i];
900
        } else if(keys[i].millis > aMillis) {
901
            if(i > 0){
902
//                signed long delta = aMillis - keys[i-1].millis;
903
//                float pct = double(delta) / double(keys[i].millis - keys[i-1].millis);
904
                // should we lerp all of the mesh vertices //
905
                return keys[i];
906
//                srcMesh = &keys[i].mesh;
907
                //return ofLerp(keys[i-1].value,keys[i].value,pct);
908
            } else {
909
                return keys[0];
910
            }
911
        }
912
    }
913
    
914
    if(!keys.empty()){
915
        return keys.back();
916
    }
917
    return dummyMeshAnimKey;
918
}
919

920
#pragma mark - Deformations
921
//--------------------------------------------------------------
922
void Mesh::computeBlendShapes( ofMesh* aMesh, FbxTime& pTime, FbxAnimLayer * pAnimLayer ) {
923
    int lBlendShapeDeformerCount = fbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
924
    //    cout << "Computing blendshapes for " << getName() << endl;
925
    for(int lBlendShapeIndex = 0; lBlendShapeIndex<lBlendShapeDeformerCount; ++lBlendShapeIndex) {
926
        FbxBlendShape* lBlendShape = (FbxBlendShape*)fbxMesh->GetDeformer(lBlendShapeIndex, FbxDeformer::eBlendShape);
927
        
928
        int lBlendShapeChannelCount = lBlendShape->GetBlendShapeChannelCount();
929
        for(int lChannelIndex = 0; lChannelIndex < lBlendShapeChannelCount; ++lChannelIndex) {
930
            FbxBlendShapeChannel* lChannel = lBlendShape->GetBlendShapeChannel(lChannelIndex);
931
            if(lChannel && pAnimLayer) {
932
                // Get the percentage of influence on this channel.
933
                FbxAnimCurve* lFCurve = fbxMesh->GetShapeChannel(lBlendShapeIndex, lChannelIndex, pAnimLayer);
934
                if (!lFCurve) continue;
935
                
936
                double lWeight          = lFCurve->Evaluate(pTime);
937
                //                cout << "updateMesh lWeight = " << lWeight << " time = " << pTime.GetMilliSeconds() << endl;
938
                
939
                int lShapeCount         = lChannel->GetTargetShapeCount();
940
                double* lFullWeights    = lChannel->GetTargetShapeFullWeights();
941
                
942
                // Find out which scope the lWeight falls in.
943
                int lStartIndex = -1;
944
                int lEndIndex = -1;
945
                for(int lShapeIndex = 0; lShapeIndex<lShapeCount; ++lShapeIndex) {
946
                    if(lWeight > 0 && lWeight <= lFullWeights[0]) {
947
                        lEndIndex = 0;
948
                        break;
949
                    }
950
                    if(lWeight > lFullWeights[lShapeIndex] && lWeight < lFullWeights[lShapeIndex+1]) {
951
                        lStartIndex = lShapeIndex;
952
                        lEndIndex = lShapeIndex + 1;
953
                        break;
954
                    }
955
                }
956
                
957
                FbxShape* lStartShape = NULL;
958
                FbxShape* lEndShape = NULL;
959
                if(lStartIndex > -1) {
960
                    lStartShape = lChannel->GetTargetShape(lStartIndex);
961
                }
962
                if(lEndIndex > -1) {
963
                    lEndShape = lChannel->GetTargetShape(lEndIndex);
964
                }
965
                
966
                //The weight percentage falls between base geometry and the first target shape.
967
                if(lStartIndex == -1 && lEndShape) {
968
                    float lEndWeight    = lFullWeights[0];
969
                    lWeight = (lWeight/lEndWeight);
970
                    
971
                    //                    cout << "updateMesh : weight = " << lWeight << endl;
972
                    for (int j = 0; j < aMesh->getNumVertices(); j++) {
973
                        // Add the influence of the shape vertex to the mesh vertex.
974
                        glm::vec3 ov = original.getVertices()[j];
975
                        glm::vec4 influence = ((fbxToOf(lEndShape->GetControlPoints()[j]) - glm::vec4(ov.x, ov.y, ov.z, 0.0)) * lWeight);
976
                        aMesh->getVertices()[j] += glm::vec3(influence.x, influence.y, influence.z);
977
                    }
978
                    
979
                } else if(lStartShape && lEndShape) {
980
                    float lStartWeight  = lFullWeights[lStartIndex];
981
                    float lEndWeight    = lFullWeights[lEndIndex];
982
                    // Calculate the real weight.
983
                    lWeight = ofMap(lWeight, lStartWeight, lEndWeight, 0, 1, true);
984
                    //                    cout << "updateMesh : weight = " << lWeight << " lStartWeight " << lStartWeight << " lEndWeight " << lEndWeight << endl;
985
                    //                    lWeight = ((lWeight-lStartWeight)/(lEndWeight-lStartWeight)) * 100;
986
                    for (int j = 0; j < aMesh->getNumVertices(); j++) {
987
                        // Add the influence of the shape vertex to the mesh vertex.
988
                        glm::vec4 influence = (fbxToOf(lEndShape->GetControlPoints()[j] - lStartShape->GetControlPoints()[j] )) * lWeight;
989
                        aMesh->getVertices()[j] += glm::vec3(influence.x, influence.y, influence.z);
990
                    }
991
                }
992
                
993
            }
994
        }
995
    }
996
}
997

998
void Mesh::computeSkinDeformation( FbxAMatrix& pGlobalPosition, FbxTime& pTime, FbxAnimLayer* pAnimLayer, FbxVector4* pVertexArray, FbxVector4* pNormalsArray, FbxPose* pPose ) {
999
    FbxSkin * lSkinDeformer = (FbxSkin *)fbxMesh->GetDeformer(0, FbxDeformer::eSkin);
1000
    FbxSkin::EType lSkinningType = lSkinDeformer->GetSkinningType();
1001
    
1002
    if(lSkinningType == FbxSkin::eLinear || lSkinningType == FbxSkin::eRigid) {
1003
        //        cout << "ofxFBXMesh :: computeSkinDeformation :: eRigid " << endl;
1004
        computeLinearDeformation(pGlobalPosition, fbxMesh, pTime, pVertexArray, pPose, false );
1005
        if( pNormalsArray != NULL ) {
1006
            //            cout << "ofxFBXMesh :: computeSkinDeformation :: calculate normals array " << endl;
1007
            computeLinearDeformation( pGlobalPosition, fbxMesh, pTime, pNormalsArray, pPose, true );
1008
        }
1009
    } else if(lSkinningType == FbxSkin::eDualQuaternion) {
1010
        //        cout << "ofxFBXMesh :: computeSkinDeformation :: eDualQuaternion " << endl;
1011
        computeDualQuaternionDeformation(pGlobalPosition, fbxMesh, pTime, pVertexArray, pPose, false );
1012
        if( pNormalsArray != NULL ) {
1013
            computeLinearDeformation( pGlobalPosition, fbxMesh, pTime, pNormalsArray, pPose, true );
1014
        }
1015
    } else if(lSkinningType == FbxSkin::eBlend) {
1016
        //        cout << "ofxFBXMesh :: computeSkinDeformation :: eBlend " << endl;
1017
        int lVertexCount = fbxMesh->GetControlPointsCount();
1018
        FbxVector4* lVertexArrayLinear = new FbxVector4[lVertexCount];
1019
        memcpy(lVertexArrayLinear, fbxMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4));
1020
        
1021
        FbxVector4* lVertexArrayDQ = new FbxVector4[lVertexCount];
1022
        memcpy(lVertexArrayDQ, fbxMesh->GetControlPoints(), lVertexCount * sizeof(FbxVector4));
1023
        
1024
        computeLinearDeformation(pGlobalPosition, fbxMesh, pTime, lVertexArrayLinear, pPose, false );
1025
        computeDualQuaternionDeformation(pGlobalPosition, fbxMesh, pTime, lVertexArrayDQ, pPose, false );
1026
        
1027
        // To blend the skinning according to the blend weights
1028
        // Final vertex = DQSVertex * blend weight + LinearVertex * (1- blend weight)
1029
        // DQSVertex: vertex that is deformed by dual quaternion skinning method;
1030
        // LinearVertex: vertex that is deformed by classic linear skinning method;
1031
        int lBlendWeightsCount = lSkinDeformer->GetControlPointIndicesCount();
1032
        for(int lBWIndex = 0; lBWIndex<lBlendWeightsCount; ++lBWIndex) {
1033
            double lBlendWeight = lSkinDeformer->GetControlPointBlendWeights()[lBWIndex];
1034
            pVertexArray[lBWIndex] = lVertexArrayDQ[lBWIndex] * lBlendWeight + lVertexArrayLinear[lBWIndex] * (1 - lBlendWeight);
1035
        }
1036
        
1037
        delete [] lVertexArrayLinear;
1038
        delete [] lVertexArrayDQ;
1039
        
1040
        if( pNormalsArray != NULL ) {
1041
            FbxVector4* lNormalArrayLinear = new FbxVector4[lVertexCount];
1042
            memcpy( lNormalArrayLinear, mNormalsArray, lVertexCount * sizeof(FbxVector4));
1043
            
1044
            FbxVector4* lNormalArrayDQ = new FbxVector4[lVertexCount];
1045
            memcpy(lNormalArrayDQ, mNormalsArray, lVertexCount * sizeof(FbxVector4));
1046
            
1047
            computeLinearDeformation(pGlobalPosition, fbxMesh, pTime, lNormalArrayLinear, pPose, true );
1048
            computeDualQuaternionDeformation(pGlobalPosition, fbxMesh, pTime, lNormalArrayDQ, pPose, true );
1049
            
1050
            // To blend the skinning according to the blend weights
1051
            // Final vertex = DQSVertex * blend weight + LinearVertex * (1- blend weight)
1052
            // DQSVertex: vertex that is deformed by dual quaternion skinning method;
1053
            // LinearVertex: vertex that is deformed by classic linear skinning method;
1054
            int lBlendWeightsCount = lSkinDeformer->GetControlPointIndicesCount();
1055
            for(int lBWIndex = 0; lBWIndex<lBlendWeightsCount; ++lBWIndex) {
1056
                double lBlendWeight = lSkinDeformer->GetControlPointBlendWeights()[lBWIndex];
1057
                pVertexArray[lBWIndex] = lNormalArrayDQ[lBWIndex] * lBlendWeight + lNormalArrayLinear[lBWIndex] * (1 - lBlendWeight);
1058
            }
1059
            
1060
            delete [] lNormalArrayLinear;
1061
            delete [] lNormalArrayDQ;
1062
        }
1063
        
1064
    }
1065
}
1066

1067
// Deform the vertex array in classic linear way.
1068
void Mesh::computeLinearDeformation(FbxAMatrix& pGlobalPosition,
1069
                                          FbxMesh* pMesh,
1070
                                          FbxTime& pTime,
1071
                                          FbxVector4* pVertexArray,
1072
                                          FbxPose* pPose,
1073
                                          bool bNormals) {
1074
    // All the links must have the same link mode.
1075
    FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)fbxMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();
1076
    
1077
    int lVertexCount = pMesh->GetControlPointsCount();
1078
    
1079
    //    cout << "control points count = " << lVertexCount << " mesh verts = " << mesh.getNumVertices() << endl;
1080
    
1081
    FbxAMatrix* lClusterDeformation = new FbxAMatrix[lVertexCount];
1082
    memset(lClusterDeformation, 0, lVertexCount * sizeof(FbxAMatrix));
1083
    
1084
    double* lClusterWeight = new double[lVertexCount];
1085
    memset(lClusterWeight, 0, lVertexCount * sizeof(double));
1086
    
1087
    if (lClusterMode == FbxCluster::eAdditive) {
1088
        for (int i = 0; i < lVertexCount; ++i) {
1089
            lClusterDeformation[i].SetIdentity();
1090
        }
1091
    }
1092
    
1093
    // For all skins and all clusters, accumulate their deformation and weight
1094
    // on each vertices and store them in lClusterDeformation and lClusterWeight.
1095
    int lSkinCount = pMesh->GetDeformerCount(FbxDeformer::eSkin);
1096
    
1097
    //    cout << "computeLinearDeformation :: number of skins = " << lSkinCount << endl;
1098
    FbxAMatrix lInfluence;// = lVertexTransformMatrix;
1099
    for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex) {
1100
        FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
1101
        
1102
        int lClusterCount = lSkinDeformer->GetClusterCount();
1103
        for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex) {
1104
            FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
1105
            if (!lCluster->GetLink())
1106
                continue;
1107
            
1108
            //            cout << "lClusterIndex: " << lClusterIndex << endl;
1109
            
1110
            FbxAMatrix lVertexTransformMatrix;
1111
            computeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose, bNormals );
1112
            
1113
            int lVertexIndexCount = lCluster->GetControlPointIndicesCount();
1114
            for (int k = 0; k < lVertexIndexCount; ++k) {
1115
                int lIndex = lCluster->GetControlPointIndices()[k];
1116
                
1117
                // Sometimes, the mesh can have less points than at the time of the skinning
1118
                // because a smooth operator was active when skinning but has been deactivated during export.
1119
                if (lIndex >= lVertexCount)
1120
                    continue;
1121
                
1122
                double lWeight = lCluster->GetControlPointWeights()[k];
1123
                
1124
                if (lWeight == 0.0) {
1125
                    continue;
1126
                }
1127
                
1128
                // Compute the influence of the link on the vertex.
1129
                //                FbxAMatrix lInfluence = lVertexTransformMatrix;
1130
                lInfluence = lVertexTransformMatrix;
1131
                MatrixScale(lInfluence, lWeight);
1132
                
1133
                if (lClusterMode == FbxCluster::eAdditive) {
1134
                    //                    cout << "computeLinearDeformation :: clustermode = eAdditive" << endl;
1135
                    // Multiply with the product of the deformations on the vertex.
1136
                    MatrixAddToDiagonal(lInfluence, 1.0 - lWeight);
1137
                    lClusterDeformation[lIndex] = lInfluence * lClusterDeformation[lIndex];
1138
                    
1139
                    // Set the link to 1.0 just to know this vertex is influenced by a link.
1140
                    lClusterWeight[lIndex] = 1.0;
1141
                } else // lLinkMode == FbxCluster::eNormalize || lLinkMode == FbxCluster::eTotalOne
1142
                {
1143
                    //                    cout << "computeLinearDeformation :: clustermode = !!eAdditive" << endl;
1144
                    //                    if(k == 0) cout << "computeLinearDeformation :: clustermode != eAdditive " << lInfluence << endl;
1145
                    // Add to the sum of the deformations on the vertex.
1146
                    MatrixAdd(lClusterDeformation[lIndex], lInfluence);
1147
                    
1148
                    // Add to the sum of weights to either normalize or complete the vertex.
1149
                    lClusterWeight[lIndex] += lWeight;
1150
                }
1151
            }//For each vertex
1152
        }//lClusterCount
1153
    }
1154
    
1155
    //Actually deform each vertices here by information stored in lClusterDeformation and lClusterWeight
1156
    //    cout << "going to deform the vertices now " << endl;
1157
    FbxVector4 lSrcVertex;
1158
    for (int i = 0; i < lVertexCount; i++) {
1159
        lSrcVertex   = pVertexArray[i];
1160
        FbxVector4& lDstVertex  = pVertexArray[i];
1161
        
1162
        double lWeight = lClusterWeight[i];
1163
        
1164
        // Deform the vertex if there was at least a link with an influence on the vertex,
1165
        if (lWeight != 0.0) {
1166
            lDstVertex = lClusterDeformation[i].MultT(lSrcVertex);
1167
            if (lClusterMode == FbxCluster::eNormalize) {
1168
                // In the normalized link mode, a vertex is always totally influenced by the links.
1169
                //                cout << i << " weight: " << lWeight << " enormalize " << endl;
1170
                lDstVertex /= lWeight;
1171
            } else if (lClusterMode == FbxCluster::eTotalOne) {
1172
                // In the total 1 link mode, a vertex can be partially influenced by the links.
1173
                //                cout << i << " weight: " << lWeight << " eTotalOne " << endl;
1174
                lSrcVertex *= (1.0 - lWeight);
1175
                lDstVertex += lSrcVertex;
1176
            }
1177
        } else {
1178
            //            cout << i << " weight is zero!! " << endl;
1179
        }
1180
    }
1181
    
1182
    delete [] lClusterDeformation;
1183
    delete [] lClusterWeight;
1184
}
1185

1186

1187
// Deform the vertex array in Dual Quaternion Skinning way.
1188
void Mesh::computeDualQuaternionDeformation(FbxAMatrix& pGlobalPosition,
1189
                                                  FbxMesh* pMesh,
1190
                                                  FbxTime& pTime,
1191
                                                  FbxVector4* pVertexArray,
1192
                                                  FbxPose* pPose,
1193
                                                  bool bNormals) {
1194
    // All the links must have the same link mode.
1195
    FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();
1196
    
1197
    int lVertexCount    = pMesh->GetControlPointsCount();
1198
    int lSkinCount      = pMesh->GetDeformerCount(FbxDeformer::eSkin);
1199
    
1200
    FbxDualQuaternion* lDQClusterDeformation = new FbxDualQuaternion[lVertexCount];
1201
    memset(lDQClusterDeformation, 0, lVertexCount * sizeof(FbxDualQuaternion));
1202
    
1203
    double* lClusterWeight = new double[lVertexCount];
1204
    memset(lClusterWeight, 0, lVertexCount * sizeof(double));
1205
    
1206
    // For all skins and all clusters, accumulate their deformation and weight
1207
    // on each vertices and store them in lClusterDeformation and lClusterWeight.
1208
    for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex)
1209
    {
1210
        FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
1211
        int lClusterCount = lSkinDeformer->GetClusterCount();
1212
        for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex)
1213
        {
1214
            FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
1215
            if (!lCluster->GetLink())
1216
                continue;
1217
            
1218
            FbxAMatrix lVertexTransformMatrix;
1219
            computeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose, bNormals );
1220
            
1221
            FbxQuaternion lQ = lVertexTransformMatrix.GetQ();
1222
            FbxVector4 lT = lVertexTransformMatrix.GetT();
1223
            FbxDualQuaternion lDualQuaternion(lQ, lT);
1224
            
1225
            int lVertexIndexCount = lCluster->GetControlPointIndicesCount();
1226
            for (int k = 0; k < lVertexIndexCount; ++k)
1227
            {
1228
                int lIndex = lCluster->GetControlPointIndices()[k];
1229
                
1230
                // Sometimes, the mesh can have less points than at the time of the skinning
1231
                // because a smooth operator was active when skinning but has been deactivated during export.
1232
                if (lIndex >= lVertexCount)
1233
                    continue;
1234
                
1235
                double lWeight = lCluster->GetControlPointWeights()[k];
1236
                
1237
                if (lWeight == 0.0)
1238
                    continue;
1239
                
1240
                // Compute the influence of the link on the vertex.
1241
                FbxDualQuaternion lInfluence = lDualQuaternion * lWeight;
1242
                if (lClusterMode == FbxCluster::eAdditive)
1243
                {
1244
                    // Simply influenced by the dual quaternion.
1245
                    lDQClusterDeformation[lIndex] = lInfluence;
1246
                    
1247
                    // Set the link to 1.0 just to know this vertex is influenced by a link.
1248
                    lClusterWeight[lIndex] = 1.0;
1249
                }
1250
                else // lLinkMode == FbxCluster::eNormalize || lLinkMode == FbxCluster::eTotalOne
1251
                {
1252
                    if(lClusterIndex == 0)
1253
                    {
1254
                        lDQClusterDeformation[lIndex] = lInfluence;
1255
                    }
1256
                    else
1257
                    {
1258
                        // Add to the sum of the deformations on the vertex.
1259
                        // Make sure the deformation is accumulated in the same rotation direction.
1260
                        // Use dot product to judge the sign.
1261
                        double lSign = lDQClusterDeformation[lIndex].GetFirstQuaternion().DotProduct(lDualQuaternion.GetFirstQuaternion());
1262
                        if( lSign >= 0.0 )
1263
                        {
1264
                            lDQClusterDeformation[lIndex] += lInfluence;
1265
                        }
1266
                        else
1267
                        {
1268
                            lDQClusterDeformation[lIndex] -= lInfluence;
1269
                        }
1270
                    }
1271
                    // Add to the sum of weights to either normalize or complete the vertex.
1272
                    lClusterWeight[lIndex] += lWeight;
1273
                }
1274
            }//For each vertex
1275
        }//lClusterCount
1276
    }
1277
    
1278
    //Actually deform each vertices here by information stored in lClusterDeformation and lClusterWeight
1279
    for (int i = 0; i < lVertexCount; i++) {
1280
        FbxVector4 lSrcVertex = pVertexArray[i];
1281
        FbxVector4& lDstVertex = pVertexArray[i];
1282
        
1283
        double lWeightSum = lClusterWeight[i];
1284
        
1285
        // Deform the vertex if there was at least a link with an influence on the vertex,
1286
        if (lWeightSum != 0.0)
1287
        {
1288
            lDQClusterDeformation[i].Normalize();
1289
            lDstVertex = lDQClusterDeformation[i].Deform(lDstVertex);
1290
            
1291
            if (lClusterMode == FbxCluster::eNormalize)
1292
            {
1293
                // In the normalized link mode, a vertex is always totally influenced by the links.
1294
                lDstVertex /= lWeightSum;
1295
            }
1296
            else if (lClusterMode == FbxCluster::eTotalOne)
1297
            {
1298
                // In the total 1 link mode, a vertex can be partially influenced by the links.
1299
                lSrcVertex *= (1.0 - lWeightSum);
1300
                lDstVertex += lSrcVertex;
1301
            }
1302
        }
1303
    }
1304
    
1305
    delete [] lDQClusterDeformation;
1306
    delete [] lClusterWeight;
1307
}
1308

1309

1310
//Compute the transform matrix that the cluster will transform the vertex.
1311
void Mesh::computeClusterDeformation(FbxAMatrix& pGlobalPosition,
1312
                                           FbxMesh* pMesh,
1313
                                           FbxCluster* pCluster,
1314
                                           FbxAMatrix& pVertexTransformMatrix,
1315
                                           FbxTime pTime,
1316
                                           FbxPose* pPose, bool bNormal ) {
1317
    
1318
    FbxCluster::ELinkMode lClusterMode = pCluster->GetLinkMode();
1319
    
1320
    ofxFBXSource::Bone* bone        = NULL;
1321
    ofxFBXSource::Cluster* cluster  = NULL;
1322
    FbxNode* boneNode       = pCluster->GetLink();
1323
    
1324
    if(boneNode) {
1325
        if(boneNode->GetUserDataPtr()) {
1326
            bone = static_cast<ofxFBXSource::Bone *>(boneNode->GetUserDataPtr());
1327
        }
1328
    }
1329
    
1330
    if(bone != NULL) {
1331
        if(pCluster->GetUserDataPtr()) {
1332
            cluster = static_cast<ofxFBXSource::Cluster *>(pCluster->GetUserDataPtr());
1333
            //            cluster->update( pTime, pPose );
1334
        }
1335
    }
1336
    
1337
    if( bone != NULL && cluster != NULL ) {
1338
        //        cout << "computeClusterDeformation: bone != NULL && cluster != NULL " << bone->getName() << endl;
1339
        //        cout << "We have cached cluster and bone! " << bone->getName() << endl;
1340
        //        pVertexTransformMatrix = cluster->preTrans * bone->fbxTransform * cluster->postTrans;
1341
        //        pVertexTransformMatrix = cluster->preTrans * bone->fbxTransform * cluster->postTrans;
1342
        pVertexTransformMatrix = cluster->preTrans * bone->fbxTransform * cluster->postTrans;
1343
        if( bNormal ) {
1344
            //            cout << "We have cached cluster andNORMAL bone! " << bone->getName() << endl;
1345
            pVertexTransformMatrix = pVertexTransformMatrix.Inverse();
1346
            pVertexTransformMatrix = pVertexTransformMatrix.Transpose();
1347
        }
1348
    } else {
1349
        
1350
        FbxAMatrix lReferenceGlobalInitPosition;
1351
        FbxAMatrix lReferenceGlobalCurrentPosition;
1352
        FbxAMatrix lAssociateGlobalInitPosition;
1353
        FbxAMatrix lAssociateGlobalCurrentPosition;
1354
        FbxAMatrix lClusterGlobalInitPosition;
1355
        FbxAMatrix lClusterGlobalCurrentPosition;
1356
        
1357
        FbxAMatrix lReferenceGeometry;
1358
        FbxAMatrix lAssociateGeometry;
1359
        FbxAMatrix lClusterGeometry;
1360
        
1361
        FbxAMatrix lClusterRelativeInitPosition;
1362
        FbxAMatrix lClusterRelativeCurrentPositionInverse;
1363
        
1364
        // nothing is setup for the control of the bones, so we are just doing animation
1365
        // right now, can't do animation and control the bones at the same time.
1366
        if (lClusterMode == FbxCluster::eAdditive && pCluster->GetAssociateModel()) {
1367
            
1368
            //            cout << "computeClusterDeformation: FbxCluster::eAdditive " << endl;
1369
            
1370
            pCluster->GetTransformAssociateModelMatrix(lAssociateGlobalInitPosition);
1371
            // Geometric transform of the model
1372
            lAssociateGeometry = GetGeometry(pCluster->GetAssociateModel());
1373
            lAssociateGlobalInitPosition *= lAssociateGeometry;
1374
            lAssociateGlobalCurrentPosition = GetGlobalPosition(pCluster->GetAssociateModel(), pTime, pPose);
1375
            
1376
            pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
1377
            // Multiply lReferenceGlobalInitPosition by Geometric Transformation
1378
            lReferenceGeometry = GetGeometry(pMesh->GetNode());
1379
            lReferenceGlobalInitPosition *= lReferenceGeometry;
1380
            lReferenceGlobalCurrentPosition = pGlobalPosition;
1381
            
1382
            // Get the link initial global position and the link current global position.
1383
            pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
1384
            // Multiply lClusterGlobalInitPosition by Geometric Transformation
1385
            lClusterGeometry = GetGeometry(pCluster->GetLink());
1386
            lClusterGlobalInitPosition *= lClusterGeometry;
1387
            lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), pTime, pPose);
1388
            
1389
            // Compute the shift of the link relative to the reference.
1390
            //ModelM-1 * AssoM * AssoGX-1 * LinkGX * LinkM-1*ModelM
1391
            pVertexTransformMatrix = lReferenceGlobalInitPosition.Inverse() * lAssociateGlobalInitPosition * lAssociateGlobalCurrentPosition.Inverse() *
1392
            lClusterGlobalCurrentPosition * lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
1393
        } else {
1394
            
1395
            //            cout << "computeClusterDeformation: !!FbxCluster::eAdditive " << endl;
1396
            
1397
            pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
1398
            lReferenceGlobalCurrentPosition = pGlobalPosition;
1399
            // Multiply lReferenceGlobalInitPosition by Geometric Transformation
1400
            lReferenceGeometry = GetGeometry(pMesh->GetNode());
1401
            lReferenceGlobalInitPosition *= lReferenceGeometry;
1402
            
1403
            // Get the link initial global position and the link current global position.
1404
            pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
1405
            lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), pTime, pPose);
1406
            
1407
            // Compute the initial position of the link relative to the reference.
1408
            lClusterRelativeInitPosition = lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
1409
            
1410
            // Compute the current position of the link relative to the reference.
1411
            lClusterRelativeCurrentPositionInverse = lReferenceGlobalCurrentPosition.Inverse() * lClusterGlobalCurrentPosition;
1412
            
1413
            // Compute the shift of the link relative to the reference.
1414
            pVertexTransformMatrix = lClusterRelativeCurrentPositionInverse * lClusterRelativeInitPosition;
1415
        }
1416
    }
1417
}
1418

1419
//--------------------------------------------------------------
1420
void Mesh::populateNormals( FbxVector4* pNormalsArray ) {
1421
    
1422
    const int lVertexCount = fbxMesh->GetControlPointsCount();
1423
    
1424
    //get the normal element
1425
    FbxGeometryElementNormal* lNormalElement = fbxMesh->GetElementNormal();
1426
    if(lNormalElement)
1427
    {
1428
        //mapping mode is by control points. The mesh should be smooth and soft.
1429
        //we can get normals by retrieving each control point
1430
        if( lNormalElement->GetMappingMode() == FbxGeometryElement::eByControlPoint )
1431
        {
1432
            //Let's get normals of each vertex, since the mapping mode of normal element is by control point
1433
            for(int lVertexIndex = 0; lVertexIndex < fbxMesh->GetControlPointsCount(); lVertexIndex++)
1434
            {
1435
                int lNormalIndex = 0;
1436
                //reference mode is direct, the normal index is same as vertex index.
1437
                //get normals by the index of control vertex
1438
                if( lNormalElement->GetReferenceMode() == FbxGeometryElement::eDirect )
1439
                    lNormalIndex = lVertexIndex;
1440
                
1441
                //reference mode is index-to-direct, get normals by the index-to-direct
1442
                if(lNormalElement->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
1443
                    lNormalIndex = lNormalElement->GetIndexArray().GetAt(lVertexIndex);
1444
                
1445
                //Got normals of each vertex.
1446
                //void KFbxMesh::GetPolygonVertexNormal&#40; int pPolyIndex, int pVertexIndex, KFbxVector4 &pNormal&#41; const;
1447
                //void KFbxMesh::GetPolygonVertexNormal&#40; int pPolyIndex, int pVertexIndex, KFbxVector4 &pNormal&#41; const;
1448
                FbxVector4 lNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
1449
                pNormalsArray[ lVertexIndex ] = lNormal;
1450
                // lNormals->GetDirectArray().Release&#40;&#40;void**&#41;&lFbxNormals&#41;
1451
                //                if( gVerbose ) FBXSDK_printf("normals for vertex[%d]: %f %f %f %f \n", lVertexIndex, lNormal[0], lNormal[1], lNormal[2], lNormal[3]);
1452
                
1453
                //add your custom code here, to output normals or get them into a list, such as KArrayTemplate<FbxVector4>
1454
                //. . .
1455
            }//end for lVertexIndex
1456
        }//end eByControlPoint
1457
        //mapping mode is by polygon-vertex.
1458
        //we can get normals by retrieving polygon-vertex.
1459
        else if(lNormalElement->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
1460
        {
1461
            int lIndexByPolygonVertex = 0;
1462
            //Let's get normals of each polygon, since the mapping mode of normal element is by polygon-vertex.
1463
            for(int lPolygonIndex = 0; lPolygonIndex < fbxMesh->GetPolygonCount(); lPolygonIndex++)
1464
            {
1465
                //get polygon size, you know how many vertices in current polygon.
1466
                int lPolygonSize = fbxMesh->GetPolygonSize(lPolygonIndex);
1467
                //retrieve each vertex of current polygon.
1468
                for(int i = 0; i < lPolygonSize; i++)
1469
                {
1470
                    int lNormalIndex = 0;
1471
                    //reference mode is direct, the normal index is same as lIndexByPolygonVertex.
1472
                    if( lNormalElement->GetReferenceMode() == FbxGeometryElement::eDirect )
1473
                        lNormalIndex = lIndexByPolygonVertex;
1474
                    
1475
                    //reference mode is index-to-direct, get normals by the index-to-direct
1476
                    if(lNormalElement->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
1477
                        lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndexByPolygonVertex);
1478
                    
1479
                    //Got normals of each polygon-vertex.
1480
                    FbxVector4 lNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
1481
                    const int lControlPointIndex = fbxMesh->GetPolygonVertex( lPolygonIndex, i );
1482
                    pNormalsArray[ lControlPointIndex ] = lNormal;
1483
                    
1484
                    //                    if( gVerbose ) FBXSDK_printf("normals for polygon[%d]vertex[%d]: %f %f %f %f \n",
1485
                    //                                                 lPolygonIndex, i, lNormal[0], lNormal[1], lNormal[2], lNormal[3]);
1486
                    
1487
                    
1488
                    
1489
                    //add your custom code here, to output normals or get them into a list, such as KArrayTemplate<FbxVector4>
1490
                    //. . .
1491
                    
1492
                    lIndexByPolygonVertex++;
1493
                }//end for i //lPolygonSize
1494
            }//end for lPolygonIndex //PolygonCount
1495
            
1496
        }//end eByPolygonVertex
1497
    }//end if lNormalElement
1498
}
1499

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.