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

Revision 13557, 24.9 kB (checked in by robert, 4 weeks ago)

Moved widgets from VolumeEditorWidget? to TransferFunctionWidget?, and widget utilities into WidgetUtils?.

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