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) );
        }
    }
}
Exemple #2
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;
    }

#if OSG_VERSION_GREATER_OR_EQUAL(3,1,9)

    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 == NULL )
        {
            OE_NOTICE << LC << "Found a NULL array\n";
        }
        else 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() );
    }

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

#else // pre-3.1.9 ... phase out.

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

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

#endif

    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";
    }
}
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);
                }
            }
        }
        
    }
    
}
Exemple #5
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 #6
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);
}