void OBJWriterNodeVisitor::apply(osg::Geometry& geometry)
{
    osg::Matrix m = osg::computeLocalToWorld(getNodePath());

    pushStateSet(geometry.getStateSet());

    processGeometry(&geometry,m);

    popStateSet(geometry.getStateSet());
}
Exemple #2
0
void KdTreeBuilder::apply(osg::Geometry& geometry)
{
    osg::KdTree* previous = dynamic_cast<osg::KdTree*>(geometry.getShape());
    if (previous) return;

    osg::ref_ptr<osg::KdTree> kdTree = osg::clone(_kdTreePrototype.get());

    if (kdTree->build(_buildOptions, &geometry))
    {
        geometry.setShape(kdTree.get());
    }
}
bool
FltExportVisitor::atLeastOneMesh( const osg::Geometry& geom ) const
{
    // Return true if at least one PrimitiveSet mode will use a Mesh record.
    unsigned int jdx;
    for (jdx=0; jdx < geom.getNumPrimitiveSets(); jdx++)
    {
        const osg::PrimitiveSet* prim = geom.getPrimitiveSet( jdx );
        if( isMesh( prim->getMode() ) )
            return true;
    }
    // All PrimitiveSet modes will use Face records.
    return false;
}
void deleteFaces(osg::Geometry& geometry)
{
    geometry.removePrimitiveSet(0, geometry.getNumPrimitiveSets());

    auto _vertices = detail::getOrCreateVertexArray(geometry);
    auto _normals = detail::getOrCreateNormalArray(geometry);
    auto _colors = detail::getOrCreateColorArray(geometry);

    _vertices->clear();
    _normals->clear();
    _colors->clear();

    _vertices->dirty();
    _normals->dirty();
    _colors->dirty();
}
void DrawElementTypeSimplifier::simplify(osg::Geometry & geometry) const
{
    osg::Geometry::PrimitiveSetList & psl = geometry.getPrimitiveSetList();
    osg::Geometry::PrimitiveSetList::iterator it, end = psl.end();

    unsigned int max = 0;

    for (it = psl.begin(); it!=end; ++it)
    {
        switch ((*it)->getType())
        {
            case osg::PrimitiveSet::DrawElementsUShortPrimitiveType:
            {
                osg::DrawElementsUShort & de = *static_cast<osg::DrawElementsUShort*>(it->get());

                max = getMax<osg::DrawElementsUShort>(de);
                if (max < 255) *it = copy<osg::DrawElementsUShort, osg::DrawElementsUByte>(de);

                break;
            }
            case osg::PrimitiveSet::DrawElementsUIntPrimitiveType:
            {
                osg::DrawElementsUInt & de = *static_cast<osg::DrawElementsUInt*>(it->get());

                max = getMax<osg::DrawElementsUInt>(de);
                if (max < 256) *it = copy<osg::DrawElementsUInt, osg::DrawElementsUByte>(de);
                else if (max < 65536) *it = copy<osg::DrawElementsUInt, osg::DrawElementsUShort>(de);

                break;
            }
            default: break;
        }
    }
}
void
FltExportVisitor::writeUVList( int numVerts, const osg::Geometry& geom )
{
    unsigned int numLayers( 0 );
    uint32 flags( 0 );
    unsigned int idx;
    for( idx=1; idx<8; idx++)
    {
        if( isTextured( idx, geom ) )
        {
            flags |= LAYER_1 >> (idx-1);
            numLayers++;
        }
    }
    if( numLayers == 0 )
        return;

    uint16 length( 8 + (8*numLayers*numVerts) );

    _records->writeInt16( (int16) UV_LIST_OP );
    _records->writeUInt16( length );
    _records->writeInt32( flags );

    osg::Vec2 defaultCoord( 0., 0. );
    // const osg::StateSet* ss = getCurrentStateSet();
    for( idx=1; idx<8; idx++)
    {
        if( isTextured( idx, geom ) )
        {
            osg::Array* t = const_cast<osg::Array*>( geom.getTexCoordArray( idx ) );
            osg::ref_ptr<osg::Vec2Array> t2 = dynamic_cast<osg::Vec2Array*>( t );
            if (!t2.valid())
            {
                std::ostringstream warning;
                warning << "fltexp: No Texture2D for unit " << idx;
                osg::notify( osg::WARN ) << warning.str() << std::endl;
                _fltOpt->getWriteResult().warn( warning.str() );
                t2 = new osg::Vec2Array;
            }
            else if (static_cast<int>(t2->getNumElements()) != numVerts)
            {
                std::ostringstream warning;
                warning << "fltexp: Invalid number of texture coordinates for unit " << idx;
                osg::notify( osg::WARN ) << warning.str() << std::endl;
                _fltOpt->getWriteResult().warn( warning.str() );
            }

            const int size = t2->getNumElements();
            int vIdx;
            for( vIdx=0; vIdx<numVerts; vIdx++)
            {
                osg::Vec2& tc( defaultCoord );
                if (vIdx < size)
                    tc = (*t2)[ vIdx ];
                _records->writeFloat32( tc[0] );
                _records->writeFloat32( tc[1] );
            }
        }
    }
}
void
MeshSubdivider::run(osg::Geometry& geom, double granularity, GeoInterpolation interp)
{
    if ( geom.getNumPrimitiveSets() < 1 )
        return;

    subdivide( granularity, interp, geom, _world2local, _local2world, _maxElementsPerEBO );
}
void
createDAIGeometry( osg::Geometry& geom, int nInstances=1 )
{
    const float halfDimX( .5 );
    const float halfDimZ( .5 );

    osg::Vec3Array* v = new osg::Vec3Array;
    v->resize( 4 );
    geom.setVertexArray( v );

    // Geometry for a single quad.
    (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ );
    (*v)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ );
    (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ );
    (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ );

    // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances.
    geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) );
}
Exemple #9
0
        void setVertexAttrib(osg::Geometry& geom, const AttributeAlias& alias, osg::Array* array, bool normalize, osg::Array::Binding binding = osg::Array::BIND_UNDEFINED)
        {
            unsigned int index = alias.first;
            const std::string& name = alias.second;
            array->setName(name);
            if (binding!=osg::Array::BIND_UNDEFINED) array->setBinding(binding);
            array->setNormalize(normalize);
            geom.setVertexAttribArray(index, array);

            osg::notify(osg::NOTICE)<<"   vertex attrib("<<name<<", index="<<index<<", normalize="<<normalize<<" binding="<<binding<<")"<<std::endl;
        }
Exemple #10
0
 VertexAttribComparitor(osg::Geometry& geometry)
 {
     add(geometry.getVertexArray());
     add(geometry.getNormalArray());
     add(geometry.getColorArray());
     add(geometry.getSecondaryColorArray());
     add(geometry.getFogCoordArray());
     unsigned int i;
     for(i=0;i<geometry.getNumTexCoordArrays();++i)
     {
         add(geometry.getTexCoordArray(i));
     }
     for(i=0;i<geometry.getNumVertexAttribArrays();++i)
     {
         add(geometry.getVertexAttribArray(i));
     }
 }
 void apply(osg::Geometry& geom) {
     osg::Vec3Array* array = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
     if (array) {
         for (unsigned int i = 0; i < array->size(); i++) {
             double x,y,z;
             double lng = (*array)[i][0];
             double lat = (*array)[i][1];
             _coordinates->convertLatLongHeightToXYZ(osg::DegreesToRadians(lat), osg::DegreesToRadians(lng), 0, x, y, z);
             (*array)[i] = osg::Vec3(x,y,z);
         }
     }
 }
