void generateTexCoordsSphere( VertexAttributeSetSharedPtr const& vas, const Sphere3f &sphere, unsigned int tu )
      {
        Buffer::ConstIterator<Vec3f>::Type vertices = vas->getVertices();
        std::vector<Vec2f> texCoords( vas->getNumberOfVertices() );
        Vec2f tp;

        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          Vec3f p = vertices[i] - sphere.getCenter();
          if ( fabsf( p[1] ) > FLT_EPSILON )
          {
            tp[0] = 0.5f * atan2f( p[0], -p[1] ) / (float) PI + 0.5f;
          }
          else
          {
            tp[0] = (float)( ( p[0] >= 0.0f ) ? 0.75f : 0.25f );
          }

          float d = sqrtf( square( p[0] ) + square( p[1] ) );
          if ( d > FLT_EPSILON )
          {
            tp[1] = atan2f( p[2], d ) / (float) PI + 0.5f;
          }
          else
          {
            tp[1] = (float)( ( p[2] >= 0.0f ) ? 1.0f : 0.0f );
          }

          texCoords[i] = tp;
        }

        vas->setTexCoords( tu, &texCoords[0], vas->getNumberOfVertices() );
      }
      void copySelectedVertices( const VertexAttributeSetSharedPtr & from, const VertexAttributeSetSharedPtr & to
                               , std::vector<std::vector<unsigned int> > &indices )
      {
        // indexMap below is intended to hold vertex indices, which should not exceed 32-bit precision by definition!
        std::vector<unsigned int> indexMap( from->getNumberOfVertices(), ~0 );
        std::vector<unsigned int> iFrom; iFrom.reserve(from->getNumberOfVertices());
        for ( size_t i=0 ; i<indices.size() ; i++ )
        {
          for ( size_t j=0 ; j<indices[i].size() ; j++ )
          {
            if ( indexMap[indices[i][j]] == ~0 )
            {
              indexMap[indices[i][j]] = dp::checked_cast<unsigned int>(iFrom.size());
              iFrom.push_back(indices[i][j]);
            }
          }
        }

        for ( unsigned int slot=0 ; slot<static_cast<unsigned int>(VertexAttributeSet::AttributeID::VERTEX_ATTRIB_COUNT) ; slot++ )
        {
          VertexAttributeSet::AttributeID id = static_cast<VertexAttributeSet::AttributeID>(slot);
          if ( from->getSizeOfVertexData( id ) )
          {
            BufferSharedPtr oldData = from->getVertexBuffer(id);
            Buffer::DataReadLock lock( oldData );

            unsigned int size = from->getSizeOfVertexData( id );
            dp::DataType type = from->getTypeOfVertexData( id );

            to->setVertexData( id, NULL, &iFrom[0], size, type, lock.getPtr()
                             , from->getStrideOfVertexData( id )
                             , dp::checked_cast<unsigned int>(iFrom.size()) );

            // inherit enable states from source id
            // normalize-enable state only meaningful for generic aliases!
            to->setEnabled(id, from->isEnabled(id)); // conventional

            id = static_cast<VertexAttributeSet::AttributeID>(slot+16);    // generic
            to->setEnabled(id, from->isEnabled(id));
            to->setNormalizeEnabled(id, from->isNormalizeEnabled(id));
          }
        }

        for ( size_t i=0 ; i<indices.size() ; i++ )
        {
          for ( size_t j=0 ; j<indices[i].size() ; j++ )
          {
            indices[i][j] = indexMap[indices[i][j]];
          }
        }
      }
      void  generateTexCoordsPlane( VertexAttributeSetSharedPtr const& vas, const Sphere3f &sphere, unsigned int tu )
      {
        Buffer::ConstIterator<Vec3f>::Type vertices = vas->getVertices();

        // get the bounding box of vas and determine the axes u,v to use to texture along
        unsigned int u, v, w;
        getSortedAxes( vertices, vas->getNumberOfVertices(), u, v, w );

        // create the texture coordinates
        std::vector<Vec2f> texCoords( vas->getNumberOfVertices() );
        Vec2f tp;
        float oneOverTwoR = 0.5f / sphere.getRadius();
        Vec2f tpMin( 1.0f, 1.0f );
        Vec2f tpMax( 0.0f, 0.0f );
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          Vec3f p = vertices[i] - sphere.getCenter();
          tp[0] = p[u] * oneOverTwoR + 0.5f;  // 0.0 <= tp[0] <= 1.0
          if ( tp[0] < tpMin[0] )
          {
            tpMin[0] = tp[0];
          }
          else if ( tp[0] > tpMax[0] )
          {
            tpMax[0] = tp[0];
          }

          tp[1] = p[v] * oneOverTwoR + 0.5f;   //  0.0 <= tp[1] <= 1.0
          if ( tp[1] < tpMin[1] )
          {
            tpMin[1] = tp[1];
          }
          else if ( tp[1] > tpMax[1] )
          {
            tpMax[1] = tp[1];
          }

          texCoords[i] = tp;
        }

        // scale the texcoords to [0..1]
        DP_ASSERT( ( FLT_EPSILON < ( tpMax[0] - tpMin[0] ) ) && ( FLT_EPSILON < ( tpMax[1] - tpMin[1] ) ) );
        Vec2f tpScale( 1.0f / ( tpMax[0] - tpMin[0] ), 1.0f / ( tpMax[1] - tpMin[1] ) );
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          texCoords[i] = Vec2f( ( texCoords[i][0] - tpMin[0] ) * tpScale[0],
                                ( texCoords[i][1] - tpMin[1] ) * tpScale[1] );
        }

        vas->setTexCoords( tu, &texCoords[0], vas->getNumberOfVertices() );
      }
      void  generateTexCoordsCylinder( VertexAttributeSetSharedPtr const& vas, const Sphere3f &sphere, unsigned int tu )
      {
        Buffer::ConstIterator<Vec3f>::Type vertices = vas->getVertices();

        // get the bounding box of vas and determine the axes u,v to use to texture along
        unsigned int u, v, w;
        getSortedAxes( vertices, vas->getNumberOfVertices(), u, v, w );

        // create the texture coordinates
        std::vector<Vec2f> texCoords( vas->getNumberOfVertices() );
        Vec2f tp;
        float oneOverTwoR = 0.5f / sphere.getRadius();
        float tpuMin = 1.0f;
        float tpuMax = 0.0f;
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          Vec3f p = vertices[i] - sphere.getCenter();

          // largest axis as the cylinder axis
          tp[0] = p[u] * oneOverTwoR + 0.5f;   //  0.0 <= tp[1] <= 1.0
          if ( tp[0] < tpuMin )
          {
            tpuMin = tp[0];
          }
          else if ( tpuMax < tp[0] )
          {
            tpuMax = tp[0];
          }

          if ( FLT_EPSILON < fabsf( p[v] ) )
          {
            tp[1] = 0.5f * atan2f( p[w], -p[v] ) / (float) PI + 0.5f;
          }
          else
          {
            tp[1] = (float)( ( 0.0f <= p[w] ) ? 0.75f : 0.25f );
          }

          texCoords[i] = tp;
        }

        // scale the texcoords to [0..1]
        DP_ASSERT( FLT_EPSILON < ( tpuMax - tpuMin ) );
        float tpuScale = 1.0f / ( tpuMax - tpuMin );
        for ( unsigned int i=0 ; i<vas->getNumberOfVertices() ; i++ )
        {
          texCoords[i][0] = ( texCoords[i][0] - tpuMin ) * tpuScale;
        }
        vas->setTexCoords( tu, &texCoords[0], vas->getNumberOfVertices() );
      }