void SimpleDotVisitor::handle(osg::Geode &node, int id)
{
    std::stringstream label;

    label << "<top> " << node.className();
    if (!node.getName().empty())
    {
        label << "| " << node.getName();
    }

    drawNode(id, "record", "solid", label.str(), "brown", "white");
}
void OBJWriterNodeVisitor::apply( osg::Geode &node )
{
    pushStateSet(node.getStateSet());
    _nameStack.push_back(node.getName());
    unsigned int count = node.getNumDrawables();
    for ( unsigned int i = 0; i < count; i++ )
    {
        node.getDrawable( i )->accept(*this);
    }

    popStateSet(node.getStateSet());
    _nameStack.pop_back();
}
예제 #3
0
        virtual void apply(osg::Geode& node)
        {
            osg::Matrix mat = osg::computeLocalToWorld(getNodePath());

            if (m_options && (m_options->getOptionString() == "separateFiles"))
            {
                std::string sepFile = m_fout + i2s(counter) + "." + m_fout_ext;
                m_f = new osgDB::ofstream(sepFile.c_str());
            }

            if (node.getName().empty())
                *m_f << "solid " << counter << std::endl;
            else
                *m_f << "solid " << node.getName() << std::endl;

            for (unsigned int i = 0; i < node.getNumDrawables(); ++i)
            {
                osg::TriangleFunctor<PushPoints> tf;
                tf.m_stream = m_f;
                tf.m_mat = mat;
                tf.m_dontSaveNormals = m_dontSaveNormals;
                node.getDrawable(i)->accept(tf);
            }

            if (node.getName().empty())
                *m_f << "endsolid " << counter << std::endl;
            else
                *m_f << "endsolid " << node.getName() << std::endl;

            if (m_options && (m_options->getOptionString() == "separateFiles"))
            {
                m_f->close();
                delete m_f;
            }

            ++counter;
            traverse(node);
        }