Exemple #12
0
MorphGeometry::MorphGeometry(const osg::Geometry& b) :
    osg::Geometry(b, osg::CopyOp::DEEP_COPY_ARRAYS),
    _dirty(false),
    _method(NORMALIZED),
    _morphNormals(true)
{
    setUseDisplayList(false);
    setUpdateCallback(new UpdateVertex);
    setDataVariance(osg::Object::DYNAMIC);
    setUseVertexBufferObjects(true);
    if (b.getInternalOptimizedGeometry())
        computeInternalOptimizedGeometry();
}
Exemple #13
0
void createDAIGeometry( osg::Geometry& geom, int nInstances=1 )
{
    const float halfDimX( .5 );
    const float halfDimZ( .5 );

    osg::Vec3Array* v = new osg::Vec3Array;
    v->resize( 4 );
    geom.setVertexArray( v );

    // Geometry for a single quad.
    (*v)[ 0 ] = osg::Vec3( -halfDimX, 0., 0. );
    (*v)[ 1 ] = osg::Vec3( halfDimX, 0., 0. );
    (*v)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ*2.0f );
    (*v)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ*2.0f );


	// create color array data (each corner of our triangle will have one color component)
    osg::Vec4Array* pColors = new osg::Vec4Array;
    pColors->push_back( osg::Vec4( 1.0f, 0.0f, 0.0f, 1.0f ) );
    pColors->push_back( osg::Vec4( 0.0f, 1.0f, 0.0f, 1.0f ) );
    pColors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f ) );
	pColors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 1.0f ) );
    geom.setColorArray( pColors );

	// make sure that our geometry is using one color per vertex
    geom.setColorBinding( osg::Geometry::BIND_PER_VERTEX );

    osg::Vec2Array* pTexCoords = new osg::Vec2Array( 4 );
    (*pTexCoords)[0].set( 0.0f, 0.0f );
    (*pTexCoords)[1].set( 1.0f, 0.0f );
    (*pTexCoords)[2].set( 1.0f, 1.0f );
    (*pTexCoords)[3].set( 0.0f, 1.0f );
    geom.setTexCoordArray( 0, pTexCoords );

    // Use the DrawArraysInstanced PrimitiveSet and tell it to draw 1024 instances.
    geom.addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, nInstances ) );
}
    bool InstancesManagerImpl::_initSkinning(osg::Geometry& geom, const image_data& id )
    {
        osg::Geometry& source = geom;
        osg::Vec3Array* positionSrc = dynamic_cast<osg::Vec3Array*>(source.getVertexArray());
        if (!positionSrc)
        {
            OSG_WARN << "InstancedAnimationManager no vertex array in the geometry " << geom.getName() << std::endl;
            return false;
        }

        osg::ref_ptr<osg::Program> cSkinningProg = creators::createProgram("skininst2").program; 
        cSkinningProg->setName("SkinningShader");

        const int attribIndex = cAttribSkinningBaseIndex;
        int nbAttribs = id.bonesWeights.size();
        for (int i = 0; i < nbAttribs; i++)
        {
            osg::ref_ptr<osg::Vec4Array> array = new osg::Vec4Array(osg::Array::BIND_PER_VERTEX);
            const image_data::weights_t&  w = id.bonesWeights[i];
            for (unsigned j = 0; j < w.size(); j+=id.divisor)
            {
                array->push_back(osg::Vec4(w.at(j),w.at(j+1),w.at(j+2),w.at(j+3)));
            }		

            std::stringstream ss;
            ss << "boneWeight" << i;
            cSkinningProg->addBindAttribLocation(ss.str(), attribIndex + i);
            geom.setVertexAttribArray(attribIndex + i, array);
            OSG_INFO << "set vertex attrib " << ss.str() << std::endl;
        }

        osg::ref_ptr<osg::StateSet> ss = geom.getOrCreateStateSet();
        ss->addUniform(new osg::Uniform("nbBonesPerVertex", id.bonesPerVertex));
        ss->setAttributeAndModes(cSkinningProg.get());

        return true;
    }
Exemple #15
0
void osgToy::FacetingVisitor::facet( osg::Geometry& geom )
{
    // count #surfaces, exit if none
    osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList();
    osg::Geometry::PrimitiveSetList::iterator itr;
    unsigned int numSurfacePrimitives=0;
    for(itr=primitives.begin();
        itr!=primitives.end();
        ++itr)
    {
        switch((*itr)->getMode())
        {
            case osg::PrimitiveSet::TRIANGLES:
            case osg::PrimitiveSet::TRIANGLE_STRIP:
            case osg::PrimitiveSet::TRIANGLE_FAN:
            case osg::PrimitiveSet::QUADS:
            case osg::PrimitiveSet::QUAD_STRIP:
            case osg::PrimitiveSet::POLYGON:
                ++numSurfacePrimitives;
                break;

            default:
                break;
        }
    }
    if (!numSurfacePrimitives) return;

    // exit if no vertices
    osg::Vec3Array *coords = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
    if (!coords || !coords->size()) return;
    
    // generate the normals
    osg::Vec3Array *normals = new osg::Vec3Array(coords->size());
    osg::TriangleIndexFunctor<FacetingOperator> ftif;
    ftif.set( coords, normals );
    geom.accept(ftif);

    geom.setNormalArray( normals );
    geom.setNormalIndices( geom.getVertexIndices() );
    geom.setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
    geom.dirtyDisplayList();
}
void createFaces(osg::Geometry& geometry, Polyhedron const& polyhedron, unsigned int faceMask = PolyhedronGeometry::All)
{
    osgUtil::Tessellator tessellator;
    tessellator.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS);
    tessellator.setWindingType(osgUtil::Tessellator::TESS_WINDING_NONZERO);

    auto _vertices = getOrCreateVertexArray(geometry);
    auto _normals = getOrCreateNormalArray(geometry);
    auto _colors = getOrCreateColorArray(geometry);

    osg::ref_ptr<osg::Vec3Array> vertices = createVertexArray(polyhedron);
    VertexIndexArrays polygons = createVertexIndexArrays(polyhedron);

    for (auto const& polygon: polygons)
    {
        assert(polygon && polygon->size() >= 3);

        if (!(faceMask & PolyhedronGeometry::FaceMaskFromSides(polygon->size()))) continue;

        auto first = _vertices->size();
        auto count = polygon->size();

        auto normal = detail::calculateNormal(vertices, polygon);
        auto color = detail::calculateColor(vertices, polygon);

        for (auto i = 0u; i < polygon->size(); ++i)
        {
            auto vertex = vertices->at(polygon->at(i));
            _vertices->push_back(vertex);
            _normals->push_back(normal);
            _colors->push_back(color);
        }

        geometry.addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, first, count));
    }

    tessellator.retessellatePolygons(geometry);
}
    void ShaderVisitor::apply(osg::Geometry& geometry)
    {
        bool needPop = (geometry.getStateSet() != NULL);
        if (geometry.getStateSet())
        {
            pushRequirements();
            applyStateSet(geometry.getStateSet(), geometry);
        }

        if (!mRequirements.empty())
        {
            const ShaderRequirements& reqs = mRequirements.back();

            if (mAllowedToModifyStateSets)
            {
                // make sure that all UV sets are there
                for (std::map<int, std::string>::const_iterator it = reqs.mTextures.begin(); it != reqs.mTextures.end(); ++it)
                {
                    if (geometry.getTexCoordArray(it->first) == NULL)
                        geometry.setTexCoordArray(it->first, geometry.getTexCoordArray(0));
                }
            }

            if (reqs.mTexStageRequiringTangents != -1 && mAllowedToModifyStateSets)
            {
                osg::ref_ptr<osgUtil::TangentSpaceGenerator> generator (new osgUtil::TangentSpaceGenerator);
                generator->generate(&geometry, reqs.mTexStageRequiringTangents);

                geometry.setTexCoordArray(7, generator->getTangentArray(), osg::Array::BIND_PER_VERTEX);
            }

            // TODO: find a better place for the stateset
            if (reqs.mShaderRequired || mForceShaders)
                createProgram(reqs, geometry);
        }

        if (needPop)
            popRequirements();
    }
