root/OpenSceneGraph/trunk/src/osgPlugins/fbx/fbxRMesh.cpp @ 13466

Revision 13466, 46.1 kB (checked in by robert, 2 days ago)

Added shaders to support experimental shader based displacement mapping technique osgTerrain::ShaderTerrain?.

  • Property svn:eol-style set to native
Line 
1#include <cassert>
2#include <sstream>
3
4#include <osg/BlendFunc>
5#include <osg/Geode>
6#include <osg/Image>
7#include <osg/MatrixTransform>
8#include <osg/TexMat>
9#include <osg/TexGen>
10#include <osg/TexEnvCombine>
11
12#include <osgUtil/TriStripVisitor>
13#include <osgUtil/Tessellator>
14
15#include <osgDB/ReadFile>
16
17#include <osgAnimation/RigGeometry>
18#include <osgAnimation/MorphGeometry>
19#include <osgAnimation/BasicAnimationManager>
20
21#if defined(_MSC_VER)
22#pragma warning( disable : 4505 )
23#pragma warning( default : 4996 )
24#endif
25#include <fbxsdk.h>
26
27#include "fbxReader.h"
28
29enum GeometryType
30{
31    GEOMETRY_STATIC,
32    GEOMETRY_RIG,
33    GEOMETRY_MORPH
34};
35
36osg::Vec3d convertVec3(const FbxVector4& v)
37{
38    return osg::Vec3d(
39        v[0],
40        v[1],
41        v[2]);
42}
43
44template <typename T>
45bool layerElementValid(const FbxLayerElementTemplate<T>* pLayerElement)
46{
47    if (!pLayerElement)
48        return false;
49
50    switch (pLayerElement->GetMappingMode())
51    {
52    case FbxLayerElement::eByControlPoint:
53    case FbxLayerElement::eByPolygonVertex:
54    case FbxLayerElement::eByPolygon:
55        break;
56    default:
57        return false;
58    }
59
60    switch (pLayerElement->GetReferenceMode())
61    {
62    case FbxLayerElement::eDirect:
63    case FbxLayerElement::eIndexToDirect:
64        return true;
65    default:
66        break;
67    }
68
69    return false;
70}
71
72template <typename T>
73int getVertexIndex(const FbxLayerElementTemplate<T>* pLayerElement,
74    const FbxMesh* fbxMesh,
75    int nPolygon, int nPolyVertex, int nMeshVertex)
76{
77    int index = 0;
78
79    switch (pLayerElement->GetMappingMode())
80    {
81    case FbxLayerElement::eByControlPoint:
82        index = fbxMesh->GetPolygonVertex(nPolygon, nPolyVertex);
83        break;
84    case FbxLayerElement::eByPolygonVertex:
85        index = nMeshVertex;
86        break;
87    case FbxLayerElement::eByPolygon:
88        index = nPolygon;
89        break;
90    default:
91        OSG_WARN << "getVertexIndex: unsupported FBX mapping mode" << std::endl;
92    }
93
94    if (pLayerElement->GetReferenceMode() == FbxLayerElement::eDirect)
95    {
96        return index;
97    }
98
99    return pLayerElement->GetIndexArray().GetAt(index);
100}
101
102template <typename T>
103int getPolygonIndex(const FbxLayerElementTemplate<T>* pLayerElement, int nPolygon)
104{
105    if (pLayerElement &&
106        pLayerElement->GetMappingMode() == FbxLayerElement::eByPolygon)
107    {
108        switch (pLayerElement->GetReferenceMode())
109        {
110        case FbxLayerElement::eDirect:
111            return nPolygon;
112        case FbxLayerElement::eIndexToDirect:
113            return pLayerElement->GetIndexArray().GetAt(nPolygon);
114        default:
115            break;
116        }
117    }
118
119    return 0;
120}
121
122template <typename FbxT>
123FbxT getElement(const FbxLayerElementTemplate<FbxT>* pLayerElement,
124    const FbxMesh* fbxMesh,
125    int nPolygon, int nPolyVertex, int nMeshVertex)
126{
127    return pLayerElement->GetDirectArray().GetAt(getVertexIndex(
128        pLayerElement, fbxMesh, nPolygon, nPolyVertex, nMeshVertex));
129}
130
131typedef std::map<unsigned, osg::ref_ptr<osg::Geometry> > GeometryMap;
132
133osg::Array* createVec2Array(bool doublePrecision)
134{
135    if  (doublePrecision) return new osg::Vec2dArray;
136    else return new osg::Vec2Array;
137}
138osg::Array* createVec3Array(bool doublePrecision)
139{
140    if  (doublePrecision) return new osg::Vec3dArray;
141    else return new osg::Vec3Array;
142}
143osg::Array* createVec4Array(bool doublePrecision)
144{
145    if  (doublePrecision) return new osg::Vec4dArray;
146    else return new osg::Vec4Array;
147}
148
149osg::Geometry* getGeometry(osg::Geode* pGeode, GeometryMap& geometryMap,
150    std::vector<StateSetContent>& stateSetList,
151    GeometryType gt,
152    unsigned int mti,
153    bool bNormal,
154    bool useDiffuseMap,
155    bool useOpacityMap,
156    bool useEmissiveMap,
157    // more here...
158    bool bColor,
159    const osgDB::Options& options,
160    bool lightmapTextures)
161{
162    GeometryMap::iterator it = geometryMap.find(mti);
163
164    if (it != geometryMap.end())
165    {
166        return it->second.get();
167    }
168
169    osg::ref_ptr<osg::Geometry> pGeometry;
170    if (gt == GEOMETRY_MORPH)
171    {
172        pGeometry = new osgAnimation::MorphGeometry;
173    }
174    else
175    {
176        pGeometry = new osg::Geometry;
177    }
178
179    osgDB::Options::PrecisionHint precision = options.getPrecisionHint();
180
181    pGeometry->setVertexData(osg::Geometry::ArrayData(createVec3Array((precision & osgDB::Options::DOUBLE_PRECISION_VERTEX) != 0), osg::Geometry::BIND_PER_VERTEX));
182    if (bNormal) pGeometry->setNormalData(osg::Geometry::ArrayData(createVec3Array((precision & osgDB::Options::DOUBLE_PRECISION_NORMAL) != 0), osg::Geometry::BIND_PER_VERTEX));
183
184    // create as much textures coordinates as needed...
185    if (useDiffuseMap)
186        pGeometry->setTexCoordData(StateSetContent::DIFFUSE_TEXTURE_UNIT, osg::Geometry::ArrayData(createVec2Array((precision & osgDB::Options::DOUBLE_PRECISION_TEX_COORD) != 0), osg::Geometry::BIND_PER_VERTEX));
187    if (useOpacityMap)
188        pGeometry->setTexCoordData(StateSetContent::OPACITY_TEXTURE_UNIT, osg::Geometry::ArrayData(createVec2Array((precision & osgDB::Options::DOUBLE_PRECISION_TEX_COORD) != 0), osg::Geometry::BIND_PER_VERTEX));
189    if (useEmissiveMap)
190        pGeometry->setTexCoordData(StateSetContent::EMISSIVE_TEXTURE_UNIT, osg::Geometry::ArrayData(createVec2Array((precision & osgDB::Options::DOUBLE_PRECISION_TEX_COORD) != 0), osg::Geometry::BIND_PER_VERTEX));
191    // create more textures coordinates here...
192
193    if (bColor) pGeometry->setColorData(osg::Geometry::ArrayData(createVec4Array((precision & osgDB::Options::DOUBLE_PRECISION_COLOR) != 0), osg::Geometry::BIND_PER_VERTEX));
194
195    if (mti < stateSetList.size())
196    {
197        osg::StateSet* stateSet = pGeometry->getOrCreateStateSet();
198
199        bool transparent = false;
200        const StateSetContent& ssc = stateSetList[mti];
201
202        // set material...
203        if (osg::Material* pMaterial = ssc.material.get())
204        {
205            stateSet->setAttributeAndModes(pMaterial);
206            transparent = pMaterial->getDiffuse(osg::Material::FRONT).w() < 1.0f;
207        }
208
209        // diffuse texture map...
210        if (ssc.diffuseTexture)
211        {
212            stateSet->setTextureAttributeAndModes(StateSetContent::DIFFUSE_TEXTURE_UNIT, ssc.diffuseTexture.get());
213
214            if (ssc.diffuseScaleU != 1.0 || ssc.diffuseScaleV != 1.0)
215            {
216                // set UV scaling...
217                osg::ref_ptr<osg::TexMat> texmat = new osg::TexMat();
218                osg::Matrix uvScaling;
219                uvScaling.makeScale(osg::Vec3(ssc.diffuseScaleU, ssc.diffuseScaleV, 1.0));
220                texmat->setMatrix(uvScaling);
221                stateSet->setTextureAttributeAndModes(StateSetContent::DIFFUSE_TEXTURE_UNIT, texmat.get(), osg::StateAttribute::ON);
222            }
223
224            if (lightmapTextures)
225            {
226                double factor = ssc.diffuseFactor;
227                osg::ref_ptr<osg::TexEnvCombine> texenv = new osg::TexEnvCombine();
228                texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
229                texenv->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
230                texenv->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
231                texenv->setSource2_RGB(osg::TexEnvCombine::CONSTANT);
232                texenv->setConstantColor(osg::Vec4(factor, factor, factor, factor));
233                stateSet->setTextureAttributeAndModes(StateSetContent::DIFFUSE_TEXTURE_UNIT, texenv.get(), osg::StateAttribute::ON);
234            }
235
236            // setup transparency
237            if (!transparent && ssc.diffuseTexture->getImage())
238                transparent = ssc.diffuseTexture->getImage()->isImageTranslucent();
239        }
240
241        // opacity texture map...
242        if (ssc.opacityTexture)
243        {
244            stateSet->setTextureAttributeAndModes(StateSetContent::OPACITY_TEXTURE_UNIT, ssc.opacityTexture.get());
245
246            if (ssc.opacityScaleU != 1.0 || ssc.opacityScaleV != 1.0)
247            {
248                // set UV scaling...
249                osg::ref_ptr<osg::TexMat> texmat = new osg::TexMat();
250                osg::Matrix uvScaling;
251                uvScaling.makeScale(osg::Vec3(ssc.opacityScaleU, ssc.opacityScaleV, 1.0));
252                texmat->setMatrix(uvScaling);
253                stateSet->setTextureAttributeAndModes(StateSetContent::OPACITY_TEXTURE_UNIT, texmat.get(), osg::StateAttribute::ON);
254            }
255
256            // setup combiner to ignore RGB...
257            osg::ref_ptr<osg::TexEnvCombine> texenv = new osg::TexEnvCombine();
258            texenv->setCombine_RGB(osg::TexEnvCombine::REPLACE);
259            texenv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
260            stateSet->setTextureAttributeAndModes(StateSetContent::OPACITY_TEXTURE_UNIT, texenv.get(), osg::StateAttribute::ON);
261
262            // setup transparency...
263            if (!transparent && ssc.opacityTexture->getImage())
264                transparent = ssc.opacityTexture->getImage()->isImageTranslucent();
265        }
266
267        // reflection texture map...
268        if (ssc.reflectionTexture)
269        {
270            stateSet->setTextureAttributeAndModes(StateSetContent::REFLECTION_TEXTURE_UNIT, ssc.reflectionTexture.get());
271
272            // setup spherical map...
273            osg::ref_ptr<osg::TexGen> texgen = new osg::TexGen();
274            texgen->setMode(osg::TexGen::SPHERE_MAP);
275            stateSet->setTextureAttributeAndModes(StateSetContent::REFLECTION_TEXTURE_UNIT, texgen.get(), osg::StateAttribute::ON);
276
277            // setup combiner for factor...
278            double factor = ssc.reflectionFactor;
279            osg::ref_ptr<osg::TexEnvCombine> texenv = new osg::TexEnvCombine();
280            texenv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
281            texenv->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
282            texenv->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
283            texenv->setSource2_RGB(osg::TexEnvCombine::CONSTANT);
284            texenv->setConstantColor(osg::Vec4(factor, factor, factor, factor));
285            stateSet->setTextureAttributeAndModes(StateSetContent::REFLECTION_TEXTURE_UNIT, texenv.get(), osg::StateAttribute::ON);
286        }
287
288        // emissive texture map
289        if (ssc.emissiveTexture)
290        {
291            if (ssc.emissiveScaleU != 1.0 || ssc.emissiveScaleV != 1.0)
292            {
293                // set UV scaling...
294                osg::ref_ptr<osg::TexMat> texmat = new osg::TexMat();
295                osg::Matrix uvScaling;
296                uvScaling.makeScale(osg::Vec3(ssc.emissiveScaleU, ssc.emissiveScaleV, 1.0));
297                texmat->setMatrix(uvScaling);
298                stateSet->setTextureAttributeAndModes(StateSetContent::EMISSIVE_TEXTURE_UNIT, texmat.get(), osg::StateAttribute::ON);
299            }
300
301            stateSet->setTextureAttributeAndModes(StateSetContent::EMISSIVE_TEXTURE_UNIT, ssc.emissiveTexture.get());
302        }
303
304        // add more texture maps here...
305
306        if (transparent)
307        {
308            stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
309            stateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
310        }
311    }
312
313    geometryMap.insert(std::pair<unsigned, osg::ref_ptr<osg::Geometry> >(mti, pGeometry));
314    pGeode->addDrawable(pGeometry.get());
315
316    return pGeometry.get();
317}
318
319osgAnimation::VertexInfluence& getVertexInfluence(
320    osgAnimation::VertexInfluenceMap& vim, const std::string& name)
321{
322    osgAnimation::VertexInfluenceMap::iterator it = vim.lower_bound(name);
323    if (it == vim.end() || name != it->first)
324    {
325        it = vim.insert(it, osgAnimation::VertexInfluenceMap::value_type(
326            name, osgAnimation::VertexInfluence()));
327        it->second.setName(name);
328    }
329    return it->second;
330}
331
332void addChannel(
333    osgAnimation::Channel* pChannel,
334    osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimManager,
335    const char* pTakeName)
336{
337    if (!pChannel)
338    {
339        return;
340    }
341
342    if (!pAnimManager) pAnimManager = new osgAnimation::BasicAnimationManager;
343
344    osgAnimation::Animation* pAnimation = 0;
345    const osgAnimation::AnimationList& anims = pAnimManager->getAnimationList();
346    for (size_t i = 0; i < anims.size(); ++i)
347    {
348        if (anims[i]->getName() == pTakeName)
349        {
350            pAnimation = anims[i].get();
351        }
352    }
353
354    if (!pAnimation)
355    {
356        pAnimation = new osgAnimation::Animation;
357        pAnimation->setName(pTakeName);
358        pAnimManager->registerAnimation(pAnimation);
359    }
360
361    pAnimation->addChannel(pChannel);
362}
363
364void readAnimation(FbxNode* pNode, FbxScene& fbxScene, const std::string& targetName,
365    osg::ref_ptr<osgAnimation::AnimationManagerBase>& pAnimationManager,
366    FbxMesh* pMesh, int nBlendShape, int nBlendShapeChannel, int nShape)
367{
368    for (int i = 0; i < fbxScene.GetSrcObjectCount<FbxAnimStack>(); ++i)
369    {
370        FbxAnimStack* pAnimStack = FbxCast<FbxAnimStack>(fbxScene.GetSrcObject<FbxAnimStack>(i));
371
372        int nbAnimLayers = pAnimStack->GetMemberCount<FbxAnimLayer>();
373
374        const char* pTakeName = pAnimStack->GetName();
375
376        if (!pTakeName || !*pTakeName)
377            continue;
378
379        for (int j = 0; j < nbAnimLayers; j++)
380        {
381            FbxAnimLayer* pAnimLayer = pAnimStack->GetMember<FbxAnimLayer>(j);
382
383            FbxAnimCurve* pCurve = pMesh->GetShapeChannel(nBlendShape, nBlendShapeChannel, pAnimLayer, false);
384
385            if (!pCurve)
386            {
387                continue;
388            }
389
390            int nKeys = pCurve->KeyGetCount();
391            if (!nKeys)
392            {
393                continue;
394            }
395
396            osgAnimation::FloatLinearChannel* pChannel = new osgAnimation::FloatLinearChannel;
397            std::vector<osgAnimation::TemplateKeyframe<float> >& keyFrameCntr = *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer();
398
399            for (int k = 0; k < nKeys; ++k)
400            {
401                FbxAnimCurveKey key = pCurve->KeyGet(k);
402                double fTime = key.GetTime().GetSecondDouble();
403                float fValue = static_cast<float>(key.GetValue() * 0.01);
404                keyFrameCntr.push_back(osgAnimation::FloatKeyframe(fTime,fValue));
405            }
406
407            pChannel->setTargetName(targetName);
408            std::stringstream ss;
409            ss << nShape;
410            pChannel->setName(ss.str());
411            addChannel(pChannel, pAnimationManager, pTakeName);
412        }
413    }
414}
415
416void addBindMatrix(
417    BindMatrixMap& boneBindMatrices,
418    FbxNode* pBone,
419    const osg::Matrix& bindMatrix,
420    osgAnimation::RigGeometry* pRigGeometry)
421{
422    boneBindMatrices.insert(BindMatrixMap::value_type(
423        BindMatrixMap::key_type(pBone, pRigGeometry), bindMatrix));
424}
425
426void addVec2ArrayElement(osg::Array& a, const FbxVector2& v)
427{
428    if (a.getType() == osg::Array::Vec2dArrayType)
429    {
430        static_cast<osg::Vec2dArray&>(a).push_back(osg::Vec2d(v[0], v[1]));
431    }
432    else
433    {
434        static_cast<osg::Vec2Array&>(a).push_back(osg::Vec2(
435            static_cast<float>(v[0]),
436            static_cast<float>(v[1])));
437    }
438}
439
440void addVec3ArrayElement(osg::Array& a, const FbxVector4& v)
441{
442    if (a.getType() == osg::Array::Vec3dArrayType)
443    {
444        static_cast<osg::Vec3dArray&>(a).push_back(osg::Vec3d(v[0], v[1], v[2]));
445    }
446    else
447    {
448        static_cast<osg::Vec3Array&>(a).push_back(osg::Vec3(
449            static_cast<float>(v[0]),
450            static_cast<float>(v[1]),
451            static_cast<float>(v[2])));
452    }
453}
454
455void addColorArrayElement(osg::Array& a, const FbxColor& c)
456{
457    if (a.getType() == osg::Array::Vec4dArrayType)
458    {
459        static_cast<osg::Vec4dArray&>(a).push_back(osg::Vec4d(c.mRed, c.mGreen, c.mBlue, c.mAlpha));
460    }
461    else
462    {
463        static_cast<osg::Vec4Array&>(a).push_back(osg::Vec4(
464            static_cast<float>(c.mRed),
465            static_cast<float>(c.mGreen),
466            static_cast<float>(c.mBlue),
467            static_cast<float>(c.mAlpha)));
468    }
469}
470
471// scans StateSetList looking for the (first) channel name for the specified map type...
472std::string getUVChannelForTextureMap(std::vector<StateSetContent>& stateSetList, const char* pName)
473{
474    // will return the first occurrence in the state set list...
475    // TODO: what if more than one channel for the same map type?
476    for (unsigned int i = 0; i < stateSetList.size(); i++)
477    {
478        if (0 == strcmp(pName, FbxSurfaceMaterial::sDiffuse))
479            return stateSetList[i].diffuseChannel;
480        if (0 == strcmp(pName, FbxSurfaceMaterial::sTransparentColor))
481            return stateSetList[i].opacityChannel;
482        if (0 == strcmp(pName, FbxSurfaceMaterial::sReflection))
483            return stateSetList[i].reflectionChannel;
484        if (0 == strcmp(pName, FbxSurfaceMaterial::sEmissive))
485            return stateSetList[i].emissiveChannel;
486        // more here...
487    }
488
489    return "";
490}
491
492// scans mesh layers looking for the UV element corresponding to the specified channel name...
493const FbxLayerElementUV* getUVElementForChannel(std::string uvChannelName,
494    FbxLayerElement::EType elementType, FbxMesh* pFbxMesh)
495{
496    // scan layers for specified UV channel...
497    for (int cLayerIndex = 0; cLayerIndex < pFbxMesh->GetLayerCount(); cLayerIndex++)
498    {
499        const FbxLayer* pFbxLayer = pFbxMesh->GetLayer(cLayerIndex);
500        if (!pFbxLayer)
501            continue;
502
503        if (const FbxLayerElementUV* uv = pFbxLayer->GetUVs())
504        {
505            if (0 == uvChannelName.compare(uv->GetName()))
506                return uv;
507        }
508    }
509
510    for (int cLayerIndex = 0; cLayerIndex < pFbxMesh->GetLayerCount(); cLayerIndex++)
511    {
512        const FbxLayer* pFbxLayer = pFbxMesh->GetLayer(cLayerIndex);
513        if (!pFbxLayer)
514            continue;
515
516        if (const FbxLayerElementUV* uv = pFbxLayer->GetUVs(elementType))
517        {
518            return uv;
519        }
520    }
521
522    return 0;
523}
524
525typedef std::pair<osg::Geometry*, int> GIPair;
526typedef std::multimap<int, GIPair> FbxToOsgVertexMap;
527typedef std::map<GIPair, int> OsgToFbxNormalMap;
528
529void readMeshTriangle(const FbxMesh * fbxMesh, int i /*polygonIndex*/,
530                      int posInPoly0, int posInPoly1, int posInPoly2,
531                      int meshVertex0, int meshVertex1, int meshVertex2,
532                      FbxToOsgVertexMap& fbxToOsgVertMap,
533                      OsgToFbxNormalMap& osgToFbxNormMap,
534                      const FbxVector4* pFbxVertices,
535                      const FbxLayerElementNormal* pFbxNormals,
536                      const FbxLayerElementUV* pFbxUVs_diffuse,
537                      const FbxLayerElementUV* pFbxUVs_opacity,
538                      const FbxLayerElementUV* pFbxUVs_emissive,
539                      const FbxLayerElementVertexColor* pFbxColors,
540                      osg::Geometry* pGeometry,
541                      osg::Array* pVertices,
542                      osg::Array* pNormals,
543                      osg::Array* pTexCoords_diffuse,
544                      osg::Array* pTexCoords_opacity,
545                      osg::Array* pTexCoords_emissive,
546                      osg::Array* pColors)
547{
548    int v0 = fbxMesh->GetPolygonVertex(i, posInPoly0),
549        v1 = fbxMesh->GetPolygonVertex(i, posInPoly1),
550        v2 = fbxMesh->GetPolygonVertex(i, posInPoly2);
551
552    fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v0, GIPair(pGeometry, pVertices->getNumElements())));
553    fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v1, GIPair(pGeometry, pVertices->getNumElements() + 1)));
554    fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v2, GIPair(pGeometry, pVertices->getNumElements() + 2)));
555
556    addVec3ArrayElement(*pVertices, pFbxVertices[v0]);
557    addVec3ArrayElement(*pVertices, pFbxVertices[v1]);
558    addVec3ArrayElement(*pVertices, pFbxVertices[v2]);
559
560    if (pNormals)
561    {
562        int n0 = getVertexIndex(pFbxNormals, fbxMesh, i, posInPoly0, meshVertex0);
563        int n1 = getVertexIndex(pFbxNormals, fbxMesh, i, posInPoly1, meshVertex1);
564        int n2 = getVertexIndex(pFbxNormals, fbxMesh, i, posInPoly2, meshVertex2);
565
566        osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements()), n0));
567        osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements() + 1), n1));
568        osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements() + 2), n2));
569
570        addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n0));
571        addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n1));
572        addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n2));
573    }
574
575    // add texture maps data (avoid duplicates)...
576    if (pTexCoords_diffuse)
577    {
578        addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, posInPoly0, meshVertex0));
579        addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, posInPoly1, meshVertex1));
580        addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, posInPoly2, meshVertex2));
581    }
582    if (pTexCoords_opacity && (pTexCoords_opacity != pTexCoords_diffuse))
583    {
584        addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, posInPoly0, meshVertex0));
585        addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, posInPoly1, meshVertex1));
586        addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, posInPoly2, meshVertex2));
587    }
588
589    // Only spherical reflection maps are supported (so do not add coordinates for the reflection map)
590
591    if (pTexCoords_emissive && (pTexCoords_emissive != pTexCoords_opacity) && (pTexCoords_emissive != pTexCoords_diffuse))
592    {
593        addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, posInPoly0, meshVertex0));
594        addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, posInPoly1, meshVertex1));
595        addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, posInPoly2, meshVertex2));
596    }
597    // add more texture maps here...
598
599    if (pColors)
600    {
601        addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, posInPoly0, meshVertex0));
602        addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, posInPoly1, meshVertex1));
603        addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, posInPoly2, meshVertex2));
604    }
605}
606
607/// Says if a quad should be split using vertices 02 (or else 13)
608bool quadSplit02(const FbxMesh * fbxMesh, int i /*polygonIndex*/,
609                 int posInPoly0, int posInPoly1, int posInPoly2, int posInPoly3,
610                 const FbxVector4* pFbxVertices)
611{
612    // Algorithm may be a bit dumb. If you got a faster one, feel free to change.
613    // Here we test each of the 4 triangles and see if there is one in the opposite direction.
614    //        Triangles: 012, 023, 013, 123
615    // For this, we do a cross product to get normals. We say here the first triangle is the reference, and do a dot product to see the direction.
616    //        Normals: na (= (p1-p0)^(p2-p1)), nb, na, nd
617    //        Dot products: rb (na.nb), rc, rd
618    // Results:
619    //        if r*>0 => convex (02 and 13 are ok, so choose 02)
620    //        if rb only <0, or r*<0 => concave, split on 13
621    //        if rc only <0, or rd<0 => concave, split on 02
622    //        else unhandled (crossed polygon?) => choose 02
623    //    In short:
624    //        if rb only <0, or r*<0 => return false
625    //        else return true
626
627    int v0 = fbxMesh->GetPolygonVertex(i, posInPoly0);
628    int v1 = fbxMesh->GetPolygonVertex(i, posInPoly1);
629    int v2 = fbxMesh->GetPolygonVertex(i, posInPoly2);
630    int v3 = fbxMesh->GetPolygonVertex(i, posInPoly3);
631
632    osg::Vec3d p0(pFbxVertices[v0][0], pFbxVertices[v0][1], pFbxVertices[v0][2]);
633    osg::Vec3d p1(pFbxVertices[v1][0], pFbxVertices[v1][1], pFbxVertices[v1][2]);
634    osg::Vec3d p2(pFbxVertices[v2][0], pFbxVertices[v2][1], pFbxVertices[v2][2]);
635    osg::Vec3d p3(pFbxVertices[v3][0], pFbxVertices[v3][1], pFbxVertices[v3][2]);
636
637    osg::Vec3d na((p1 - p0) ^ (p2 - p1));
638    osg::Vec3d nb((p2 - p0) ^ (p3 - p2));
639
640    double rb(na * nb);
641    if (rb >= 0) return true;        // Split at 02
642
643    osg::Vec3d nc((p1 - p0) ^ (p3 - p1));
644    osg::Vec3d nd((p2 - p1) ^ (p3 - p2));
645    double rc(na * nc);
646    double rd(na * nd);
647    return (rc >= 0 || rd >= 0);
648}
649
650struct PolygonRef
651{
652    PolygonRef(osg::Geometry* pGeometry, int numPoly, int nVertex)
653        : pGeometry(pGeometry), numPoly(numPoly), nVertex(nVertex)
654    {}
655    osg::Geometry* pGeometry;
656    int numPoly;
657    int nVertex;
658};
659typedef std::vector<PolygonRef> PolygonRefList;
660
661osgDB::ReaderWriter::ReadResult OsgFbxReader::readMesh(
662    FbxNode* pNode,
663    FbxMesh* fbxMesh,
664    std::vector<StateSetContent>& stateSetList,
665    const char* szName)
666{
667    GeometryMap geometryMap;
668
669    osg::Geode* pGeode = new osg::Geode;
670    pGeode->setName(szName);
671
672    const FbxLayerElementNormal* pFbxNormals = 0;
673    const FbxLayerElementVertexColor* pFbxColors = 0;
674    const FbxLayerElementMaterial* pFbxMaterials = 0;
675
676    const FbxVector4* pFbxVertices = fbxMesh->GetControlPoints();
677
678    // scan layers for Normals, Colors and Materials elements (this will get the first available elements)...
679    for (int cLayerIndex = 0; cLayerIndex < fbxMesh->GetLayerCount(); cLayerIndex++)
680    {
681        const FbxLayer* pFbxLayer = fbxMesh->GetLayer(cLayerIndex);
682        if (!pFbxLayer)
683            continue;
684
685        // get normals, colors and materials...
686        if (!pFbxNormals)
687            pFbxNormals = pFbxLayer->GetNormals();
688        if (!pFbxColors)
689            pFbxColors = pFbxLayer->GetVertexColors();
690        if (!pFbxMaterials)
691            pFbxMaterials = pFbxLayer->GetMaterials();
692    }
693
694    // look for UV elements (diffuse, opacity, reflection, emissive, ...) and get their channels names...
695    std::string diffuseChannel = getUVChannelForTextureMap(stateSetList, FbxSurfaceMaterial::sDiffuse);
696    std::string opacityChannel = getUVChannelForTextureMap(stateSetList, FbxSurfaceMaterial::sTransparentColor);
697    std::string emissiveChannel = getUVChannelForTextureMap(stateSetList, FbxSurfaceMaterial::sEmissive);
698    // look for more UV elements here...
699
700    // UV elements...
701    const FbxLayerElementUV* pFbxUVs_diffuse = getUVElementForChannel(diffuseChannel, FbxLayerElement::eTextureDiffuse, fbxMesh);
702    const FbxLayerElementUV* pFbxUVs_opacity = getUVElementForChannel(opacityChannel, FbxLayerElement::eTextureTransparency, fbxMesh);
703    const FbxLayerElementUV* pFbxUVs_emissive = getUVElementForChannel(emissiveChannel, FbxLayerElement::eTextureEmissive, fbxMesh);
704    // more UV elements here...
705
706    // check elements validity...
707    if (!layerElementValid(pFbxNormals)) pFbxNormals = 0;
708    if (!layerElementValid(pFbxColors)) pFbxColors = 0;
709
710    if (!layerElementValid(pFbxUVs_diffuse)) pFbxUVs_diffuse = 0;
711    if (!layerElementValid(pFbxUVs_opacity)) pFbxUVs_opacity = 0;
712    if (!layerElementValid(pFbxUVs_emissive)) pFbxUVs_emissive = 0;
713    // more here...
714
715    int nPolys = fbxMesh->GetPolygonCount();
716
717    int nDeformerCount = fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
718    int nDeformerBlendShapeCount = fbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
719
720    GeometryType geomType = GEOMETRY_STATIC;
721
722    //determine the type of geometry
723    if (nDeformerCount)
724    {
725        geomType = GEOMETRY_RIG;
726    }
727    else if (nDeformerBlendShapeCount)
728    {
729        geomType = GEOMETRY_MORPH;
730    }
731
732    FbxToOsgVertexMap fbxToOsgVertMap;
733    OsgToFbxNormalMap osgToFbxNormMap;
734
735    // First add only triangles and quads (easy to split into triangles without
736    // more processing)
737    // This is the reason we store polygons references:
738
739    PolygonRefList polygonRefList;
740
741    for (int i = 0, nVertex = 0; i < nPolys; ++i)
742    {
743        int lPolygonSize = fbxMesh->GetPolygonSize(i);
744
745        int materialIndex = getPolygonIndex(pFbxMaterials, i);
746
747        osg::Geometry* pGeometry = getGeometry(pGeode, geometryMap,
748            stateSetList, geomType, materialIndex,
749            pFbxNormals != 0,
750            pFbxUVs_diffuse != 0,
751            pFbxUVs_opacity != 0,
752            pFbxUVs_emissive != 0,
753            // more UV elements here...
754            pFbxColors != 0,
755            options,
756            lightmapTextures);
757
758        osg::Array* pVertices = pGeometry->getVertexArray();
759        osg::Array* pNormals = pGeometry->getNormalArray();
760
761        // get texture coordinates...
762        osg::Array* pTexCoords_diffuse = pGeometry->getTexCoordArray(StateSetContent::DIFFUSE_TEXTURE_UNIT);
763        osg::Array* pTexCoords_opacity = pGeometry->getTexCoordArray(StateSetContent::OPACITY_TEXTURE_UNIT);
764        osg::Array* pTexCoords_emissive = pGeometry->getTexCoordArray(StateSetContent::EMISSIVE_TEXTURE_UNIT);
765        // more texture coordinates here...
766
767        osg::Array* pColors = pGeometry->getColorArray();
768
769        if (lPolygonSize == 3)
770        {
771            // Triangle
772            readMeshTriangle(fbxMesh, i,
773                0, 1, 2,
774                nVertex, nVertex+1, nVertex+2,
775                fbxToOsgVertMap, osgToFbxNormMap,
776                pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
777                pGeometry,
778                pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
779            nVertex += 3;
780        }
781        else if (lPolygonSize == 4)
782        {
783            // Quad - Convert to triangles
784            // Use some fast specialized code to see how the should be decomposed
785            // Two cases : Split at '02' (012 and 023), or split at '13 (013 and 123)
786            bool split02 = quadSplit02(fbxMesh, i, 0, 1, 2, 3, pFbxVertices);
787            int p02 = split02 ? 2 : 3; // Triangle 0, point 2
788            int p10 = split02 ? 0 : 1; // Triangle 1, point 0
789            readMeshTriangle(fbxMesh, i,
790                0, 1, p02,
791                nVertex, nVertex+1, nVertex+p02,
792                fbxToOsgVertMap, osgToFbxNormMap,
793                pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
794                pGeometry,
795                pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
796            readMeshTriangle(fbxMesh, i,
797                p10, 2, 3,
798                nVertex+p10, nVertex+2, nVertex+3,
799                fbxToOsgVertMap, osgToFbxNormMap,
800                pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
801                pGeometry,
802                pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
803            nVertex += 4;
804        }
805        else if (tessellatePolygons)
806        {
807            // Polygons - Store to add after triangles
808            polygonRefList.push_back(PolygonRef(pGeometry, i, nVertex));
809            nVertex += lPolygonSize;
810        }
811        else
812        {
813            int nVertex0 = nVertex;
814            nVertex += (std::min)(2, lPolygonSize);
815
816            for (int j = 2; j < lPolygonSize; ++j, ++nVertex)
817            {
818                readMeshTriangle(fbxMesh, i,
819                    0, j - 1, j,
820                    nVertex0, nVertex - 1, nVertex,
821                    fbxToOsgVertMap, osgToFbxNormMap,
822                    pFbxVertices, pFbxNormals, pFbxUVs_diffuse, pFbxUVs_opacity, pFbxUVs_emissive, pFbxColors,
823                    pGeometry,
824                    pVertices, pNormals, pTexCoords_diffuse, pTexCoords_opacity, pTexCoords_emissive, pColors);
825            }
826        }
827    }
828
829    for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
830    {
831        osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
832        osg::DrawArrays* pDrawArrays = new osg::DrawArrays(
833            GL_TRIANGLES, 0, pGeometry->getVertexArray()->getNumElements());
834        pGeometry->addPrimitiveSet(pDrawArrays);
835    }
836
837    // Now add polygons - Convert to triangles
838    // We put vertices in their own PrimitiveSet with Mode=POLYGON; then run the
839    // Tessellator on the Geometry which should tessellate the polygons
840    // automagically.
841    for (PolygonRefList::iterator it = polygonRefList.begin(), itEnd=polygonRefList.end();
842        it != itEnd; ++it)
843    {
844        int i = it->numPoly;
845        int lPolygonSize = fbxMesh->GetPolygonSize(i);
846        //int materialIndex = getPolygonIndex(pFbxMaterials, i);
847        osg::Geometry* pGeometry = it->pGeometry;
848
849        osg::Array* pVertices = pGeometry->getVertexArray();
850        osg::Array* pNormals = pGeometry->getNormalArray();
851        osg::Array* pTexCoords_diffuse = pGeometry->getTexCoordArray(StateSetContent::DIFFUSE_TEXTURE_UNIT);
852        osg::Array* pTexCoords_opacity = pGeometry->getTexCoordArray(StateSetContent::OPACITY_TEXTURE_UNIT);
853        osg::Array* pTexCoords_emissive = pGeometry->getTexCoordArray(StateSetContent::EMISSIVE_TEXTURE_UNIT);
854        osg::Array* pColors = pGeometry->getColorArray();
855        // Index of the 1st vertex of the polygon in the geometry
856        int osgVertex0 = pVertices->getNumElements();
857
858        for (int j = 0, nVertex = it->nVertex; j<lPolygonSize; ++j, ++nVertex)
859        {
860            int v0 = fbxMesh->GetPolygonVertex(i, j);
861            fbxToOsgVertMap.insert(FbxToOsgVertexMap::value_type(v0, GIPair(pGeometry, pVertices->getNumElements())));
862            addVec3ArrayElement(*pVertices, pFbxVertices[v0]);
863            if (pNormals)
864            {
865                int n0 = getVertexIndex(pFbxNormals, fbxMesh, i, j, nVertex);
866                osgToFbxNormMap.insert(OsgToFbxNormalMap::value_type(GIPair(pGeometry, pNormals->getNumElements()), n0));
867                addVec3ArrayElement(*pNormals, pFbxNormals->GetDirectArray().GetAt(n0));
868            }
869
870            // add texture maps data (avoid duplicates)...
871            if (pTexCoords_diffuse)
872            {
873                addVec2ArrayElement(*pTexCoords_diffuse, getElement(pFbxUVs_diffuse, fbxMesh, i, j, nVertex));
874            }
875            if (pTexCoords_opacity && (pTexCoords_opacity != pTexCoords_diffuse))
876            {
877                addVec2ArrayElement(*pTexCoords_opacity, getElement(pFbxUVs_opacity, fbxMesh, i, j, nVertex));
878            }
879
880            // Only spherical reflection maps are supported (so do not add coordinates for the reflection map)
881
882            if (pTexCoords_emissive && (pTexCoords_emissive != pTexCoords_opacity) && (pTexCoords_emissive != pTexCoords_diffuse))
883            {
884                addVec2ArrayElement(*pTexCoords_emissive, getElement(pFbxUVs_emissive, fbxMesh, i, j, nVertex));
885            }
886            // add more texture maps here...
887
888            if (pColors)
889            {
890                addColorArrayElement(*pColors, getElement(pFbxColors, fbxMesh, i, j, nVertex));
891            }
892        }
893
894        osg::DrawArrays* pDrawArrays = new osg::DrawArrays(
895            GL_POLYGON, osgVertex0, pGeometry->getVertexArray()->getNumElements() - osgVertex0);
896        pGeometry->addPrimitiveSet(pDrawArrays);
897    }
898
899    for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
900    {
901        osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
902
903        // Now split polygons if necessary
904        osgUtil::Tessellator tessellator;
905        tessellator.retessellatePolygons(*pGeometry);
906
907        if (pGeode->getNumDrawables() > 1)
908        {
909            std::stringstream ss;
910            ss << pGeode->getName() << " " << i + 1;
911            pGeometry->setName(ss.str());
912        }
913        else
914        {
915            pGeometry->setName(pGeode->getName());
916        }
917    }
918
919    if (geomType == GEOMETRY_RIG)
920    {
921        typedef std::map<osg::ref_ptr<osg::Geometry>,
922            osg::ref_ptr<osgAnimation::RigGeometry> > GeometryRigGeometryMap;
923        GeometryRigGeometryMap old2newGeometryMap;
924
925        for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
926        {
927            osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
928
929            osgAnimation::RigGeometry* pRig = new osgAnimation::RigGeometry;
930            pRig->setSourceGeometry(pGeometry);
931            pRig->copyFrom(*pGeometry);
932            old2newGeometryMap.insert(GeometryRigGeometryMap::value_type(
933                pGeometry, pRig));
934            pRig->setDataVariance(osg::Object::DYNAMIC);
935            pRig->setUseDisplayList( false );
936            pGeode->setDrawable(i, pRig);
937
938            pRig->setInfluenceMap(new osgAnimation::VertexInfluenceMap);
939            pGeometry = pRig;
940        }
941
942        for (int i = 0; i < nDeformerCount; ++i)
943        {
944            FbxSkin* pSkin = (FbxSkin*)fbxMesh->GetDeformer(i, FbxDeformer::eSkin);
945            int nClusters = pSkin->GetClusterCount();
946            for (int j = 0; j < nClusters; ++j)
947            {
948                FbxCluster* pCluster = pSkin->GetCluster(j);
949                //assert(KFbxCluster::eNORMALIZE == pCluster->GetLinkMode());
950                FbxNode* pBone = pCluster->GetLink();
951
952                FbxAMatrix transformLink;
953                pCluster->GetTransformLinkMatrix(transformLink);
954                FbxAMatrix transformLinkInverse = transformLink.Inverse();
955                const double* pTransformLinkInverse = transformLinkInverse;
956                osg::Matrix bindMatrix(pTransformLinkInverse);
957
958                int nIndices = pCluster->GetControlPointIndicesCount();
959                int* pIndices = pCluster->GetControlPointIndices();
960                double* pWeights = pCluster->GetControlPointWeights();
961
962                for (int k = 0; k < nIndices; ++k)
963                {
964                    int fbxIndex = pIndices[k];
965                    float weight = static_cast<float>(pWeights[k]);
966
967                    for (FbxToOsgVertexMap::const_iterator it =
968                        fbxToOsgVertMap.find(fbxIndex);
969                        it != fbxToOsgVertMap.end() &&
970                        it->first == fbxIndex; ++it)
971                    {
972                        GIPair gi = it->second;
973                        osgAnimation::RigGeometry& rig =
974                            dynamic_cast<osgAnimation::RigGeometry&>(
975                            *old2newGeometryMap[gi.first]);
976                        addBindMatrix(boneBindMatrices, pBone, bindMatrix, &rig);
977                        osgAnimation::VertexInfluenceMap& vim =
978                            *rig.getInfluenceMap();
979                        osgAnimation::VertexInfluence& vi =
980                            getVertexInfluence(vim, pBone->GetName());
981                        vi.push_back(osgAnimation::VertexIndexWeight(
982                            gi.second, weight));
983                    }
984                }
985            }
986        }
987    }
988    else if (geomType == GEOMETRY_MORPH)
989    {
990        for (unsigned i = 0; i < pGeode->getNumDrawables(); ++i)
991        {
992            osg::Geometry* pGeometry = pGeode->getDrawable(i)->asGeometry();
993
994            osgAnimation::MorphGeometry& morph = dynamic_cast<osgAnimation::MorphGeometry&>(*pGeometry);
995
996            pGeode->addUpdateCallback(new osgAnimation::UpdateMorph(morph.getName()));
997
998            //read morph geometry
999            for (int nBlendShape = 0; nBlendShape < nDeformerBlendShapeCount; ++nBlendShape)
1000            {
1001                FbxBlendShape* pBlendShape = FbxCast<FbxBlendShape>(fbxMesh->GetDeformer(nBlendShape, FbxDeformer::eBlendShape));
1002                const int nBlendShapeChannelCount = pBlendShape->GetBlendShapeChannelCount();
1003
1004                for (int nBlendShapeChannel = 0; nBlendShapeChannel < nBlendShapeChannelCount; ++nBlendShapeChannel)
1005                {
1006                    FbxBlendShapeChannel* pBlendShapeChannel = pBlendShape->GetBlendShapeChannel(nBlendShapeChannel);
1007                    if (!pBlendShapeChannel->GetTargetShapeCount()) continue;
1008
1009                    //Assume one shape
1010                    if (pBlendShapeChannel->GetTargetShapeCount() > 1)
1011                    {
1012                        OSG_WARN << "Multiple FBX Target Shapes, only the first will be used" << std::endl;
1013                    }
1014                    const FbxGeometryBase* pMorphShape = pBlendShapeChannel->GetTargetShape(0);
1015
1016                    const FbxLayerElementNormal* pFbxShapeNormals = 0;
1017                    if (const FbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0))
1018                    {
1019                        pFbxShapeNormals = pFbxShapeLayer->GetNormals();
1020                        if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0;
1021                    }
1022
1023                    osg::Geometry* pMorphTarget = new osg::Geometry(morph);
1024                    pMorphTarget->setVertexArray(static_cast<osg::Array*>(
1025                        pMorphTarget->getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
1026                    if (pFbxShapeNormals)
1027                    {
1028                        if (osg::Array* pNormals = pMorphTarget->getNormalArray())
1029                        {
1030                            pMorphTarget->setNormalArray(static_cast<osg::Array*>(
1031                                pNormals->clone(osg::CopyOp::DEEP_COPY_ARRAYS)));
1032                        }
1033                    }
1034                    pMorphTarget->setName(pMorphShape->GetName());
1035                    morph.addMorphTarget(pMorphTarget, 0.0f);
1036
1037                    readAnimation(pNode, fbxScene, morph.getName(), pAnimationManager, fbxMesh,
1038                        nBlendShape, nBlendShapeChannel, (int)morph.getMorphTargetList().size() - 1);
1039                }
1040            }
1041        }
1042
1043        int nMorphTarget = 0;
1044        for (int nBlendShape = 0; nBlendShape < nDeformerBlendShapeCount; ++nBlendShape)
1045        {
1046            FbxBlendShape* pBlendShape = FbxCast<FbxBlendShape>(fbxMesh->GetDeformer(nBlendShape, FbxDeformer::eBlendShape));
1047            const int nBlendShapeChannelCount = pBlendShape->GetBlendShapeChannelCount();
1048
1049            for (int nBlendShapeChannel = 0; nBlendShapeChannel < nBlendShapeChannelCount; ++nBlendShapeChannel)
1050            {
1051                FbxBlendShapeChannel* pBlendShapeChannel = pBlendShape->GetBlendShapeChannel(nBlendShapeChannel);
1052                if (!pBlendShapeChannel->GetTargetShapeCount()) continue;
1053
1054                //Assume one shape again
1055                const FbxGeometryBase* pMorphShape = pBlendShapeChannel->GetTargetShape(0);
1056
1057                const FbxLayerElementNormal* pFbxShapeNormals = 0;
1058                if (const FbxLayer* pFbxShapeLayer = pMorphShape->GetLayer(0))
1059                {
1060                    pFbxShapeNormals = pFbxShapeLayer->GetNormals();
1061                    if (!layerElementValid(pFbxShapeNormals)) pFbxShapeNormals = 0;
1062                }
1063
1064                const FbxVector4* pControlPoints = pMorphShape->GetControlPoints();
1065                int nControlPoints = pMorphShape->GetControlPointsCount();
1066                for (int fbxIndex = 0; fbxIndex < nControlPoints; ++fbxIndex)
1067                {
1068                    osg::Vec3d vPos = convertVec3(pControlPoints[fbxIndex]);
1069                    for (FbxToOsgVertexMap::const_iterator it =
1070                        fbxToOsgVertMap.find(fbxIndex);
1071                        it != fbxToOsgVertMap.end() &&
1072                        it->first == fbxIndex; ++it)
1073                    {
1074                        GIPair gi = it->second;
1075                        osgAnimation::MorphGeometry& morphGeom =
1076                            dynamic_cast<osgAnimation::MorphGeometry&>(*gi.first);
1077                        osg::Geometry* pGeometry = morphGeom.getMorphTarget(nMorphTarget).getGeometry();
1078
1079                        if (pGeometry->getVertexArray()->getType() == osg::Array::Vec3dArrayType)
1080                        {
1081                            osg::Vec3dArray* pVertices = static_cast<osg::Vec3dArray*>(pGeometry->getVertexArray());
1082                            (*pVertices)[gi.second] = vPos;
1083                        }
1084                        else
1085                        {
1086                            osg::Vec3Array* pVertices = static_cast<osg::Vec3Array*>(pGeometry->getVertexArray());
1087                            (*pVertices)[gi.second] = vPos;
1088                        }
1089
1090                        if (pFbxShapeNormals && pGeometry->getNormalArray())
1091                        {
1092                            if (pGeometry->getNormalArray()->getType() == osg::Array::Vec3dArrayType)
1093                            {
1094                                osg::Vec3dArray* pNormals = static_cast<osg::Vec3dArray*>(pGeometry->getNormalArray());
1095                                (*pNormals)[gi.second] = convertVec3(
1096                                    pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi]));
1097                            }
1098                            else
1099                            {
1100                                osg::Vec3Array* pNormals = static_cast<osg::Vec3Array*>(pGeometry->getNormalArray());
1101                                (*pNormals)[gi.second] = convertVec3(
1102                                    pFbxShapeNormals->GetDirectArray().GetAt(osgToFbxNormMap[gi]));
1103                            }
1104                        }
1105                    }
1106                }
1107
1108                //don't put this in the for loop as we don't want to do it if the loop continues early
1109                ++nMorphTarget;
1110            }
1111        }
1112    }
1113
1114    FbxAMatrix fbxGeometricTransform;
1115    fbxGeometricTransform.SetTRS(
1116        pNode->GeometricTranslation.Get(),
1117        pNode->GeometricRotation.Get(),
1118        pNode->GeometricScaling.Get());
1119    const double* pGeometricMat = fbxGeometricTransform;
1120    osg::Matrix osgGeometricTransform(pGeometricMat);
1121
1122    if (geomType == GEOMETRY_RIG)
1123    {
1124        FbxSkin* pSkin = (FbxSkin*)fbxMesh->GetDeformer(0, FbxDeformer::eSkin);
1125        if (pSkin->GetClusterCount())
1126        {
1127            FbxAMatrix fbxTransformMatrix;
1128            pSkin->GetCluster(0)->GetTransformMatrix(fbxTransformMatrix);
1129            const double* pTransformMatrix = fbxTransformMatrix;
1130            osgGeometricTransform.postMult(osg::Matrix(pTransformMatrix));
1131        }
1132    }
1133
1134    osg::Node* pResult = pGeode;
1135
1136    if (!osgGeometricTransform.isIdentity())
1137    {
1138        osg::MatrixTransform* pMatTrans = new osg::MatrixTransform(osgGeometricTransform);
1139        pMatTrans->addChild(pGeode);
1140        pResult = pMatTrans;
1141    }
1142
1143    if (geomType == GEOMETRY_RIG)
1144    {
1145        //Add the geometry to the skeleton ancestor of one of the bones.
1146        FbxSkin* pSkin = (FbxSkin*)fbxMesh->GetDeformer(0, FbxDeformer::eSkin);
1147        if (pSkin->GetClusterCount())
1148        {
1149            osgAnimation::Skeleton* pSkeleton = getSkeleton(
1150                pSkin->GetCluster(0)->GetLink(), fbxSkeletons, skeletonMap);
1151            pSkeleton->addChild(pResult);
1152            return osgDB::ReaderWriter::ReadResult::FILE_LOADED;
1153        }
1154    }
1155
1156    return osgDB::ReaderWriter::ReadResult(pResult);
1157}
1158
1159osgDB::ReaderWriter::ReadResult OsgFbxReader::readFbxMesh(FbxNode* pNode,
1160    std::vector<StateSetContent>& stateSetList)
1161{
1162    FbxMesh* lMesh = FbxCast<FbxMesh>(pNode->GetNodeAttribute());
1163
1164    if (!lMesh)
1165    {
1166        return osgDB::ReaderWriter::ReadResult::ERROR_IN_READING_FILE;
1167    }
1168
1169    return readMesh(pNode, lMesh, stateSetList,
1170        pNode->GetName());
1171}
Note: See TracBrowser for help on using the browser.