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

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

From Sebastian Messerschmidt, "Added setColor function to modify an image based on texture coordinates, parallel to the getColor functionality."

  • 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.