OSG::Action::ResultE changeGeo(OSG::Node *node)
{   
    OSG::Geometry *geo = dynamic_cast<OSG::Geometry *>(node->getCore());
    
    if(geo == NULL)
        return OSG::Action::Continue;


    OSG::GeoColor3fPropertyRefPtr col = dynamic_cast<OSG::GeoColor3fProperty *>(geo->getColors());
    if(col == NULL)
    {
        col = OSG::GeoColor3fProperty::create();

        col->resize(geo->getPositions()->getSize());
        
        // Change the geometry to use the new colors
        geo->setColors(col);
        // If multi-indexed, make the colors use the same index as
        // the geometry
        if(geo->getIndex(OSG::Geometry::PositionsIndex) != NULL)
        {
            geo->setIndex(geo->getIndex(OSG::Geometry::PositionsIndex),
                          OSG::Geometry::ColorsIndex                   );
        }
    }
    
    OSG::Real32 size = col->getSize();
    for(OSG::UInt32 i = 0; i < size; ++i)
    {
        OSG::Color3f c;
        c[0] = 0.0f;
        c[1] = static_cast<OSG::Real32>(i) / size;
        c[2] = 0.0f;
        col->setValue(c, i);
    }
    
    return OSG::Action::Continue; 
}
Exemple #19
0
void
GeometryValidator::apply(osg::Geometry& geom)
{
    unsigned numVerts = geom.getVertexArray()->getNumElements();

    if ( geom.getColorArray() )
    {
        if ( geom.getColorBinding() == osg::Geometry::BIND_OVERALL && geom.getColorArray()->getNumElements() != 1 )
        {
            OE_WARN << "Color: BIND_OVERALL with wrong number of elements" << std::endl;
        }
        else if ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getColorArray()->getNumElements() != numVerts )
        {
            OE_WARN << "Color: BIND_PER_VERTEX with color.size != verts.size" << std::endl;
        }
    }

    if ( geom.getNormalArray() )
    {
        if ( geom.getNormalBinding() == osg::Geometry::BIND_OVERALL && geom.getNormalArray()->getNumElements() != 1 )
        {
            OE_WARN << "Normal: BIND_OVERALL with wrong number of elements" << std::endl;
        }
        else if ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX && geom.getNormalArray()->getNumElements() != numVerts )
        {
            OE_WARN << "Normal: BIND_PER_VERTEX with color.size != verts.size" << std::endl;
        }
    }

    const osg::Geometry::PrimitiveSetList& plist = geom.getPrimitiveSetList();

    for( osg::Geometry::PrimitiveSetList::const_iterator p = plist.begin(); p != plist.end(); ++p )
    {
        osg::PrimitiveSet* pset = p->get();

        osg::DrawElementsUByte* de_byte = dynamic_cast<osg::DrawElementsUByte*>(pset);
        if ( de_byte )
        {
            if ( numVerts > 0xFF )
            {
                OE_WARN << "DrawElementsUByte used when numVerts > 255 (" << numVerts << ")" << std::endl;
            }
            validateDE(de_byte, 0xFF, numVerts );
        }

        osg::DrawElementsUShort* de_short = dynamic_cast<osg::DrawElementsUShort*>(pset);
        if ( de_short )
        {
            if ( numVerts > 0xFFFF )
            {
                OE_WARN << "DrawElementsUShort used when numVerts > 65535 (" << numVerts << ")" << std::endl;
            }
            validateDE(de_short, 0xFFFF, numVerts );
        }

        osg::DrawElementsUInt* de_int = dynamic_cast<osg::DrawElementsUInt*>(pset);
        if ( de_int )
        {
            validateDE(de_int, 0xFFFFFFFF, numVerts );
        }
    }
}
Exemple #20
0
void
MeshConsolidator::convertToTriangles( osg::Geometry& geom, bool force )
{
    if ( !force && !canOptimize(geom) )
        return;

    osg::Geometry::PrimitiveSetList& primSets = geom.getPrimitiveSetList();
    osg::Geometry::PrimitiveSetList  triSets, nonTriSets;

    for( osg::Geometry::PrimitiveSetList::iterator i = primSets.begin(); i != primSets.end(); ++i )
    {
        osg::PrimitiveSet* pset = i->get();
        switch( pset->getMode() )
        {
        case osg::PrimitiveSet::TRIANGLES:
        case osg::PrimitiveSet::TRIANGLE_STRIP:
        case osg::PrimitiveSet::TRIANGLE_FAN:
        case osg::PrimitiveSet::QUADS:
        case osg::PrimitiveSet::QUAD_STRIP:
        case osg::PrimitiveSet::POLYGON:
            triSets.push_back( pset );
            break;

        default:
            nonTriSets.push_back( pset );
        }
    }

    if ( triSets.size() > 0 )
    {
        // we are assuming at this point that all the primitive sets in a single geometry
        // share a single user data structure.
        osg::Referenced* sharedUserData = triSets[0]->getUserData();

        osg::Array* vertexArray = geom.getVertexArray();
        unsigned numVerts = vertexArray->getNumElements();
        osg::Geometry::PrimitiveSetList newPrimSets;

        if ( numVerts < 0x100 )
        {
            osg::TriangleIndexFunctor< Collector<osg::DrawElementsUByte> > collector;
            collector._newPrimSets = &newPrimSets;
            collector._maxSize = 0xFF;
            geom.accept( collector );
        }
        else if ( numVerts < 0x10000 )
        {
            osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector;
            collector._newPrimSets = &newPrimSets;
            collector._maxSize = 0xFFFF;
            geom.accept( collector );
        }
        else
        {
#ifdef OSG_GLES2_AVAILABLE
            // GLES only supports UShort, not UInt
            osg::TriangleIndexFunctor< Collector<osg::DrawElementsUShort> > collector;
            collector._newPrimSets = &newPrimSets;
            collector._maxSize = 0xFFFF;
            geom.accept( collector );
#else
            osg::TriangleIndexFunctor< Collector<osg::DrawElementsUInt> > collector;
            collector._newPrimSets = &newPrimSets;
            collector._maxSize = 0xFFFFFFFF;
            geom.accept( collector );
#endif
        }

        for( osg::Geometry::PrimitiveSetList::iterator i = newPrimSets.begin(); i != newPrimSets.end(); ++i )
        {
            i->get()->setUserData( sharedUserData );
            nonTriSets.push_back( i->get() );
        }
    }

    geom.setPrimitiveSetList( nonTriSets );
}
void
FltExportVisitor::writeLocalVertexPool( const osg::Geometry& geom )
{
    // Attribute Mask
    static const unsigned int HAS_POSITION      = 0x80000000u >> 0;
    // static const unsigned int HAS_COLOR_INDEX   = 0x80000000u >> 1;
    static const unsigned int HAS_RGBA_COLOR    = 0x80000000u >> 2;
    static const unsigned int HAS_NORMAL        = 0x80000000u >> 3;
    static const unsigned int HAS_BASE_UV       = 0x80000000u >> 4;
    static const unsigned int HAS_UV_LAYER1     = 0x80000000u >> 5;
    static const unsigned int HAS_UV_LAYER2     = 0x80000000u >> 6;
    static const unsigned int HAS_UV_LAYER3     = 0x80000000u >> 7;
    static const unsigned int HAS_UV_LAYER4     = 0x80000000u >> 8;
    static const unsigned int HAS_UV_LAYER5     = 0x80000000u >> 9;
    static const unsigned int HAS_UV_LAYER6     = 0x80000000u >> 10;
    static const unsigned int HAS_UV_LAYER7     = 0x80000000u >> 11;

    const osg::Array* v = geom.getVertexArray();
    uint32 numVerts( v->getNumElements() );
    osg::ref_ptr< const osg::Vec3dArray > v3 = VertexPaletteManager::asVec3dArray( v, numVerts );
    if (!v3)
    {
        std::string warning( "fltexp: writeLocalVertexPool: VertexArray is not Vec3Array." );
        osg::notify( osg::WARN ) << warning << std::endl;
        _fltOpt->getWriteResult().warn( warning );
        return;
    }

    // Compute attribute bits and vertex size.
    const osg::Array* c = geom.getColorArray();
    const osg::Array* n = geom.getNormalArray();
    const osg::Array* t = geom.getTexCoordArray( 0 );

    osg::ref_ptr< const osg::Vec4Array > c4 = VertexPaletteManager::asVec4Array( c, numVerts );
    osg::ref_ptr< const osg::Vec3Array > n3 = VertexPaletteManager::asVec3Array( n, numVerts );
    osg::ref_ptr< const osg::Vec2Array > t2 = VertexPaletteManager::asVec2Array( t, numVerts );
    if (c && !c4)
        return;
    if (n && !n3)
        return;
    if (t && !t2)
        return;

    std::vector< osg::ref_ptr< const osg::Vec2Array > > mtc;
    mtc.resize( 8 );
    int unit=1;
    for( ;unit<8; unit++)
        mtc[ unit ] = VertexPaletteManager::asVec2Array( geom.getTexCoordArray( unit ), numVerts );

    uint32 attr( HAS_POSITION );
    unsigned int vertSize( sizeof( float64 ) * 3 );

    if ( ( c4 != NULL ) && ( geom.getColorBinding() == osg::Geometry::BIND_PER_VERTEX) )
    {
        attr |= HAS_RGBA_COLOR;
        vertSize += sizeof( unsigned int );
    }
    if ( ( n3 != NULL ) && ( geom.getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) )
    {
        attr |= HAS_NORMAL;
        vertSize += ( sizeof( float32 ) * 3 );
    }
    if ( t2 != NULL )
    {
        attr |= HAS_BASE_UV;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    // Add multitex
    if (isTextured( 1, geom ))
    {
        attr |= HAS_UV_LAYER1;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    if (isTextured( 2, geom ))
    {
        attr |= HAS_UV_LAYER2;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    if (isTextured( 3, geom ))
    {
        attr |= HAS_UV_LAYER3;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    if (isTextured( 4, geom ))
    {
        attr |= HAS_UV_LAYER4;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    if (isTextured( 5, geom ))
    {
        attr |= HAS_UV_LAYER5;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    if (isTextured( 6, geom ))
    {
        attr |= HAS_UV_LAYER6;
        vertSize += ( sizeof( float32 ) * 2 );
    }
    if (isTextured( 7, geom ))
    {
        attr |= HAS_UV_LAYER7;
        vertSize += ( sizeof( float32 ) * 2 );
    }

    unsigned int maxVerts = (0xffff - 12) / vertSize;
    unsigned int thisVertCount = (maxVerts > numVerts) ? numVerts : maxVerts;
    unsigned int currentIndexLimit = maxVerts;
    uint16 length( 12 + (vertSize * thisVertCount) );


    _records->writeInt16( (int16) LOCAL_VERTEX_POOL_OP );
    _records->writeUInt16( length );
    _records->writeUInt32( numVerts ); // number of vertices
    _records->writeUInt32( attr ); // attribute bits

    unsigned int idx;
    for( idx=0; idx<numVerts; idx++ )
    {
        _records->writeVec3d( (*v3)[ idx ] );

        if (attr & HAS_RGBA_COLOR)
        {
            osg::Vec4 color = (*c4)[ idx ];
            unsigned int packedColor = (int)(color[3]*255) << 24 |
                (int)(color[2]*255) << 16 | (int)(color[1]*255) << 8 |
                (int)(color[0]*255);
            _records->writeUInt32( packedColor );
        }

        if (attr & HAS_NORMAL)
            _records->writeVec3f( (*n3)[ idx ] );

        if (attr & HAS_BASE_UV)
            _records->writeVec2f( (*t2)[ idx ] );

        if (attr & HAS_UV_LAYER1)
            _records->writeVec2f( (*mtc[1])[ idx ] );
        if (attr & HAS_UV_LAYER2)
            _records->writeVec2f( (*mtc[2])[ idx ] );
        if (attr & HAS_UV_LAYER3)
            _records->writeVec2f( (*mtc[3])[ idx ] );
        if (attr & HAS_UV_LAYER4)
            _records->writeVec2f( (*mtc[4])[ idx ] );
        if (attr & HAS_UV_LAYER5)
            _records->writeVec2f( (*mtc[5])[ idx ] );
        if (attr & HAS_UV_LAYER6)
            _records->writeVec2f( (*mtc[6])[ idx ] );
        if (attr & HAS_UV_LAYER7)
            _records->writeVec2f( (*mtc[7])[ idx ] );


        // Handle continuation record if necessary.
        if ( (idx+1 == currentIndexLimit) && (idx+1 < numVerts) )
        {
            currentIndexLimit += maxVerts;
            unsigned int remaining( numVerts - (idx+1) );
            thisVertCount = (maxVerts > remaining) ? remaining : maxVerts;
            writeContinuationRecord( (vertSize * thisVertCount) );
        }
    }
}
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
}
Exemple #23
0
bool Primitive_readLocalData(Input& fr,osg::Geometry& geom)
{
    bool iteratorAdvanced = false;
    bool firstMatched = false;
    if ((firstMatched = fr.matchSequence("DrawArrays %w %i %i %i")) ||
         fr.matchSequence("DrawArrays %w %i %i") )
    {

        GLenum mode;
        Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode);

        int first;
        fr[2].getInt(first);

        int count;
        fr[3].getInt(count);

        int numInstances = 0;
        if (firstMatched)
        {
            fr[4].getInt(numInstances);
            fr += 5;
        }
        else
        {
            fr += 4;
        }

        geom.addPrimitiveSet(new DrawArrays(mode, first, count, numInstances));


        iteratorAdvanced = true;

    }
    else if ((firstMatched = fr.matchSequence("DrawArrayLengths %w %i %i %i {")) ||
         fr.matchSequence("DrawArrayLengths %w %i %i {") )
    {
        int entry = fr[1].getNoNestedBrackets();

        GLenum mode;
        Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode);

        int first;
        fr[2].getInt(first);

        int capacity;
        fr[3].getInt(capacity);

        int numInstances = 0;
        if (firstMatched)
        {
            fr[4].getInt(numInstances);
            fr += 6;
        }
        else
        {
            fr += 5;
        }

        DrawArrayLengths* prim = new DrawArrayLengths;
        prim->setMode(mode);
        prim->setNumInstances(numInstances);
        prim->setFirst(first);
        prim->reserve(capacity);

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            unsigned int i;
            if (fr[0].getUInt(i))
            {
                prim->push_back(i);
                ++fr;
            }
        }
         ++fr;

         geom.addPrimitiveSet(prim);

        iteratorAdvanced = true;
    }
    else if ((firstMatched = fr.matchSequence("DrawElementsUByte %w %i %i {")) ||
         fr.matchSequence("DrawElementsUByte %w %i {"))
    {
        int entry = fr[1].getNoNestedBrackets();

        GLenum mode;
        Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode);

        int capacity;
        fr[2].getInt(capacity);

        int numInstances = 0;
        if (firstMatched)
        {
            fr[3].getInt(numInstances);
            fr += 5;
        }
        else
        {
            fr += 4;
        }

        DrawElementsUByte* prim = new DrawElementsUByte;
        prim->setMode(mode);
        prim->setNumInstances(numInstances);
        prim->reserve(capacity);

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            unsigned int i;
            if (fr[0].getUInt(i))
            {
                prim->push_back(i);
                ++fr;
            }
        }
         ++fr;

         geom.addPrimitiveSet(prim);

        iteratorAdvanced = true;
    }
    else if ((firstMatched = fr.matchSequence("DrawElementsUShort %w %i %i {")) ||
         fr.matchSequence("DrawElementsUShort %w %i {"))
    {
        int entry = fr[1].getNoNestedBrackets();

        GLenum mode;
        Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode);

        int capacity;
        fr[2].getInt(capacity);

        int numInstances = 0;
        if (firstMatched)
        {
            fr[3].getInt(numInstances);
            fr += 5;
        }
        else
        {
            fr += 4;
        }

        DrawElementsUShort* prim = new DrawElementsUShort;
        prim->setMode(mode);
        prim->setNumInstances(numInstances);
        prim->reserve(capacity);

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            unsigned int i;
            if (fr[0].getUInt(i))
            {
                prim->push_back(i);
                ++fr;
            }
        }
         ++fr;

         geom.addPrimitiveSet(prim);

        iteratorAdvanced = true;
    }
    else if ((firstMatched = fr.matchSequence("DrawElementsUInt %w %i %i {")) ||
              fr.matchSequence("DrawElementsUInt %w %i {"))
    {
        int entry = fr[1].getNoNestedBrackets();

        GLenum mode;
        Geometry_matchPrimitiveModeStr(fr[1].getStr(),mode);

        int capacity;
        fr[2].getInt(capacity);

        int numInstances = 0;
        if (firstMatched)
        {
            fr[3].getInt(numInstances);
            fr += 5;
        }
        else
        {
            fr += 4;
        }

        DrawElementsUInt* prim = new DrawElementsUInt;
        prim->setMode(mode);
        prim->setNumInstances(numInstances);
        prim->reserve(capacity);

        while (!fr.eof() && fr[0].getNoNestedBrackets()>entry)
        {
            unsigned int i;
            if (fr[0].getUInt(i))
            {
                prim->push_back(i);
                ++fr;
            }
        }
         ++fr;

         geom.addPrimitiveSet(prim);

        iteratorAdvanced = true;
    }

    return iteratorAdvanced;
}
Exemple #24
0
void
GeometryValidator::apply(osg::Geometry& geom)
{
    if ( geom.getVertexArray() == 0L )
    {
        OE_NOTICE << LC << "NULL vertex array!!\n";
        return;
    }

    unsigned numVerts = geom.getVertexArray()->getNumElements();
    if ( numVerts == 0 )
    {
        OE_NOTICE << LC << "No verts!! name=" << geom.getName() << "\n";
        return;
    }

    std::set<osg::BufferObject*> _vbos;

    osg::Geometry::ArrayList arrays;
    geom.getArrayList(arrays);

    for(unsigned i=0; i<arrays.size(); ++i)
    {
        osg::Array* a = arrays[i].get();
        if ( a )
        {
            if ( a->getBinding() == a->BIND_OVERALL && a->getNumElements() != 1 )
            {
                OE_NOTICE << LC << "Found an array with BIND_OVERALL and size <> 1\n";
            }
            else if ( a->getBinding() == a->BIND_PER_VERTEX && a->getNumElements() != numVerts )
            {
                OE_NOTICE << LC << "Found BIND_PER_VERTEX with wrong number of elements (expecting " << numVerts << "; found " << a->getNumElements() << ")\n";
            }

            _vbos.insert( a->getVertexBufferObject() );
        }
        else
        {
            OE_NOTICE << LC << "Found a NULL array\n";
        }

    }

    if ( _vbos.size() != 1 )
    {
        OE_NOTICE << LC << "Found a Geometry that uses more than one VBO (non-optimal sharing)\n";
    }

    const osg::Geometry::PrimitiveSetList& plist = geom.getPrimitiveSetList();
    
    std::set<osg::BufferObject*> _ebos;

    for( osg::Geometry::PrimitiveSetList::const_iterator p = plist.begin(); p != plist.end(); ++p )
    {
        osg::PrimitiveSet* pset = p->get();

        osg::DrawArrays* da = dynamic_cast<osg::DrawArrays*>(pset);
        if ( da )
        {
            if ( da->getFirst() >= numVerts )
            {
                OE_NOTICE << LC << "DrawArrays: first > numVerts\n";
            }
            if ( da->getFirst()+da->getCount() > numVerts )
            {
                OE_NOTICE << LC << "DrawArrays: first/count out of bounds\n";
            }
            if ( da->getCount() < 1 )
            {
                OE_NOTICE << LC << "DrawArrays: count is zero\n";
            }
        }

        bool isDe = pset->getDrawElements() != 0L;

        osg::DrawElementsUByte* de_byte = dynamic_cast<osg::DrawElementsUByte*>(pset);
        if ( de_byte )
        {
            validateDE(de_byte, 0xFF, numVerts );
            _ebos.insert( de_byte->getElementBufferObject() );
        }

        osg::DrawElementsUShort* de_short = dynamic_cast<osg::DrawElementsUShort*>(pset);
        if ( de_short )
        {
            validateDE(de_short, 0xFFFF, numVerts );
            _ebos.insert( de_short->getElementBufferObject() );
        }

        osg::DrawElementsUInt* de_int = dynamic_cast<osg::DrawElementsUInt*>(pset);
        if ( de_int )
        {
            validateDE(de_int, 0xFFFFFFFF, numVerts );
            _ebos.insert( de_int->getElementBufferObject() );
        }

        if ( pset->getNumIndices() == 0 )
        {
            OE_NOTICE << LC << "Primset: num elements = 0; class=" << pset->className() << ", name=" << pset->getName() << "\n";
        }
        else if ( pset->getType() >= GL_TRIANGLES && pset->getNumIndices() < 3 )
        {
            OE_NOTICE << LC << "Primset: not enough indicies for surface prim type\n";
        }
        else if ( pset->getType() >= GL_LINE_STRIP && pset->getNumIndices() < 2 )
        {
            OE_NOTICE << LC << "Primset: not enough indicies for linear prim type\n";
        }
        else if ( isDe && pset->getType() == GL_LINES && pset->getNumIndices() % 2 != 0 )
        {
            OE_NOTICE << LC << "Primset: non-even index count for GL_LINES\n";
        }
    }

    if ( _ebos.size() != 1 )
    {
        OE_NOTICE << LC << "Found a Geometry that uses more than one EBO (non-optimal sharing)\n";
    }
}
Exemple #25
0
	nave(int x,int y, int z, int tamaño)
		{
		pyramidGeode = new osg::Geode();
		pyramidGeometry = new osg::Geometry();
		pyramidGeode->addDrawable(pyramidGeometry);
		
		osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
	
	//0-4
	pyramidVertices->push_back( osg::Vec3(       x,       y,       z) ); // front left
    //1-5
	pyramidVertices->push_back( osg::Vec3(tamaño+x,       y,       z) ); // front right
    //2-6
	pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y,       z) ); // back right
    //3-7
	pyramidVertices->push_back( osg::Vec3(       x,tamaño+y,       z) ); // back left
	//4-0
    pyramidVertices->push_back( osg::Vec3(	     x,		  y,tamaño+z) ); // peak
    //5-1
	pyramidVertices->push_back( osg::Vec3(tamaño+x,       y,tamaño+z) ); // front right
    //6-2
	pyramidVertices->push_back( osg::Vec3(tamaño+x,tamaño+y,tamaño+z) ); // back right
    //7-3
	pyramidVertices->push_back( osg::Vec3(       x,tamaño+y,tamaño+z) ); // back left	
		
	pyramidGeometry->setVertexArray( pyramidVertices );
		
		osg::DrawElementsUInt* pyramidBase =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidBase->push_back(3);
    pyramidBase->push_back(2);
    pyramidBase->push_back(1);
    pyramidBase->push_back(0);
    pyramidGeometry->addPrimitiveSet(pyramidBase);

	osg::DrawElementsUInt* pyramidTop =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidTop->push_back(4);
    pyramidTop->push_back(5);
    pyramidTop->push_back(6);
    pyramidTop->push_back(7);
    pyramidGeometry->addPrimitiveSet(pyramidTop);

    //Repeat the same for each of the four sides. Again, vertices are
    //specified in counter-clockwise order.

    osg::DrawElementsUInt* pyramidFaceOne =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidFaceOne->push_back(0);
    pyramidFaceOne->push_back(1);
	pyramidFaceOne->push_back(5);
    pyramidFaceOne->push_back(4);
	pyramidGeometry->addPrimitiveSet(pyramidFaceOne);

    osg::DrawElementsUInt* pyramidFaceTwo =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidFaceTwo->push_back(1);
    pyramidFaceTwo->push_back(2);
    pyramidFaceTwo->push_back(6);
	pyramidFaceTwo->push_back(5);
    pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);

    osg::DrawElementsUInt* pyramidFaceThree =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidFaceThree->push_back(2);
    pyramidFaceThree->push_back(3);
    pyramidFaceThree->push_back(7);
	pyramidFaceThree->push_back(6);
    pyramidGeometry->addPrimitiveSet(pyramidFaceThree);

    osg::DrawElementsUInt* pyramidFaceFour =
        new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
    pyramidFaceFour->push_back(3);
    pyramidFaceFour->push_back(0);
    pyramidFaceThree->push_back(4);
	pyramidFaceFour->push_back(7);
    pyramidGeometry->addPrimitiveSet(pyramidFaceFour);

    //Declare and load an array of Vec4 elements to store colors.

    osg::Vec4Array* colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red
    colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 1 green
    colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 2 blue
    colors->push_back(osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); //index 3 white
    colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red
	 colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red
	  colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red
	   colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 4 red

    //The next step is to associate the array of colors with the geometry,
    //assign the color indices created above to the geometry and set the
    //binding mode to _PER_VERTEX.

    pyramidGeometry->setColorArray(colors);
    pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
	
		};