void OBJWriterNodeVisitor::apply( osg::Geode &node )
{

    pushStateSet(node.getStateSet());
    _nameStack.push_back(node.getName());
    osg::Matrix m = osg::computeLocalToWorld(getNodePath());
    unsigned int count = node.getNumDrawables();
    for ( unsigned int i = 0; i < count; i++ )
    {
        osg::Geometry *g = node.getDrawable( i )->asGeometry();
        if ( g != NULL )
        {
            pushStateSet(g->getStateSet());

            processGeometry(g,m);

            popStateSet(g->getStateSet());
        }
    }


    popStateSet(node.getStateSet());
    _nameStack.pop_back();
}
void
FltExportVisitor::writeMesh( const osg::Geode& geode, const osg::Geometry& geom )
{
    enum DrawMode
    {
        SOLID_BACKFACE = 0,
        SOLID_NO_BACKFACE = 1,
        WIREFRAME_CLOSED = 2,
        WIREFRAME_NOT_CLOSED = 3,
        SURROUND_ALTERNATE_COLOR = 4,
        OMNIDIRECTIONAL_LIGHT = 8,
        UNIDIRECTIONAL_LIGHT = 9,
        BIDIRECTIONAL_LIGHT = 10
    };
    enum TemplateMode
    {
        FIXED_NO_ALPHA_BLENDING = 0,
        FIXED_ALPHA_BLENDING = 1,
        AXIAL_ROTATE_WITH_ALPHA_BLENDING = 2,
        POINT_ROTATE_WITH_ALPHA_BLENDING = 4
    };

    // const unsigned int TERRAIN_BIT      = 0x80000000u >> 0;
    //const unsigned int NO_COLOR_BIT     = 0x80000000u >> 1;
    //const unsigned int NO_ALT_COLOR_BIT = 0x80000000u >> 2;
    const unsigned int PACKED_COLOR_BIT = 0x80000000u >> 3;
    //const unsigned int FOOTPRINT_BIT    = 0x80000000u >> 4;    // Terrain culture cutout
    const unsigned int HIDDEN_BIT       = 0x80000000u >> 5;
    //const unsigned int ROOFLINE_BIT     = 0x80000000u >> 6;
    uint32 flags( PACKED_COLOR_BIT );
    if (geode.getNodeMask() == 0)
        flags |= HIDDEN_BIT;

    enum LightMode
    {
        FACE_COLOR = 0,
        VERTEX_COLOR = 1,
        FACE_COLOR_LIGHTING = 2,
        VERTEX_COLOR_LIGHTING = 3
    };
    int8 lightMode;
    osg::Vec4 packedColorRaw( 1., 1., 1., 1. );
    uint16 transparency( 0 );
    if (geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX)
    {
        if (isLit( geom ))
            lightMode = VERTEX_COLOR_LIGHTING;
        else
            lightMode = VERTEX_COLOR;
    }
    else
    {
        const osg::Vec4Array* c = dynamic_cast<const osg::Vec4Array*>( geom.getColorArray() );
        if (c && (c->size() > 0))
        {
            packedColorRaw = (*c)[0];
            transparency = flt::uint16((1. - packedColorRaw[3]) * (double)0xffff);
        }

        if (isLit( geom ))
            lightMode = FACE_COLOR_LIGHTING;
        else
            lightMode = FACE_COLOR;
    }
    uint32 packedColor;
    packedColor = (int)(packedColorRaw[3]*255) << 24 |
        (int)(packedColorRaw[2]*255) << 16 | (int)(packedColorRaw[1]*255) << 8 |
        (int)(packedColorRaw[0]*255);


    int8 drawType;
    osg::StateSet const* ss = getCurrentStateSet();

    {
        // Default to no facet culling
        drawType = SOLID_NO_BACKFACE;

        // If facet-culling isn't *dis*abled, check whether the CullFace mode is BACK
        if (ss->getMode(GL_CULL_FACE) & osg::StateAttribute::ON)
        {
            osg::CullFace const* cullFace = static_cast<osg::CullFace const*>(
                ss->getAttribute(osg::StateAttribute::CULLFACE) );
            if( cullFace->getMode() == osg::CullFace::BACK )
                drawType = SOLID_BACKFACE;

            // Note: OpenFlt can't handle FRONT or FRONT_AND_BACK settings, so ignore these(??)
        }
    }

    // Determine the material properties for the face
    int16 materialIndex( -1 );
    if (isLit( geom ))
    {
        osg::Material const* currMaterial = static_cast<osg::Material const*>(
            ss->getAttribute(osg::StateAttribute::MATERIAL) );
        materialIndex = _materialPalette->add(currMaterial);
    }

    // Get base texture
    int16 textureIndex( -1 );
    if (isTextured( 0, geom ))
    {
        const osg::Texture2D* texture = static_cast<const osg::Texture2D*>(
            ss->getTextureAttribute( 0, osg::StateAttribute::TEXTURE )  );
        if (texture != NULL)
            textureIndex = _texturePalette->add( 0, texture );
        else
        {
            std::string warning( "fltexp: Mesh is textured, but Texture2D StateAttribute is NULL." );
            osg::notify( osg::WARN ) << warning << std::endl;
            _fltOpt->getWriteResult().warn( warning );
        }
    }

    // Set the appropriate template mode based
    // on blending or Billboarding.
    TemplateMode templateMode( FIXED_NO_ALPHA_BLENDING );
    const osg::Billboard* bb = dynamic_cast< const osg::Billboard* >( &geode );
    if (bb != NULL)
    {
        if( bb->getMode() == osg::Billboard::AXIAL_ROT )
            templateMode = AXIAL_ROTATE_WITH_ALPHA_BLENDING;
        else
            templateMode = POINT_ROTATE_WITH_ALPHA_BLENDING;
    }
    else if ( ss->getMode( GL_BLEND ) & osg::StateAttribute::ON )
    {
        const osg::BlendFunc* bf = static_cast<const osg::BlendFunc*>(
            ss->getAttribute(osg::StateAttribute::BLENDFUNC) );
        if( (bf->getSource() == osg::BlendFunc::SRC_ALPHA) &&
            (bf->getDestination() == osg::BlendFunc::ONE_MINUS_SRC_ALPHA) )
            templateMode = FIXED_ALPHA_BLENDING;
    }


    uint16 length( 84 );
    IdHelper id( *this, geode.getName() );

    _records->writeInt16( (int16) MESH_OP );
    _records->writeUInt16( length );
    _records->writeID( id );
    _records->writeInt32( 0 ); // Reserved
    _records->writeInt32( 0 ); // IR color code
    _records->writeInt16( 0 ); // Relative priority
    _records->writeInt8( drawType ); // Draw type
    _records->writeInt8( 0 ); // Texture white
    _records->writeInt16( -1 ); // Color name index
    _records->writeInt16( -1 ); // Alternate color name index
    _records->writeInt8( 0 ); // Reserved
    _records->writeInt8( templateMode ); // Template (billboard)
    _records->writeInt16( -1 ); // Detail texture pattern index
    _records->writeInt16( textureIndex ); // Texture pattern index
    _records->writeInt16( materialIndex ); // Material index
    _records->writeInt16( 0 ); // Surface material code
    _records->writeInt16( 0 ); // Feature ID
    _records->writeInt32( 0 ); // IR material code
    _records->writeUInt16( transparency ); // Transparency
    _records->writeInt8( 0 ); // LOD generation control
    _records->writeInt8( 0 ); // Line style index
    _records->writeUInt32( flags ); // Flags
    _records->writeInt8( lightMode ); // Light mode
    _records->writeFill( 7 ); // Reserved
    _records->writeUInt32( packedColor ); // Packed color, primary
    _records->writeUInt32( 0x00ffffff ); // Packed color, alternate
    _records->writeInt16( -1 ); // Texture mapping index
    _records->writeInt16( 0 ); // Reserved
    _records->writeInt32( -1 ); // Primary color index
    _records->writeInt32( -1 ); // Alternate color index
    // Next four bytes:
    //   15.8: two 2-byte "reserved" fields
    //   15.9: one 4-byte "reserved" field
    _records->writeInt16( 0 ); // Reserved
    _records->writeInt16( -1 ); // Shader index
}
virtual void apply(osg::Geode &geode)
{
    if (geode.getName().compare(0, 9, "tessellate") == 0)
    {
        for (unsigned int i = 0; i < geode.getNumDrawables(); ++i)
        {
            osg::Geometry *geom = dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
            if (geom)
            {
                osg::ref_ptr<osgUtil::Tessellator> tscx = new osgUtil::Tessellator();
                if (tscx.valid())
                {
                    tscx->setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
                    if (geode.getName() == "tessellate")
                    {
                        // add a Tessellator so that this geom is retessellated when N is pressed
                        tscx->setBoundaryOnly(true);
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ABS_GEQ_TWO);      // so that first change in wind type makes the commonest tessellation - ODD.
                        geom->setUserData(tscx.get());
                    }
                    else if (geode.getName() == "tessellate odd")
                    {
                        // OR you can just apply the Tessellator once only, using these different types
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD);      // commonest tessellation - ODD.
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate odd bound")
                    {
                        tscx->setBoundaryOnly(true);
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ODD);      // tessellation - ODD, only show boundary.
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate positive")
                    {
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE);      // tessellation - pos.
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate positive bound")
                    {
                        tscx->setBoundaryOnly(true);
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE);
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate negative")
                    {
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_NEGATIVE);
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate negative bound")
                    {
                        tscx->setBoundaryOnly(true);
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_NEGATIVE);
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate nonzero")
                    {
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_NONZERO);
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate nonzero bound")
                    {
                        tscx->setBoundaryOnly(true);
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_NONZERO);
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate geq2")
                    {
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ABS_GEQ_TWO);
                        tscx->retessellatePolygons(*geom);
                    }
                    else if (geode.getName() == "tessellate geq2 bound")
                    {
                        tscx->setBoundaryOnly(true);
                        tscx->setWindingType(osgUtil::Tessellator::TESS_WINDING_ABS_GEQ_TWO);
                        tscx->retessellatePolygons(*geom);
                    }
                }
            }
        }
    }
}
예제 #7
0
void
WriterNodeVisitor::buildFaces(osg::Geode        & geo,
                              const osg::Matrix & mat,
                              ListTriangle      & listTriangles,
                              bool                texcoords)
{
    unsigned int nbTrianglesRemaining = listTriangles.size();
    unsigned int nbVerticesRemaining  = calcVertices(geo);        // May set _succeded to false
    if (!succeeded()) return;

    std::string name( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), true, "geo") );
    if (!succeeded()) return;
    Lib3dsMesh *mesh = lib3ds_mesh_new( name.c_str() );
    if (!mesh)
    {
        OSG_NOTIFY(osg::FATAL) << "Allocation error" << std::endl;
        _succeeded = false;
        return;
    }

    //copyOsgMatrixToLib3dsMatrix(mesh->matrix, mat);
    lib3ds_mesh_resize_faces   (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES));
    lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining,  MAX_VERTICES), texcoords ? 0 : 1, 0);        // Not mandatory but will allocate once a big block

    // Test if the mesh will be split and needs sorting
    if (nbVerticesRemaining >= MAX_VERTICES || nbTrianglesRemaining >= MAX_FACES)
    {
        OSG_INFO << "Sorting elements..." << std::endl;
        WriterCompareTriangle cmp(geo, nbVerticesRemaining);
        std::sort(listTriangles.begin(), listTriangles.end(), cmp);
    }

    MapIndices index_vert;
    unsigned int numFace = 0;        // Current face index
    for (ListTriangle::iterator it = listTriangles.begin(); it != listTriangles.end(); ++it) //Go through the triangle list to define meshs
    {
        // Test if the mesh will be full after adding a face
        if (index_vert.size()+3 >= MAX_VERTICES || numFace+1 >= MAX_FACES)
        {
            // Finnish mesh
            lib3ds_mesh_resize_faces   (mesh, numFace);
            //lib3ds_mesh_resize_vertices() will be called in buildMesh()
            buildMesh(geo, mat, index_vert, texcoords, mesh);        // May set _succeded to false
            if (!succeeded())
            {
                lib3ds_mesh_free(mesh);
                return;
            }

            // "Reset" values and start over a new mesh
            index_vert.clear();
            nbTrianglesRemaining -= numFace;
            numFace = 0;
            // We can't call a thing like "nbVerticesRemaining -= ...;" because points may be used multiple times.
            // [Sukender: An optimisation here would take too much time I think.]

            mesh = lib3ds_mesh_new( getUniqueName(geo.getName().empty() ? geo.className() : geo.getName(), true, "geo").c_str());
            if (!mesh)
            {
                OSG_NOTIFY(osg::FATAL) << "Allocation error" << std::endl;
                _succeeded = false;
                return;
            }
            lib3ds_mesh_resize_faces   (mesh, osg::minimum(nbTrianglesRemaining, MAX_FACES));
            lib3ds_mesh_resize_vertices(mesh, osg::minimum(nbVerticesRemaining,  MAX_VERTICES), texcoords ? 0 : 1, 0);        // Not mandatory but will allocate once a big block
        }
        Lib3dsFace & face = mesh->faces[numFace++];
        face.index[0] = getMeshIndexForGeometryIndex(index_vert, it->first.t1, it->second);
        face.index[1] = getMeshIndexForGeometryIndex(index_vert, it->first.t2, it->second);
        face.index[2] = getMeshIndexForGeometryIndex(index_vert, it->first.t3, it->second);
        face.material = it->first.material;
    }

    buildMesh(geo, mat, index_vert, texcoords, mesh);        // May set _succeded to false
    if (!succeeded())
    {
        lib3ds_mesh_free(mesh);
        return;
    }
}