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 );
}
Exemple #2
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);
}
Exemple #3
0
void IndexMeshVisitor::apply(osg::Geometry& geom) {
    // TODO: this is deprecated
    if (geom.getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return;
    if (geom.getColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return;
    if (geom.getSecondaryColorBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return;
    if (geom.getFogCoordBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) return;

    // no point optimizing if we don't have enough vertices.
    if (!geom.getVertexArray() || geom.getVertexArray()->getNumElements() < 3) return;


    osgUtil::SharedArrayOptimizer deduplicator;
    deduplicator.findDuplicatedUVs(geom);

    // duplicate shared arrays as it isn't safe to rearrange vertices when arrays are shared.
    if (geom.containsSharedArrays()) {
        geom.duplicateSharedArrays();
    }

    osg::Geometry::PrimitiveSetList& primitives = geom.getPrimitiveSetList();
    osg::Geometry::PrimitiveSetList::iterator itr;

    osg::Geometry::PrimitiveSetList new_primitives;
    new_primitives.reserve(primitives.size());

    // compute duplicate vertices
    typedef std::vector<unsigned int> IndexList;
    unsigned int numVertices = geom.getVertexArray()->getNumElements();
    IndexList indices(numVertices);
    unsigned int i, j;
    for(i = 0 ; i < numVertices ; ++ i) {
        indices[i] = i;
    }

    VertexAttribComparitor arrayComparitor(geom);
    std::sort(indices.begin(), indices.end(), arrayComparitor);

    unsigned int lastUnique = 0;
    unsigned int numUnique = 1;
    for(i = 1 ; i < numVertices ; ++ i) {
        if (arrayComparitor.compare(indices[lastUnique], indices[i]) != 0) {
            lastUnique = i;
            ++ numUnique;
        }
    }

    IndexList remapDuplicatesToOrignals(numVertices);
    lastUnique = 0;
    for(i = 1 ; i < numVertices ; ++ i) {
        if (arrayComparitor.compare(indices[lastUnique],indices[i]) != 0) {
            // found a new vertex entry, so previous run of duplicates needs
            // to be put together.
            unsigned int min_index = indices[lastUnique];
            for(j = lastUnique + 1 ; j < i ; ++ j) {
                min_index = osg::minimum(min_index, indices[j]);
            }
            for(j = lastUnique ; j < i ; ++ j) {
                remapDuplicatesToOrignals[indices[j]] = min_index;
            }
            lastUnique = i;
        }
    }

    unsigned int min_index = indices[lastUnique];
    for(j = lastUnique + 1 ; j < i ; ++ j) {
        min_index = osg::minimum(min_index, indices[j]);
    }
    for(j = lastUnique ; j < i ; ++ j) {
        remapDuplicatesToOrignals[indices[j]] = min_index;
    }

    // copy the arrays.
    IndexList finalMapping(numVertices);
    IndexList copyMapping;
    copyMapping.reserve(numUnique);
    unsigned int currentIndex = 0;
    for(i = 0 ; i < numVertices ; ++ i) {
        if (remapDuplicatesToOrignals[i] == i) {
            finalMapping[i] = currentIndex;
            copyMapping.push_back(i);
            currentIndex++;
        }
        else {
            finalMapping[i] = finalMapping[remapDuplicatesToOrignals[i]];
        }
    }

    // remap any shared vertex attributes
    RemapArray ra(copyMapping);
    arrayComparitor.accept(ra);

    // triangulate faces
    {
        TriangleIndexor ti;
        ti._maxIndex = numVertices;
        ti._remapping = finalMapping;

        for(itr = primitives.begin() ; itr != primitives.end() ; ++ itr) {
            (*itr)->accept(ti);
        }

        addDrawElements(ti._indices, osg::PrimitiveSet::TRIANGLES, new_primitives);
    }

    // line-ify line-type primitives
    {
        LineIndexor li, wi; // lines and wireframes
        li._maxIndex = numVertices;
        wi._maxIndex = numVertices;
        li._remapping = finalMapping;
        wi._remapping = finalMapping;

        for(itr = primitives.begin() ; itr != primitives.end() ; ++ itr) {
            bool isWireframe = false;
            if((*itr)->getUserValue("wireframe", isWireframe) && isWireframe) {
                (*itr)->accept(wi);
            }
            else {
                (*itr)->accept(li);
            }
        }
        addDrawElements(li._indices, osg::PrimitiveSet::LINES, new_primitives);
        addDrawElements(wi._indices, osg::PrimitiveSet::LINES, new_primitives, "wireframe");
    }

    // adds points primitives
    {
        IndexList points;
        for(itr = primitives.begin() ; itr != primitives.end() ; ++ itr) {
            if((*itr) && (*itr)->getMode() == osg::PrimitiveSet::POINTS) {
                for(unsigned int k = 0 ; k < (*itr)->getNumIndices() ; ++ k) {
                    points.push_back(finalMapping[(*itr)->index(k)]);
                }
            }
        }
        addDrawElements(points, osg::PrimitiveSet::POINTS, new_primitives);
    }

    geom.setPrimitiveSetList(new_primitives);
    deduplicator.deduplicateUVs(geom);
    setProcessed(&geom);
}