bool
Tessellator::tessellateGeometry(osg::Geometry &geom)
{
    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());

    if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return false;

    // copy the original primitive set list
    osg::Geometry::PrimitiveSetList originalPrimitives = geom.getPrimitiveSetList();

    // clear the primitive sets
    unsigned int nprimsetoriginal= geom.getNumPrimitiveSets();
    if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal);

    bool success = true;
    for (unsigned int i=0; i < originalPrimitives.size(); i++)
    {
        osg::ref_ptr<osg::PrimitiveSet> primitive = originalPrimitives[i].get();

        if (primitive->getMode()==osg::PrimitiveSet::POLYGON || primitive->getMode()==osg::PrimitiveSet::LINE_LOOP)
        {
            if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType)
            {
                osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get());
                unsigned int first = drawArrayLengths->getFirst();
                for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin();
                    itr!=drawArrayLengths->end();
                    ++itr)
                {
                    unsigned int last = first + *itr;
                    osg::PrimitiveSet* newPrimitive = tessellatePrimitive(first, last, vertices);
                    if (newPrimitive)
                    {
                        geom.addPrimitiveSet(newPrimitive);
                    }
                    else
                    {
                        // tessellation failed, add old primitive set back
                        geom.addPrimitiveSet(primitive);
                        success = false;
                    }

                    first = last;
                }
            }
            else
            {
                if (primitive->getNumIndices()>=3)
                {
                    osg::PrimitiveSet* newPrimitive = tessellatePrimitive(primitive.get(), vertices);
                    if (newPrimitive)
                    {
                        geom.addPrimitiveSet(newPrimitive);
                    }
                    else
                    {
                        // tessellation failed, add old primitive set back
                        geom.addPrimitiveSet(primitive);
                        success = false;
                    }
                }
            }
        }
        else
        {
            //
            // TODO: handle more primitive modes
            //
        }
    }

    return success;
}
void Tessellator::collectTessellation(osg::Geometry &geom, unsigned int originalIndex)
{
    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
    VertexPtrToIndexMap vertexPtrToIndexMap;
    
    // populate the VertexPtrToIndexMap.
    for(unsigned int vi=0;vi<vertices->size();++vi)
    {
        vertexPtrToIndexMap[&((*vertices)[vi])] = vi;
    }
    
    handleNewVertices(geom, vertexPtrToIndexMap);
    
    // we don't properly handle per primitive and per primitive_set bindings yet
    // will need to address this soon. Robert Oct 2002.
    {
        osg::Vec3Array* normals = NULL; // GWM Sep 2002 - add normals for extra facets
        int iprim=0;
        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE ||
            geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET)
        {
            normals = dynamic_cast<osg::Vec3Array*>(geom.getNormalArray()); // GWM Sep 2002
        }
        // GWM Dec 2003 - needed to add colours for extra facets
        osg::Vec4Array* cols4 = NULL; // GWM Dec 2003 colours are vec4
        osg::Vec3Array* cols3 = NULL; // GWM Dec 2003 colours are vec3
        if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE ||
              geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET)
        {
              Array* colours = geom.getColorArray(); // GWM Dec 2003 - need to duplicate face colours
              switch (colours->getType()) {
              case osg::Array::Vec4ArrayType:
                  cols4=dynamic_cast<osg::Vec4Array *> (colours);
                  break;
              case osg::Array::Vec3ArrayType:
                  cols3=dynamic_cast<osg::Vec3Array *> (colours);
                  break;
              default:
                  break;
              }
              
        }
        // GWM Dec 2003 - these holders need to go outside the loop to 
        // retain the flat shaded colour &/or normal for each tessellated polygon
        osg::Vec3 norm(0.0f,0.0f,0.0f);
        osg::Vec4 primCol4(0.0f,0.0f,0.0f,1.0f);
        osg::Vec3 primCol3(0.0f,0.0f,0.0f);

        for(PrimList::iterator primItr=_primList.begin();
        primItr!=_primList.end();
        ++primItr, ++_index)
        {
              Prim* prim=primItr->get();
              int ntris=0;

              if(vertexPtrToIndexMap.size() <= 255)
              {
                  osg::DrawElementsUByte* elements = new osg::DrawElementsUByte(prim->_mode);
                  for(Prim::VecList::iterator vitr=prim->_vertices.begin();
                  vitr!=prim->_vertices.end();
                  ++vitr)
                {
                    elements->push_back(vertexPtrToIndexMap[*vitr]);
                }

                  // add to the drawn primitive list.
                  geom.addPrimitiveSet(elements);
                  ntris=elements->getNumIndices()/3;
              }
              else if(vertexPtrToIndexMap.size() > 255 && vertexPtrToIndexMap.size() <= 65535)
              {
                  osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(prim->_mode);
                  for(Prim::VecList::iterator vitr=prim->_vertices.begin();
                    vitr!=prim->_vertices.end();
                    ++vitr)
                  {
                    elements->push_back(vertexPtrToIndexMap[*vitr]);
                  }

                  // add to the drawn primitive list.
                  geom.addPrimitiveSet(elements);
                  ntris=elements->getNumIndices()/3;
              }
              else
              {
                  osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(prim->_mode);
                  for(Prim::VecList::iterator vitr=prim->_vertices.begin();
                    vitr!=prim->_vertices.end();
                    ++vitr)
                  {
                    elements->push_back(vertexPtrToIndexMap[*vitr]);
                  }

                  // add to the drawn primitive list.
                  geom.addPrimitiveSet(elements);
                  ntris=elements->getNumIndices()/3;
              }

              if (primItr==_primList.begin()) 
              {   // first primitive so collect primitive normal & colour.
                  if (normals) {
                     if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE)
                        norm=(*normals)[originalIndex + _extraPrimitives];
                     else
                        norm=(*normals)[iprim]; // GWM Sep 2002 the flat shaded normal
                  }
                  if (cols4) {
                      primCol4=(*cols4)[iprim]; // GWM Dec 2003 the flat shaded rgba colour
                    if (_index>=cols4->size()) {
                        cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet
                    }
                  }
                  if (cols3) {
                      primCol3=(*cols3)[iprim]; // GWM Dec 2003 flat shaded rgb colour
                    if (_index>=cols3->size()) {
                        cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet
                    }
                  }
              }
              else
              { // later primitives use same colour
                  if (normals)
                  {
                      if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE)
                      {
                          _extraPrimitives++;
                          normals->insert(normals->begin() + originalIndex + _extraPrimitives, norm);
                      }
                      else
                        normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet
                  }
                  if (cols4 && _index>=cols4->size()) {
                    cols4->push_back(primCol4); // GWM Dec 2003 add flat shaded colour for new facet
                  }
                  if (cols3 && _index>=cols3->size()) {
                    if (cols3) cols3->push_back(primCol3); // GWM Dec 2003 add flat shaded colour for new facet
                  }
                  if (prim->_mode==GL_TRIANGLES) {
                      if (geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET ||
                          geom.getNormalBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set.
                          for (int ii=1; ii<ntris; ii++) {
                              if (normals) normals->push_back(norm); // GWM Sep 2002 add flat shaded normal for new facet
                          }
                      }
                      if (geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE_SET ||
                          geom.getColorBinding()==osg::Geometry::BIND_PER_PRIMITIVE) { // need one per triangle? Not one per set.
                          for (int ii=1; ii<ntris; ii++) {
                              if (cols3 && _index>=cols3->size()) {
                                  if (cols3) cols3->push_back(primCol3);
                              }
                              if (cols4 && _index>=cols4->size()) {
                                  if (cols4) cols4->push_back(primCol4);
                              }
                              _index++;
                          }
                      }
                  }
                  //        osg::notify(osg::WARN)<<"Add: "<< iprim << std::endl; 
              }
              iprim++; // GWM Sep 2002 count which normal we should use
        }
    }
}
void Tessellator::handleNewVertices(osg::Geometry& geom,VertexPtrToIndexMap &vertexPtrToIndexMap)
{
    if (!_newVertexList.empty())
    {
        
        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
        osg::Vec3Array* normals = NULL;
        if (geom.getNormalBinding()==osg::Geometry::BIND_PER_VERTEX)
        {
            normals = dynamic_cast<osg::Vec3Array*>(geom.getNormalArray());
        }
        
        typedef std::vector<osg::Array*> ArrayList;
        ArrayList arrays;
        
        if (geom.getColorBinding()==osg::Geometry::BIND_PER_VERTEX)
        {
            arrays.push_back(geom.getColorArray());
        }
        
        if (geom.getSecondaryColorBinding()==osg::Geometry::BIND_PER_VERTEX)
        {
            arrays.push_back(geom.getSecondaryColorArray());
        }
        
        if (geom.getFogCoordBinding()==osg::Geometry::BIND_PER_VERTEX)
        {
            arrays.push_back(geom.getFogCoordArray());
        }
        
        osg::Geometry::ArrayDataList& tcal = geom.getTexCoordArrayList();
        for(osg::Geometry::ArrayDataList::iterator tcalItr=tcal.begin();
            tcalItr!=tcal.end();
            ++tcalItr)
        {
            if (tcalItr->array.valid()) 
            {
                arrays.push_back(tcalItr->array.get());
            }
        }
        
        // now add any new vertices that are required.
        for(NewVertexList::iterator itr=_newVertexList.begin();
            itr!=_newVertexList.end();
            ++itr)
        {
            NewVertex& newVertex = (*itr);
            osg::Vec3* vertex = newVertex._vpos;
            
            // assign vertex.
            vertexPtrToIndexMap[vertex]=vertices->size();
            vertices->push_back(*vertex);
            
            // assign normals
            if (normals)
            {
                osg::Vec3 norm(0.0f,0.0f,0.0f);
                if (newVertex._v1) norm += (*normals)[vertexPtrToIndexMap[newVertex._v1]] * newVertex._f1;
                if (newVertex._v2) norm += (*normals)[vertexPtrToIndexMap[newVertex._v2]] * newVertex._f2;
                if (newVertex._v3) norm += (*normals)[vertexPtrToIndexMap[newVertex._v3]] * newVertex._f3;
                if (newVertex._v4) norm += (*normals)[vertexPtrToIndexMap[newVertex._v4]] * newVertex._f4;
                norm.normalize();
                normals->push_back(norm);
            }
            
            if (!arrays.empty())
            {
                InsertNewVertices inv(newVertex._f1,vertexPtrToIndexMap[newVertex._v1],
                    newVertex._f2,vertexPtrToIndexMap[newVertex._v2],
                    newVertex._f3,vertexPtrToIndexMap[newVertex._v3],
                    newVertex._f4,vertexPtrToIndexMap[newVertex._v4]);
                
                // assign the rest of the attributes.
                for(ArrayList::iterator aItr=arrays.begin();
                aItr!=arrays.end();
                ++aItr)
                {
                    (*aItr)->accept(inv);
                }
            }
        }
        
    }
    
}
void Tessellator::retessellatePolygons(osg::Geometry &geom)
{
#ifdef OSG_GLU_AVAILABLE
    // turn the contour list into primitives, a little like Tessellator does but more generally
    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geom.getVertexArray());
    
    if (!vertices || vertices->empty() || geom.getPrimitiveSetList().empty()) return;


    // we currently don't handle geometry which use indices...
    if (geom.getVertexIndices() ||
        geom.getNormalIndices() ||
        geom.getColorIndices() ||
        geom.getSecondaryColorIndices() ||
        geom.getFogCoordIndices()) return;
        
    // not even text coord indices don't handle geometry which use indices...
    for(unsigned int unit=0;unit<geom.getNumTexCoordArrays();++unit)
    {
        if (geom.getTexCoordIndices(unit)) return;
    }

    if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE) _numberVerts=0; // 09.04.04 GWM reset Tessellator
    // the reset is needed by the flt loader which reuses a Tessellator for triangulating polygons.
    // as such it might be reset by other loaders/developers in future.
    _index=0; // reset the counter for indexed vertices
    _extraPrimitives = 0;
    if (!_numberVerts) {
        _numberVerts=geom.getVertexArray()->getNumElements();
        // save the contours for complex (winding rule) tessellations
        _Contours=geom.getPrimitiveSetList();
    }

    // now cut out vertex attributes added on any previous tessellation
    reduceArray(geom.getVertexArray(), _numberVerts);
    reduceArray(geom.getColorArray(), _numberVerts);
    reduceArray(geom.getNormalArray(), _numberVerts);
    reduceArray(geom.getFogCoordArray(), _numberVerts);
    for(unsigned int unit1=0;unit1<geom.getNumTexCoordArrays();++unit1)
    {
        reduceArray(geom.getTexCoordArray(unit1), _numberVerts);
    }

    // remove the existing primitives.
    unsigned int nprimsetoriginal= geom.getNumPrimitiveSets();
    if (nprimsetoriginal) geom.removePrimitiveSet(0, nprimsetoriginal);

    // the main difference from osgUtil::Tessellator for Geometry sets of multiple contours is that the begin/end tessellation
    // occurs around the whole set of contours.
    if (_ttype==TESS_TYPE_GEOMETRY) {
        beginTessellation();
        gluTessProperty(_tobj, GLU_TESS_WINDING_RULE, _wtype);
        gluTessProperty(_tobj, GLU_TESS_BOUNDARY_ONLY , _boundaryOnly);
    }
    // process all the contours into the Tessellator
    int noContours = _Contours.size();
    int currentPrimitive = 0;
    for(int primNo=0;primNo<noContours;++primNo)
    {
        osg::ref_ptr<osg::PrimitiveSet> primitive = _Contours[primNo].get();
        if (_ttype==TESS_TYPE_POLYGONS || _ttype==TESS_TYPE_DRAWABLE)
        { // this recovers the 'old' tessellation which just retessellates single polygons.
            if (primitive->getMode()==osg::PrimitiveSet::POLYGON || _ttype==TESS_TYPE_DRAWABLE)
            {

                if (primitive->getType()==osg::PrimitiveSet::DrawArrayLengthsPrimitiveType)
                {
                    osg::DrawArrayLengths* drawArrayLengths = static_cast<osg::DrawArrayLengths*>(primitive.get());
                    unsigned int first = drawArrayLengths->getFirst(); 
                    for(osg::DrawArrayLengths::iterator itr=drawArrayLengths->begin();
                        itr!=drawArrayLengths->end();
                        ++itr)
                    {
                        beginTessellation();
                            unsigned int last = first + *itr;
                            addContour(primitive->getMode(),first,last,vertices);
                            first = last;
                        endTessellation();
                        collectTessellation(geom, currentPrimitive);
                        currentPrimitive++;
                    }
                }
                else
                {
                    if (primitive->getNumIndices()>3) { // April 2005 gwm only retessellate "complex" polygons
                        beginTessellation();
                        addContour(primitive.get(), vertices);
                        endTessellation();
                        collectTessellation(geom, currentPrimitive);
                        currentPrimitive++;
                    } else { // April 2005 gwm triangles don't need to be retessellated
                        geom.addPrimitiveSet(primitive.get());
                    }
                }

            }
            else
            { // copy the contour primitive as it is not being tessellated
                geom.addPrimitiveSet(primitive.get());
            }
        } else {
            if (primitive->getMode()==osg::PrimitiveSet::POLYGON ||
                primitive->getMode()==osg::PrimitiveSet::QUADS ||
                primitive->getMode()==osg::PrimitiveSet::TRIANGLES ||
                primitive->getMode()==osg::PrimitiveSet::LINE_LOOP ||
                primitive->getMode()==osg::PrimitiveSet::QUAD_STRIP ||
                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_FAN ||
                primitive->getMode()==osg::PrimitiveSet::TRIANGLE_STRIP)
            {
                addContour(primitive.get(), vertices);
            } else { // copy the contour primitive as it is not being tessellated
                // in this case points, lines or line_strip
                geom.addPrimitiveSet(primitive.get());
            }
        }
    }
    if (_ttype==TESS_TYPE_GEOMETRY) {
        endTessellation();
    
        collectTessellation(geom, 0);    
    }
