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

Revision 13466, 25.7 kB (checked in by robert, 71 minutes ago)

Fixed typo in OPENSCENEGRAPH_OPENGL_HEADER name

  • Property svn:eol-style set to native
Line 
1// -*-c++-*-
2
3/*
4 * FBX writer for Open Scene Graph
5 *
6 * Copyright (C) 2009
7 *
8 * Writing support added 2009 by Thibault Caporal and Sukender (Benoit Neil - http://sukender.free.fr)
9 *
10 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for
11 * real-time rendering of large 3D photo-realistic models.
12 * The OSG homepage is http://www.openscenegraph.org/
13 */
14
15#include <climits>                     // required for UINT_MAX
16#include <cassert>
17#include <osg/CullFace>
18#include <osg/MatrixTransform>
19#include <osg/NodeVisitor>
20#include <osg/PrimitiveSet>
21#include <osgDB/FileUtils>
22#include <osgDB/WriteFile>
23#include "WriterNodeVisitor.h"
24
25
26// Use namespace qualification to avoid static-link symbol collisions
27// from multiply defined symbols.
28namespace pluginfbx
29{
30
31
32/** writes all primitives of a primitive-set out to a stream, decomposes quads to triangles, line-strips to lines etc */
33class PrimitiveIndexWriter : public osg::PrimitiveIndexFunctor
34{
35public:
36    PrimitiveIndexWriter(const osg::Geometry* geo,
37                         ListTriangle&        listTriangles,
38                         unsigned int         drawable_n,
39                         unsigned int         material) :
40        _drawable_n(drawable_n),
41        _listTriangles(listTriangles),
42        _modeCache(0),
43        _hasNormalCoords(geo->getNormalArray() != NULL),
44        _hasTexCoords(geo->getTexCoordArray(0) != NULL),
45        _geo(geo),
46        _lastFaceIndex(0),
47        _material(material),
48        _curNormalIndex(0),
49        _normalBinding(geo->getNormalBinding()),
50        _mesh(0)
51    {
52        if (!geo->getNormalArray() || geo->getNormalArray()->getNumElements()==0)
53        {
54            _normalBinding = osg::Geometry::BIND_OFF;        // Turn off binding if there is no normal data
55        }
56        reset();
57    }
58
59    void reset() { _curNormalIndex = 0; }
60
61    unsigned int getNextFaceIndex() { return _lastFaceIndex; }
62
63    virtual void setVertexArray(unsigned int, const osg::Vec2*) {}
64
65    virtual void setVertexArray(unsigned int, const osg::Vec3*) {}
66
67    virtual void setVertexArray(unsigned int, const osg::Vec4*) {}
68
69    virtual void setVertexArray(unsigned int, const osg::Vec2d*) {}
70
71    virtual void setVertexArray(unsigned int, const osg::Vec3d*) {}
72
73    virtual void setVertexArray(unsigned int, const osg::Vec4d*) {}
74
75    // operator for triangles
76    void writeTriangle(unsigned int i1, unsigned int i2, unsigned int i3)
77    {
78        Triangle triangle;
79        triangle.t1 = i1;
80        triangle.t2 = i2;
81        triangle.t3 = i3;
82        if (_normalBinding == osg::Geometry::BIND_PER_VERTEX){
83            triangle.normalIndex1 = i1;
84            triangle.normalIndex2 = i2;
85            triangle.normalIndex3 = i3;
86        }
87        else{
88            triangle.normalIndex1 = _curNormalIndex;
89            triangle.normalIndex2 = _curNormalIndex;
90            triangle.normalIndex3 = _curNormalIndex;
91        }
92        triangle.material = _material;
93        _listTriangles.push_back(std::make_pair(triangle, _drawable_n));
94    }
95
96    virtual void begin(GLenum mode)
97    {
98        _modeCache = mode;
99        _indexCache.clear();
100    }
101
102    virtual void vertex(unsigned int vert)
103    {
104        _indexCache.push_back(vert);
105    }
106
107    virtual void end()
108    {
109        if (!_indexCache.empty())
110        {
111            drawElements(_modeCache, _indexCache.size(), &_indexCache.front());
112        }
113    }
114
115    virtual void drawArrays(GLenum mode, GLint first, GLsizei count);
116
117    virtual void drawElements(GLenum mode, GLsizei count, const GLubyte* indices)
118    {
119        drawElementsImplementation<GLubyte>(mode, count, indices);
120    }
121
122    virtual void drawElements(GLenum mode, GLsizei count, const GLushort* indices)
123    {
124        drawElementsImplementation<GLushort>(mode, count, indices);
125    }
126
127    virtual void drawElements(GLenum mode, GLsizei count, const GLuint* indices)
128    {
129        drawElementsImplementation<GLuint>(mode, count, indices);
130    }
131
132protected:
133    template <typename T> void drawElementsImplementation(GLenum mode, GLsizei count, const T* indices)
134    {
135        if (indices==0 || count==0) return;
136
137        typedef const T* IndexPointer;
138
139        switch (mode)
140        {
141        case GL_TRIANGLES:
142            {
143                IndexPointer ilast = indices + count;
144                for (IndexPointer iptr = indices; iptr < ilast; iptr+=3)
145                {
146                    writeTriangle(iptr[0], iptr[1], iptr[2]);
147                    if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
148                }
149                break;
150            }
151        case GL_TRIANGLE_STRIP:
152            {
153                IndexPointer iptr = indices;
154                for (GLsizei i = 2; i < count; ++i, ++iptr)
155                {
156                    if (i & 1) writeTriangle(iptr[0], iptr[2], iptr[1]);
157                    else       writeTriangle(iptr[0], iptr[1], iptr[2]);
158                }
159                if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
160                break;
161            }
162        case GL_QUADS:
163            {
164                IndexPointer iptr = indices;
165                for (GLsizei i = 3; i < count; i += 4, iptr += 4)
166                {
167                    writeTriangle(iptr[0], iptr[1], iptr[2]);
168                    writeTriangle(iptr[0], iptr[2], iptr[3]);
169                    if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
170                }
171                break;
172            }
173        case GL_QUAD_STRIP:
174            {
175                IndexPointer iptr = indices;
176                for (GLsizei i = 3; i < count; i += 2, iptr += 2)
177                {
178                    writeTriangle(iptr[0], iptr[1], iptr[2]);
179                    writeTriangle(iptr[1], iptr[3], iptr[2]);
180                }
181                if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
182                break;
183            }
184        case GL_POLYGON: // treat polygons as GL_TRIANGLE_FAN
185        case GL_TRIANGLE_FAN:
186            {
187                IndexPointer iptr = indices;
188                unsigned int first = *iptr;
189                ++iptr;
190                for (GLsizei i = 2; i < count; ++i, ++iptr)
191                {
192                    writeTriangle(first, iptr[0], iptr[1]);
193                }
194                if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
195                break;
196            }
197        case GL_POINTS:
198        case GL_LINES:
199        case GL_LINE_STRIP:
200        case GL_LINE_LOOP:
201            // Not handled
202            break;
203        default:
204            // uhm should never come to this point :)
205            break;
206        }
207        if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE_SET) ++_curNormalIndex;
208    }
209
210private:
211    PrimitiveIndexWriter& operator = (const PrimitiveIndexWriter&); // { return *this; }
212
213    unsigned int         _drawable_n;
214    ListTriangle&        _listTriangles;
215    GLenum               _modeCache;
216    std::vector<GLuint>  _indexCache;
217    bool                 _hasNormalCoords, _hasTexCoords;
218    const osg::Geometry* _geo;
219    unsigned int         _lastFaceIndex;
220    int                  _material;
221    unsigned int         _curNormalIndex;
222    osg::Geometry::AttributeBinding _normalBinding;
223    FbxMesh*            _mesh;
224};
225
226void PrimitiveIndexWriter::drawArrays(GLenum mode,GLint first,GLsizei count)
227{
228    unsigned int pos=first;
229    switch (mode)
230    {
231    case GL_TRIANGLES:
232        for (GLsizei i = 2; i < count; i += 3, pos += 3)
233        {
234            writeTriangle(pos, pos + 1, pos + 2);
235            if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
236        }
237        break;
238    case GL_TRIANGLE_STRIP:
239        for (GLsizei i = 2; i < count; ++i, ++pos)
240        {
241            if (i & 1) writeTriangle(pos, pos + 2, pos + 1);
242            else       writeTriangle(pos, pos + 1, pos + 2);
243        }
244        if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
245        break;
246    case GL_QUADS:
247        for (GLsizei i = 3; i < count; i += 4, pos += 4)
248        {
249            writeTriangle(pos, pos + 1, pos + 2);
250            writeTriangle(pos, pos + 2, pos + 3);
251            if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
252        }
253        break;
254    case GL_QUAD_STRIP:
255        for (GLsizei i = 3; i < count; i += 2, pos += 2)
256        {
257            writeTriangle(pos, pos + 1, pos + 2);
258            writeTriangle(pos + 1, pos + 3, pos + 2);
259        }
260        if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
261        break;
262    case GL_POLYGON: // treat polygons as GL_TRIANGLE_FAN
263    case GL_TRIANGLE_FAN:
264        pos = first + 1;
265        for (GLsizei i = 2; i < count; ++i, ++pos)
266        {
267            writeTriangle(first, pos, pos+1);
268        }
269        if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE) ++_curNormalIndex;
270        break;
271    case GL_POINTS:
272    case GL_LINES:
273    case GL_LINE_STRIP:
274    case GL_LINE_LOOP:
275    default:
276        OSG_WARN << "WriterNodeVisitor :: can't handle mode " << mode << std::endl;
277        break;
278    }
279    if (_normalBinding == osg::Geometry::BIND_PER_PRIMITIVE_SET) ++_curNormalIndex;
280}
281
282WriterNodeVisitor::Material::Material(WriterNodeVisitor& writerNodeVisitor,
283                                      osgDB::ExternalFileWriter & externalWriter,
284                                      const osg::StateSet* stateset,
285                                      const osg::Material* mat,
286                                      const osg::Texture* tex,
287                                      FbxManager* pSdkManager,
288                                      const osgDB::ReaderWriter::Options * options,
289                                      int index) :
290    _fbxMaterial(NULL),
291    _fbxTexture(NULL),
292    _index(index),
293    _osgImage(NULL)
294{
295    osg::Vec4 diffuse(1,1,1,1),
296              ambient(0.2,0.2,0.2,1),
297              specular(0,0,0,1),
298              emission(1,1,1,1);
299
300    float shininess(0);
301    float transparency(0);
302
303    if (mat)
304    {
305        assert(stateset);
306        diffuse = mat->getDiffuse(osg::Material::FRONT);
307        ambient = mat->getAmbient(osg::Material::FRONT);
308        specular = mat->getSpecular(osg::Material::FRONT);
309        shininess = mat->getShininess(osg::Material::FRONT);
310        emission = mat->getEmission(osg::Material::FRONT);
311        transparency = 1 - diffuse.w();
312
313        const osg::StateAttribute* attribute = stateset->getAttribute(osg::StateAttribute::CULLFACE);
314        if (attribute)
315        {
316            assert(dynamic_cast<const osg::CullFace*>(attribute));
317            osg::CullFace::Mode mode = static_cast<const osg::CullFace*>(attribute)->getMode();
318            if (mode == osg::CullFace::FRONT)
319            {
320                OSG_WARN << "FBX Writer: Reversed face (culled FRONT) not supported yet." << std::endl;
321            }
322            else if (mode != osg::CullFace::BACK)
323            {
324                assert(mode == osg::CullFace::FRONT_AND_BACK);
325                OSG_WARN << "FBX Writer: Invisible face (culled FRONT_AND_BACK) not supported yet." << std::endl;
326            }
327        }
328
329        _fbxMaterial = FbxSurfacePhong::Create(pSdkManager, mat->getName().c_str());
330        if (_fbxMaterial)
331        {
332            _fbxMaterial->DiffuseFactor.Set(1);
333            _fbxMaterial->Diffuse.Set(FbxDouble3(
334                diffuse.x(),
335                diffuse.y(),
336                diffuse.z()));
337
338            _fbxMaterial->TransparencyFactor.Set(transparency);
339
340            _fbxMaterial->Ambient.Set(FbxDouble3(
341                ambient.x(),
342                ambient.y(),
343                ambient.z()));
344
345            _fbxMaterial->Emissive.Set(FbxDouble3(
346                emission.x(),
347                emission.y(),
348                emission.z()));
349
350            _fbxMaterial->Specular.Set(FbxDouble3(
351                specular.x(),
352                specular.y(),
353                specular.z()));
354
355            _fbxMaterial->Shininess.Set(shininess);
356        }
357    }
358    if (tex && tex->getImage(0))
359    {
360        _osgImage = tex->getImage(0);
361
362        std::string relativePath;
363        externalWriter.write(*_osgImage, options, NULL, &relativePath);
364
365        _fbxTexture = FbxFileTexture::Create(pSdkManager, relativePath.c_str());
366        _fbxTexture->SetFileName(relativePath.c_str());
367        // Create a FBX material if needed
368        if (!_fbxMaterial)
369        {
370            _fbxMaterial = FbxSurfacePhong::Create(pSdkManager, relativePath.c_str());
371        }
372        // Connect texture to material's diffuse
373        // Note there should be no reason FbxSurfacePhong::Create() would return NULL, but as previous code made this secirity test, here we keep the same way.
374        if (_fbxMaterial)
375        {
376            _fbxMaterial->Diffuse.ConnectSrcObject(_fbxTexture);
377        }
378    }
379}
380
381int WriterNodeVisitor::processStateSet(const osg::StateSet* ss)
382{
383    //OSG_ALWAYS << "Trying Adding " << ss->getAttribute(osg::StateAttribute::MATERIAL)->getName() << std::endl;
384    MaterialMap::iterator itr = _materialMap.find(MaterialMap::key_type(ss));
385    if (itr != _materialMap.end())
386    {
387        if (itr->second.getIndex() < 0)
388            itr->second.setIndex(_lastMaterialIndex++);
389        return itr->second.getIndex();
390    }
391
392    const osg::Material* mat = dynamic_cast<const osg::Material*>(ss->getAttribute(osg::StateAttribute::MATERIAL));
393    const osg::Texture* tex = dynamic_cast<const osg::Texture*>(ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE));
394
395    if (mat || tex)
396    {
397        int matNum = _lastMaterialIndex;
398        _materialMap.insert(MaterialMap::value_type(MaterialMap::key_type(ss),
399            Material(*this, _externalWriter, ss, mat, tex, _pSdkManager, _options, matNum)));
400        ++_lastMaterialIndex;
401        return matNum;
402    }
403    return -1;
404}
405
406unsigned int addPolygon(MapIndices & index_vert, unsigned int vertIndex, unsigned int normIndex, unsigned int drawableNum)
407{
408    VertexIndex vert(vertIndex, drawableNum, normIndex);
409    MapIndices::iterator itIndex = index_vert.find(vert);
410    if (itIndex == index_vert.end())
411    {
412        unsigned int indexMesh = index_vert.size();
413        index_vert.insert(std::make_pair(vert, indexMesh));
414        return indexMesh;
415    }
416    return itIndex->second;
417}
418
419void addPolygon(FbxMesh * mesh, MapIndices & index_vert, const Triangle & tri, unsigned int drawableNum)
420{
421    mesh->AddPolygon(addPolygon(index_vert, tri.t1, tri.normalIndex1, drawableNum));
422    mesh->AddPolygon(addPolygon(index_vert, tri.t2, tri.normalIndex2, drawableNum));
423    mesh->AddPolygon(addPolygon(index_vert, tri.t3, tri.normalIndex3, drawableNum));
424}
425
426
427void
428WriterNodeVisitor::setLayerTextureAndMaterial(FbxMesh* mesh)
429{
430    FbxLayerElementTexture* lTextureDiffuseLayer = FbxLayerElementTexture::Create(mesh, "Diffuse");
431    lTextureDiffuseLayer->SetMappingMode(FbxLayerElement::eByPolygon);
432    lTextureDiffuseLayer->SetReferenceMode(FbxLayerElement::eIndexToDirect);
433
434    FbxLayerElementMaterial* lMaterialLayer = FbxLayerElementMaterial::Create(mesh, "materialLayer");
435    lMaterialLayer->SetMappingMode(FbxLayerElement::eByPolygon);
436    lMaterialLayer->SetReferenceMode(FbxLayerElement::eIndexToDirect);
437
438    lTextureDiffuseLayer->GetDirectArray().SetCount(_lastMaterialIndex);
439    lMaterialLayer->mDirectArray->SetCount(_lastMaterialIndex);
440
441    for (MaterialMap::iterator it = _materialMap.begin(); it != _materialMap.end(); ++it)
442    {
443        if (it->second.getIndex() != -1)
444        {
445            FbxSurfaceMaterial* lMaterial = it->second.getFbxMaterial();
446            FbxFileTexture* lTexture = it->second.getFbxTexture();
447            lTextureDiffuseLayer->GetDirectArray().SetAt(it->second.getIndex(), lTexture);
448            lMaterialLayer->mDirectArray->SetAt(it->second.getIndex(), lMaterial);
449        }
450    }
451    mesh->GetLayer(0)->SetMaterials(lMaterialLayer);
452    mesh->GetLayer(0)->SetTextures(FbxLayerElement::eTextureDiffuse, lTextureDiffuseLayer);
453}
454
455void
456WriterNodeVisitor::setControlPointAndNormalsAndUV(const osg::Geode& geo,
457                                                  MapIndices&       index_vert,
458                                                  bool              texcoords,
459                                                  FbxMesh*         mesh)
460{
461    mesh->InitControlPoints(index_vert.size());
462    FbxLayerElementNormal* lLayerElementNormal= FbxLayerElementNormal::Create(mesh, "");
463    // For now, FBX writer only supports normals bound per vertices
464    lLayerElementNormal->SetMappingMode(FbxLayerElement::eByControlPoint);
465    lLayerElementNormal->SetReferenceMode(FbxLayerElement::eDirect);
466    lLayerElementNormal->GetDirectArray().SetCount(index_vert.size());
467    mesh->GetLayer(0)->SetNormals(lLayerElementNormal);
468    FbxLayerElementUV* lUVDiffuseLayer = FbxLayerElementUV::Create(mesh, "DiffuseUV");
469
470    if (texcoords)
471    {
472        lUVDiffuseLayer->SetMappingMode(FbxLayerElement::eByControlPoint);
473        lUVDiffuseLayer->SetReferenceMode(FbxLayerElement::eDirect);
474        lUVDiffuseLayer->GetDirectArray().SetCount(index_vert.size());
475        mesh->GetLayer(0)->SetUVs(lUVDiffuseLayer, FbxLayerElement::eTextureDiffuse);
476    }
477
478    for (MapIndices::iterator it = index_vert.begin(); it != index_vert.end(); ++it)
479    {
480        const osg::Geometry* pGeometry = geo.getDrawable(it->first.drawableIndex)->asGeometry();
481        unsigned int vertexIndex = it->first.vertexIndex;
482        unsigned int normalIndex = it->first.normalIndex;
483
484        const osg::Array * basevecs = pGeometry->getVertexArray();
485        assert(basevecs);
486        if (!basevecs || basevecs->getNumElements()==0)
487        {
488            //OSG_NOTIFY()
489            continue;
490        }
491        FbxVector4 vertex;
492        if (basevecs->getType() == osg::Array::Vec3ArrayType)
493        {
494            const osg::Vec3  & vec = (*static_cast<const osg::Vec3Array  *>(basevecs))[vertexIndex];
495            vertex.Set(vec.x(), vec.y(), vec.z());
496        }
497        else if (basevecs->getType() == osg::Array::Vec3dArrayType)
498        {
499            const osg::Vec3d & vec = (*static_cast<const osg::Vec3dArray *>(basevecs))[vertexIndex];
500            vertex.Set(vec.x(), vec.y(), vec.z());
501        }
502        else
503        {
504            OSG_NOTIFY(osg::FATAL) << "Vertex array is not Vec3 or Vec3d. Not implemented" << std::endl;
505            throw "Vertex array is not Vec3 or Vec3d. Not implemented";
506            //_succeeded = false;
507            //return;
508        }
509        mesh->SetControlPointAt(vertex, it->second);
510
511
512        const osg::Array * basenormals = pGeometry->getNormalArray();
513
514        if (basenormals && basenormals->getNumElements()>0)
515        {
516            FbxVector4 normal;
517            if (basenormals->getType() == osg::Array::Vec3ArrayType)
518            {
519                const osg::Vec3  & vec = (*static_cast<const osg::Vec3Array  *>(basenormals))[normalIndex];
520                normal.Set(vec.x(), vec.y(), vec.z(), 0);
521            }
522            else if (basenormals->getType() == osg::Array::Vec3dArrayType)
523            {
524                const osg::Vec3d & vec = (*static_cast<const osg::Vec3dArray *>(basenormals))[normalIndex];
525                normal.Set(vec.x(), vec.y(), vec.z(), 0);
526            }
527            else
528            {
529                OSG_NOTIFY(osg::FATAL) << "Normal array is not Vec3 or Vec3d. Not implemented" << std::endl;
530                throw "Normal array is not Vec3 or Vec3d. Not implemented";
531                //_succeeded = false;
532                //return;
533            }
534
535            //switch (pGeometry->getNormalBinding())
536            //{
537            //case osg::Geometry::BIND_PER_PRIMITIVE_SET:
538            //case osg::Geometry::BIND_PER_PRIMITIVE:
539            //case osg::Geometry::BIND_PER_VERTEX:
540            //    break;
541            //}
542            lLayerElementNormal->GetDirectArray().SetAt(it->second, normal);
543        }
544
545        if (texcoords)
546        {
547            const osg::Array * basetexcoords = pGeometry->getTexCoordArray(0);
548            if (basetexcoords && basetexcoords->getNumElements()>0)
549            {
550                FbxVector2 texcoord;
551                if (basetexcoords->getType() == osg::Array::Vec2ArrayType)
552                {
553                    const osg::Vec2 & vec = (*static_cast<const osg::Vec2Array *>(basetexcoords))[vertexIndex];
554                    texcoord.Set(vec.x(), vec.y());
555                }
556                else if (basetexcoords->getType() == osg::Array::Vec2dArrayType)
557                {
558                    const osg::Vec2d & vec = (*static_cast<const osg::Vec2dArray *>(basetexcoords))[vertexIndex];
559                    texcoord.Set(vec.x(), vec.y());
560                }
561                else
562                {
563                    OSG_NOTIFY(osg::FATAL) << "Texture coords array is not Vec2 or Vec2d. Not implemented" << std::endl;
564                    throw "Texture coords array is not Vec2 or Vec2d. Not implemented";
565                    //_succeeded = false;
566                    //return;
567                }
568
569                lUVDiffuseLayer->GetDirectArray().SetAt(it->second, texcoord);
570            }
571        }
572    }
573}
574
575void WriterNodeVisitor::buildFaces(const osg::Geode& geo,
576                                   ListTriangle&     listTriangles,
577                                   bool              texcoords)
578{
579    MapIndices index_vert;
580    FbxMesh* mesh = FbxMesh::Create(_pSdkManager, geo.getName().c_str());
581    _curFbxNode->AddNodeAttribute(mesh);
582    _curFbxNode->SetShadingMode(FbxNode::eTextureShading);
583    FbxLayer* lLayer = mesh->GetLayer(0);
584    if (lLayer == NULL)
585    {
586        mesh->CreateLayer();
587        lLayer = mesh->GetLayer(0);
588    }
589    setLayerTextureAndMaterial(mesh);
590    lLayer->GetTextures(FbxLayerElement::eTextureDiffuse)->GetIndexArray().SetCount(listTriangles.size());
591    lLayer->GetMaterials()->GetIndexArray().SetCount(listTriangles.size());
592
593    unsigned int i = 0;
594    for (ListTriangle::iterator it = listTriangles.begin(); it != listTriangles.end(); ++it, ++i) //Go through the triangle list to define meshs
595    {
596        if (it->first.material == -1)
597        {
598            mesh->BeginPolygon();
599        }
600        else
601        {
602            mesh->BeginPolygon(i);
603            lLayer->GetTextures(FbxLayerElement::eTextureDiffuse)->GetIndexArray().SetAt(i, it->first.material);
604            lLayer->GetMaterials()->GetIndexArray().SetAt(i, it->first.material);
605        }
606        addPolygon(mesh, index_vert, it->first, it->second);
607        mesh->EndPolygon();
608    }
609    setControlPointAndNormalsAndUV(geo, index_vert, texcoords, mesh);
610}
611
612void WriterNodeVisitor::createListTriangle(const osg::Geometry* geo,
613                                           ListTriangle&        listTriangles,
614                                           bool&                texcoords,
615                                           unsigned int&        drawable_n)
616{
617    unsigned int nbVertices = 0;
618    texcoords = false;
619    {
620        const osg::Array * vecs = geo->getVertexArray();
621        if (vecs)
622        {
623            nbVertices = vecs->getNumElements();
624
625            // Texture coords
626            const osg::Array * texvec = geo->getTexCoordArray(0);
627            if (texvec)
628            {
629                unsigned int nb = texvec->getNumElements();
630                if (nb == nbVertices) texcoords = true;
631                else
632                {
633                    OSG_WARN << "There are more/less texture coords than vertices! Ignoring texture coords.";
634                }
635            }
636        }
637    }
638
639    if (nbVertices==0) return;
640
641    int material = processStateSet(_currentStateSet.get());
642
643    PrimitiveIndexWriter pif(geo, listTriangles, drawable_n, material);
644    for (unsigned int iPrimSet = 0; iPrimSet < geo->getNumPrimitiveSets(); ++iPrimSet) //Fill the Triangle List
645    {
646        const osg::PrimitiveSet* ps = geo->getPrimitiveSet(iPrimSet);
647        const_cast<osg::PrimitiveSet*>(ps)->accept(pif);
648    }
649}
650
651void WriterNodeVisitor::apply(osg::Geode& node)
652{
653    FbxNode* parent = _curFbxNode;
654    FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, node.getName().empty() ? "DefaultName" : node.getName().c_str());
655    _curFbxNode->AddChild(nodeFBX);
656    _curFbxNode = nodeFBX;
657    unsigned int count = node.getNumDrawables();
658    ListTriangle listTriangles;
659    bool texcoords = false;
660    for (MaterialMap::iterator it = _materialMap.begin(); it != _materialMap.end(); ++it)
661        it->second.setIndex(-1);
662    _lastMaterialIndex = 0;
663    if(node.getStateSet()){
664        pushStateSet(node.getStateSet());
665    }
666    for (unsigned int i = 0; i < count; ++i)
667    {
668        const osg::Geometry* g = node.getDrawable(i)->asGeometry();
669        if (g != NULL)
670        {
671            pushStateSet(g->getStateSet());
672            createListTriangle(g, listTriangles, texcoords, i);
673            popStateSet(g->getStateSet());
674        }
675    }
676    if(node.getStateSet()){
677        popStateSet(node.getStateSet());
678    }
679    if (count > 0)
680    {
681        buildFaces(node, listTriangles, texcoords);
682    }
683    if (succeedLastApply())
684        traverse(node);
685    _curFbxNode = parent;
686}
687
688void WriterNodeVisitor::apply(osg::Group& node)
689{
690    FbxNode* parent = _curFbxNode;
691
692    FbxNode* nodeFBX = FbxNode::Create(_pSdkManager, node.getName().empty() ? "DefaultName" : node.getName().c_str());
693    _curFbxNode->AddChild(nodeFBX);
694    _curFbxNode = nodeFBX;
695    traverse(node);
696    _curFbxNode = parent;
697}
698
699void WriterNodeVisitor::apply(osg::MatrixTransform& node)
700{
701    FbxNode* parent = _curFbxNode;
702    _curFbxNode = FbxNode::Create(_pSdkManager, node.getName().empty() ? "DefaultName" : node.getName().c_str());
703    parent->AddChild(_curFbxNode);
704
705    const osg::Matrix& matrix = node.getMatrix();
706    osg::Vec3d pos, scl;
707    osg::Quat rot, so;
708
709    matrix.decompose(pos, rot, scl, so);
710    _curFbxNode->LclTranslation.Set(FbxDouble3(pos.x(), pos.y(), pos.z()));
711    _curFbxNode->LclScaling.Set(FbxDouble3(scl.x(), scl.y(), scl.z()));
712
713    FbxAMatrix mat;
714
715    FbxQuaternion q(rot.x(), rot.y(), rot.z(), rot.w());
716    mat.SetQ(q);
717    FbxVector4 vec4 = mat.GetR();
718
719    _curFbxNode->LclRotation.Set(FbxDouble3(vec4[0], vec4[1], vec4[2]));
720
721    traverse(node);
722    _curFbxNode = parent;
723}
724
725// end namespace pluginfbx
726}
Note: See TracBrowser for help on using the browser.