Beispiel #1
0
void
WriterNodeVisitor::createListTriangle(osg::Geometry * geo,
                                      ListTriangle  & listTriangles,
                                      bool          & texcoords,
                                      unsigned int  & drawable_n)
{
    const osg::Array * basevecs = geo->getVertexArray();
    if (!basevecs || basevecs->getNumElements()==0) return;

    // Texture coords
    const osg::Array * basetexvecs = geo->getNumTexCoordArrays()>=1 ? geo->getTexCoordArray(0) : NULL;
    if (basetexvecs)
    {
        unsigned int nb = basetexvecs->getNumElements();
        if (nb != geo->getVertexArray()->getNumElements())
        {
            OSG_NOTIFY(osg::FATAL) << "There are more/less texture coords than vertices (corrupted geometry)" << std::endl;
            _succeeded = false;
            return;
        }
        texcoords = true;
    }

    int material = processStateSet(_currentStateSet.get());

    for(unsigned int i = 0; i < geo->getNumPrimitiveSets(); ++i) //Fill the Triangle List
    {
        osg::PrimitiveSet* ps = geo->getPrimitiveSet(i);
        PrimitiveIndexWriter pif(geo, listTriangles, drawable_n, material);
        ps->accept(pif);
    }
}
Beispiel #2
0
bool osg::isGLExtensionOrVersionSupported(unsigned int contextID, const char *extension, float requiredGLVersion)
{
    ExtensionSet& extensionSet = s_glExtensionSetList[contextID];
    std::string& rendererString = s_glRendererList[contextID];

    // first check to see if GL version number of recent enough.
    bool result = requiredGLVersion <= osg::getGLVersionNumber();
    
    if (!result)
    {    
        // if not already set up, initialize all the per graphic context values.
        if (!s_glInitializedList[contextID])
        {
            s_glInitializedList[contextID] = 1;

            // set up the renderer
            const GLubyte* renderer = glGetString(GL_RENDERER);
            rendererString = renderer ? (const char*)renderer : "";

            // get the extension list from OpenGL.
            GLint numExt = 0;
            #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
            if( osg::getGLVersionNumber() >= 3.0 )
            {
                // OpenGL 3.0 adds the concept of indexed strings and
                // deprecates calls to glGetString( GL_EXTENSIONS ), which
                // will now generate GL_INVALID_ENUM.

                // Get extensions using new indexed string interface.

                typedef const GLubyte * GL_APIENTRY PFNGLGETSTRINGIPROC( GLenum, GLuint );
                PFNGLGETSTRINGIPROC* glGetStringi = 0;
                setGLExtensionFuncPtr( glGetStringi, "glGetStringi");

                if( glGetStringi != NULL )
                {
                    #  ifndef GL_NUM_EXTENSIONS
                    #    define GL_NUM_EXTENSIONS 0x821D
                    #  endif
                    glGetIntegerv( GL_NUM_EXTENSIONS, &numExt );
                    int idx;
                    for( idx=0; idx<numExt; idx++ )
                    {
                        extensionSet.insert( std::string( (char*)( glGetStringi( GL_EXTENSIONS, idx ) ) ) );
                    }
                }
                else
                {
                    OSG_WARN << "isGLExtensionOrVersionSupported: Can't obtain glGetStringi function pointer." << std::endl;
                }
            }
            #endif

            // No extensions found so far, so try with glGetString
            if (numExt == 0)
            {
                // Get extensions using GL1/2 interface.

                const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
                if (extensions==NULL) return false;

                // insert the ' ' delimiated extensions words into the extensionSet.
                const char *startOfWord = extensions;
                const char *endOfWord;
                while ((endOfWord = strchr(startOfWord,' '))!=NULL)
                {
                    extensionSet.insert(std::string(startOfWord,endOfWord));
                    startOfWord = endOfWord+1;
                }
                if (*startOfWord!=0) extensionSet.insert(std::string(startOfWord));
            }

    #if defined(WIN32) && (defined(OSG_GL1_AVAILABLE) || defined(OSG_GL2_AVAILABLE) || defined(OSG_GL3_AVAILABLE))

            // add WGL extensions to the list

            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGARB(HDC);
            WGLGETEXTENSIONSSTRINGARB* wglGetExtensionsStringARB = 0;
            setGLExtensionFuncPtr(wglGetExtensionsStringARB, "wglGetExtensionsStringARB");

            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGEXT();
            WGLGETEXTENSIONSSTRINGEXT* wglGetExtensionsStringEXT = 0;
            setGLExtensionFuncPtr(wglGetExtensionsStringEXT, "wglGetExtensionsStringEXT");

            const char* wglextensions = 0;

            if (wglGetExtensionsStringARB)
            {
                HDC dc = wglGetCurrentDC();
                wglextensions = wglGetExtensionsStringARB(dc);
            }
            else if (wglGetExtensionsStringEXT)
            {
                wglextensions = wglGetExtensionsStringEXT();
            }

            if (wglextensions)
            {    
                const char* startOfWord = wglextensions;
                const char* endOfWord;
                while ((endOfWord = strchr(startOfWord, ' ')))
                {
                    extensionSet.insert(std::string(startOfWord, endOfWord));
                    startOfWord = endOfWord+1;
                }
                if (*startOfWord != 0) extensionSet.insert(std::string(startOfWord));
            }

    #endif

            OSG_NOTIFY(INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<std::endl;
            for(ExtensionSet::iterator itr=extensionSet.begin();
                itr!=extensionSet.end();
                ++itr)
            {
                OSG_NOTIFY(INFO)<<"    "<<*itr<<std::endl;
            }

        }

        // true if extension found in extensionSet.
        result = extensionSet.find(extension)!=extensionSet.end();
    }
Beispiel #3
0
void
Lwo2Layer::notify(NotifySeverity severity)
{
  OSG_NOTIFY(severity) << "Current layer: " << _number << endl;
  OSG_NOTIFY(severity) << "  flags  \t" << _flags << endl;
  OSG_NOTIFY(severity) << "  pivot  \t" << _pivot << endl;
  OSG_NOTIFY(severity) << "  name:  \t'" << _name.c_str() << "'" << endl;
  OSG_NOTIFY(severity) << "  parent:\t" << _parent << endl;

  // points
  OSG_NOTIFY(severity) << "  points:\t" << _points.size() << endl;
  OSG_NOTIFY(severity) << "\tcoord\t\t\t\ttexcoord" <<  endl;
  OSG_NOTIFY(severity) << "\t=====\t\t\t\t========" <<  endl;
  IteratorPoint itr;
  for (itr = _points.begin(); itr != _points.end(); itr++)
    {
      OSG_NOTIFY(severity) << "    \t" << (*itr).coord << "\t\t" << (*itr).texcoord << endl;
    }

  // polygons
  OSG_NOTIFY(severity) << "  polygons:\t" << _polygons.size() << endl;
  OSG_NOTIFY(severity) << "\tcoord\t\t\t\ttexcoord" <<  endl;
  OSG_NOTIFY(severity) << "\t=====\t\t\t\t========" <<  endl;
  IteratorPolygonsList polygon_iterator;
  int polygon_index = 0;
  for (polygon_iterator = _polygons.begin(); polygon_iterator != _polygons.end(); polygon_iterator++, polygon_index++)
    {
      OSG_NOTIFY(severity) << "    \t" << polygon_index << " ("<< (*polygon_iterator).size() << " vertexes" << "):" << endl;
      for (itr = (*polygon_iterator).begin(); itr != (*polygon_iterator).end(); itr++)
        {
          OSG_NOTIFY(severity) << "    \t" << (*itr).coord << "\t\t" << (*itr).texcoord << endl;
        }
      OSG_NOTIFY(severity) << endl;
    }

  // polygons tags
  OSG_NOTIFY(severity) << "  polygons tags:\t" << _polygons_tag.size() << endl;
  IteratorShort short_itr;
  for (short_itr = _polygons_tag.begin(); short_itr != _polygons_tag.end(); short_itr++)
    {
      OSG_NOTIFY(severity) << "\t" << (*short_itr) << endl;
    }
}
Beispiel #4
0
WindowCaptureCallback::ContextData::ContextData(osg::GraphicsContext* gc, Mode mode, GLenum readBuffer)
    : _gc(gc),
      _index(_gc->getState()->getContextID()),
      _mode(mode),
      _readBuffer(readBuffer),
      _pixelFormat(GL_RGBA),
      _type(GL_UNSIGNED_BYTE),
      _width(0),
      _height(0),
      _currentImageIndex(0),
      _currentPboIndex(0),
      _reportTimingFrequency(100),
      _numTimeValuesRecorded(0),
      _timeForReadPixels(0.0),
      _timeForMemCpy(0.0),
      _timeForCaptureOperation(0.0),
      _timeForFullCopy(0.0),
      _timeForFullCopyAndOperation(0.0),
      _previousFrameTick(0)
{
    _previousFrameTick = osg::Timer::instance()->tick();

    osg::NotifySeverity level = osg::INFO;

    if (gc->getTraits())
    {
        if (gc->getTraits()->alpha)
        {
            OSG_NOTIFY(level)<<"ScreenCaptureHandler: Selected GL_RGBA read back format"<<std::endl;
            _pixelFormat = GL_RGBA;
        }
        else
        {
            OSG_NOTIFY(level)<<"ScreenCaptureHandler: Selected GL_RGB read back format"<<std::endl;
            _pixelFormat = GL_RGB;
        }
    }

    getSize(gc, _width, _height);

    //OSG_NOTICE<<"Window size "<<_width<<", "<<_height<<std::endl;

    // single buffered image
    _imageBuffer.push_back(new osg::Image);

    // double buffer PBO.
    switch(_mode)
    {
        case(READ_PIXELS):
            OSG_NOTIFY(level)<<"ScreenCaptureHandler: Reading window using glReadPixels, without PixelBufferObject."<<std::endl;
            break;
        case(SINGLE_PBO):
            OSG_NOTIFY(level)<<"ScreenCaptureHandler: Reading window using glReadPixels, with a single PixelBufferObject."<<std::endl;
            _pboBuffer.push_back(0);
            break;
        case(DOUBLE_PBO):
            OSG_NOTIFY(level)<<"ScreenCaptureHandler: Reading window using glReadPixels, with a double buffer PixelBufferObject."<<std::endl;
            _pboBuffer.push_back(0);
            _pboBuffer.push_back(0);
            break;
        case(TRIPLE_PBO):
            OSG_NOTIFY(level)<<"ScreenCaptureHandler: Reading window using glReadPixels, with a triple buffer PixelBufferObject."<<std::endl;
            _pboBuffer.push_back(0);
            _pboBuffer.push_back(0);
            _pboBuffer.push_back(0);
            break;
        default:
            break;
    }
}
Beispiel #5
0
void
WriterNodeVisitor::buildFaces(osg::Geode        & geo,
                              const osg::Matrix & mat,
                              ListTriangle      & listTriangles,
                              bool                texcoords)
{
    unsigned int nbTrianglesRemaining = listTriangles.size();
    unsigned int nbVerticesRemaining  = calcVertices(geo);        // May set _succeded to false
    if (!succeeded()) return;

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

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

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

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

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

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

    buildMesh(geo, mat, index_vert, texcoords, mesh);        // May set _succeded to false
    if (!succeeded())
    {
        lib3ds_mesh_free(mesh);
        return;
    }
}
Beispiel #6
0
void
WriterNodeVisitor::buildMesh(osg::Geode        & geo,
                             const osg::Matrix & mat,
                             MapIndices        & index_vert,
                             bool                texcoords,
                             Lib3dsMesh        * mesh)
{
    OSG_DEBUG << "Building Mesh" << std::endl;
    assert(mesh);

    // Write points
    assert(index_vert.size() <= MAX_VERTICES);
    lib3ds_mesh_resize_vertices(mesh, index_vert.size(), texcoords ? 1 : 0, 0);

    for(MapIndices::iterator it = index_vert.begin(); it != index_vert.end();++it)
    {
        osg::Geometry *g = geo.getDrawable( it->first.second )->asGeometry();
        const osg::Array * basevecs = g->getVertexArray();
        assert(basevecs);
        if (!basevecs || basevecs->getNumElements()==0) continue;
        if (basevecs->getType() == osg::Array::Vec3ArrayType)
        {
            const osg::Vec3Array & vecs= *static_cast<const osg::Vec3Array *>(basevecs);
            copyOsgVectorToLib3dsVector(mesh->vertices[it->second], vecs[it->first.first]*mat);
        }
        else if (basevecs->getType() == osg::Array::Vec3dArrayType)
        {
            // Handle double presision vertices by converting them to float with a warning
            OSG_NOTICE << "3DS format only supports single precision vertices. Converting double precision to single." << std::endl;
            const osg::Vec3dArray & vecs= *static_cast<const osg::Vec3dArray *>(basevecs);
            copyOsgVectorToLib3dsVector(mesh->vertices[it->second], vecs[it->first.first]*mat);
        }
        else
        {
            OSG_NOTIFY(osg::FATAL) << "Vertex array is not Vec3 or Vec3d. Not implemented" << std::endl;
            _succeeded = false;
            return;
        }
    }

    // Write texture coords (Texture 0 only)
    if (texcoords)
    {
        for(MapIndices::iterator it = index_vert.begin(); it != index_vert.end(); ++it)
        {
            osg::Geometry *g = geo.getDrawable( it->first.second )->asGeometry();
            const osg::Array * texarray = g->getNumTexCoordArrays()>=1 ? g->getTexCoordArray(0) : NULL;
            if (!texarray || texarray->getNumElements()==0) continue;

            if (g->getTexCoordArray(0)->getType() != osg::Array::Vec2ArrayType)
            {
                OSG_NOTIFY(osg::FATAL) << "Texture coords array is not Vec2. Not implemented" << std::endl;
                _succeeded = false;
                return;
            }
            const osg::Vec2Array & vecs= *static_cast<const osg::Vec2Array *>(texarray);
            mesh->texcos[it->second][0] = vecs[it->first.first][0];
            mesh->texcos[it->second][1] = vecs[it->first.first][1];
        }
    }
    lib3ds_file_insert_mesh(_file3ds, mesh, _lastMeshIndex);
    ++_lastMeshIndex;

    Lib3dsMeshInstanceNode * node3ds = lib3ds_node_new_mesh_instance(mesh, mesh->name, NULL, NULL, NULL);
    lib3ds_file_append_node(_file3ds, reinterpret_cast<Lib3dsNode*>(node3ds), reinterpret_cast<Lib3dsNode*>(_cur3dsNode));
}
Beispiel #7
0
std::string WriterNodeVisitor::getUniqueName(const std::string& _defaultValue, bool isNodeName, const std::string & _defaultPrefix, int currentPrefixLen)
{
    //const unsigned int MAX_LENGTH = maxNameLen(_extendedFilePaths);
    const unsigned int MAX_PREFIX_LENGTH = _extendedFilePaths ? 52 : 6;        // Arbitrarily defined for short names, kept enough room for displaying UINT_MAX (10 characters) for long names.
    assert(_defaultPrefix.length()<=4);        // Default prefix is too long (implementation error)
    const std::string defaultPrefix(_defaultPrefix.empty() ? "_" : _defaultPrefix);
    if (currentPrefixLen<0) currentPrefixLen = osg::maximum(_defaultPrefix.length(), _defaultValue.length());
    currentPrefixLen = osg::clampBelow(currentPrefixLen, static_cast<int>(MAX_PREFIX_LENGTH));

    // Tests if default name is valid and unique
    NameMap & nameMap = isNodeName ? _nodeNameMap : _imageNameMap;
    PrefixMap & prefixMap = isNodeName ? _nodePrefixMap : _imagePrefixMap;

    // Handling of paths is simple. Algorithm:
    //    - For short names, subdirectories are simply forbidden. Use the simple file name.
    //    - Else, the whole (relative) path must simply be <64 chars.
    // After this, begin enumeration.
    std::string parentPath, filename, ext, namePrefix;
    unsigned int max_val = 0;

    // TODO Move the two parts of this giant if/else into two separate functions for better readability.
    if (_extendedFilePaths)
    {
        // Tests if default name is valid and unique
        if (is3DSName(_defaultValue, _extendedFilePaths, isNodeName))
        {
            std::pair<NameMap::iterator, bool> insertion( nameMap.insert(_defaultValue) );
            if (insertion.second) return _defaultValue;        // Return if element is newly inserted in the map (else there is a naming collision)
        }

        // Simply separate name and last extension
        filename = osgDB::getNameLessExtension(osgDB::getSimpleFileName(_defaultValue));
        if (!isNodeName)
        {
            ext = osgDB::getFileExtensionIncludingDot(_defaultValue);
            if (ext == ".") ext = "";
        }

        // Compute parent path
        // Pre-condition: paths are supposed to be relative.
        // If full path is too long (>MAX_PREFIX_LENGTH), cut path to let enough space for simple file name.
        // Do not cut in the middle of a name, but at path separators.
        parentPath = osgDB::getFilePath(_defaultValue);
        if (_defaultValue.length() >MAX_PREFIX_LENGTH)        // Not parentPath but _defaultValue!
        {
            // Nodes names: keep last directories (used only for the root name, generally named after the full file path)
            // Images names: keep first directories (for images)
            if (isNodeName) std::reverse(parentPath.begin(), parentPath.end());
            unsigned lenToDelete(filename.length() + ext.length() + 1);
            lenToDelete = osg::clampBelow(lenToDelete, MAX_PREFIX_LENGTH);
            parentPath = truncateFilenameBytes(parentPath, MAX_PREFIX_LENGTH - lenToDelete);        // +1 for the path separator
            std::string::size_type separator = parentPath.find_last_of("/\\");
            if (separator != std::string::npos) parentPath = parentPath.substr(0, separator);
            if (isNodeName) std::reverse(parentPath.begin(), parentPath.end());
        }

        // Assert "MAX_PREFIX_LENGTH - parent path length - extension length -1" is >=0 and truncate name to this length to get our new prefix.
        assert(parentPath.length() + ext.length() <= MAX_PREFIX_LENGTH);
        const unsigned int len = MAX_PREFIX_LENGTH - (parentPath.length() + ext.length() +1);
        namePrefix = truncateFilenameBytes(filename, len);
        if (namePrefix.empty()) namePrefix = defaultPrefix;

        // Truncate the filename to get our new prefix
        namePrefix = truncateFilenameBytes(filename, currentPrefixLen);

        // Enough space has been reserved for UINT_MAX values
        max_val = UINT_MAX;
    }
    else
    {
        // Get last extension, and make filename have no extension
        filename = osgDB::getNameLessAllExtensions(osgDB::getSimpleFileName(_defaultValue));
        if (!isNodeName)
        {
            ext = truncateFilenameBytes(osgDB::getFileExtensionIncludingDot(_defaultValue), 4);        // 4 chars = dot + 3 chars
            if (ext == ".") ext = "";
        }

        // Tests if STRIPPED default name is valid and unique
        const std::string strippedName( filename + ext );
        if (is3DSName(strippedName, _extendedFilePaths, isNodeName))
        {
            std::pair<NameMap::iterator, bool> insertion( nameMap.insert(strippedName) );
            if (insertion.second) return strippedName;        // Return if element is newly inserted in the map (else there is a naming collision)
        }

        namePrefix = filename;
        if (namePrefix.empty()) namePrefix = defaultPrefix;
        // Truncate the filename to get our new prefix
        namePrefix = truncateFilenameBytes(namePrefix, currentPrefixLen);

        // Compute the maximum enumeration value
        max_val = static_cast<unsigned int>(pow(10., 8. - namePrefix.length())) -1;
    }
    assert(namePrefix.size() <= MAX_PREFIX_LENGTH);

    // Find the current enumeration value (searchStart)
    unsigned int searchStart(0);
    PrefixMap::iterator pairPrefix( prefixMap.find(namePrefix) );
    if (pairPrefix != prefixMap.end())
    {
        searchStart = pairPrefix->second;
    }
    else
    {
        // Check if truncated name is ok
        const std::string res( osgDB::concatPaths(parentPath, namePrefix + ext) );
        if (nameMap.find(res) == nameMap.end()) {
            prefixMap.insert(std::pair<std::string, unsigned int>(namePrefix, 0));
            nameMap.insert(res);
            return res;
        }
    }

    // Search for a free value
    for(unsigned int i = searchStart; i <= max_val; ++i)
    {
        std::stringstream ss;
        ss << namePrefix << i;
        const std::string res( osgDB::concatPaths(parentPath, ss.str() + ext) );
        if (nameMap.find(res) == nameMap.end())
        {
            if (pairPrefix != prefixMap.end())
            {
                pairPrefix->second = i + 1;
            } else
            {
                prefixMap.insert(std::pair<std::string, unsigned int>(namePrefix, i + 1));
            }
            nameMap.insert(res);
            return res;
        }
    }

    // Failed finding a name
    // Try with a shorter prefix if possible
    if (currentPrefixLen>1) return getUniqueName(_defaultValue, isNodeName, defaultPrefix, currentPrefixLen-1);
    // Try with default prefix if not arleady done
    if (defaultPrefix != std::string("_")) return getUniqueName(_defaultValue, isNodeName, "_", 1);

    // No more names
    OSG_NOTIFY(osg::FATAL) << "No more names available!" << std::endl;
    _succeeded = false;
    return "ERROR";
}