#endif
}
Exemple #30
0
void UnIndexMeshVisitor::apply(osg::Geometry& geom) 
{
    // no point optimizing if we don't have enough vertices.
    if (!geom.getVertexArray()) return;

    // check for the existence of surface primitives
    unsigned int numIndexedPrimitives = 0;
    osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList();
    osg::Geometry::PrimitiveSetList::iterator itr;
    for(itr=primitives.begin();
        itr!=primitives.end();
        ++itr)
    {
        osg::PrimitiveSet::Type type = (*itr)->getType();
        if ((type == osg::PrimitiveSet::DrawElementsUBytePrimitiveType
             || type == osg::PrimitiveSet::DrawElementsUShortPrimitiveType
             || type == osg::PrimitiveSet::DrawElementsUIntPrimitiveType))
            numIndexedPrimitives++;
    }
    
    // no polygons or no indexed primitive, nothing to do
    if (!numIndexedPrimitives) {
        return;
    }

    // we dont manage lines
    
    GeometryArrayList arraySrc(geom);
    GeometryArrayList arrayList = arraySrc.cloneType();

    osg::Geometry::PrimitiveSetList newPrimitives;

    for(itr=primitives.begin();
        itr!=primitives.end();
        ++itr)
    {
        osg::PrimitiveSet::Mode mode = (osg::PrimitiveSet::Mode)(*itr)->getMode();

        switch(mode) {

            // manage triangles
        case(osg::PrimitiveSet::TRIANGLES):
        case(osg::PrimitiveSet::TRIANGLE_STRIP):
        case(osg::PrimitiveSet::TRIANGLE_FAN):
        case(osg::PrimitiveSet::QUADS):
        case(osg::PrimitiveSet::QUAD_STRIP):
        case(osg::PrimitiveSet::POLYGON):
        {
            // for each geometry list indexes of vertexes
            // to makes triangles
            TriangleIndexor triangleIndexList;
            (*itr)->accept(triangleIndexList);

            unsigned int index = arrayList.size();

            // now copy each vertex to new array, like a draw array
            arraySrc.append(triangleIndexList._indices, arrayList);

            newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
                                                        index,
                                                        triangleIndexList._indices.size()));
        }
        break;

        // manage lines
        case(osg::PrimitiveSet::LINES):
        case(osg::PrimitiveSet::LINE_STRIP):
        case(osg::PrimitiveSet::LINE_LOOP):
        {
            EdgeIndexor edgesIndexList;
            (*itr)->accept(edgesIndexList);

            unsigned int index = arrayList.size();

            // now copy each vertex to new array, like a draw array
            arraySrc.append(edgesIndexList._indices, arrayList);

            newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::LINES,
                                                        index,
                                                        edgesIndexList._indices.size()));
        }
        break;
        case(osg::PrimitiveSet::POINTS):
        {
            PointIndexor pointsIndexList;
            (*itr)->accept(pointsIndexList);

            unsigned int index = arrayList.size();

            // now copy each vertex to new array, like a draw array
            arraySrc.append(pointsIndexList._indices, arrayList);
            newPrimitives.push_back(new osg::DrawArrays(osg::PrimitiveSet::POINTS,
                                                        index,
                                                        pointsIndexList._indices.size()));
        }
        break;
        default:
            break;
        }
    }

    arrayList.setToGeometry(geom);
    geom.setPrimitiveSetList(newPrimitives);
}