Exemple #1
0
Trade::MeshData3D Capsule3D::solid(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, UnsignedInt segments, Float halfLength, TextureCoords textureCoords) {
    CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1 && segments >= 3, "Capsule must have at least one hemisphere ring, one cylinder ring and three segments", Trade::MeshData3D(MeshPrimitive::Triangles, std::vector<UnsignedInt>{}, std::vector<std::vector<Vector3>>{}, std::vector<std::vector<Vector3>>{}, std::vector<std::vector<Vector2>>{}));

    Implementation::Spheroid capsule(segments, textureCoords == TextureCoords::Generate ?
        Implementation::Spheroid::TextureCoords::Generate :
        Implementation::Spheroid::TextureCoords::DontGenerate);

    Float height = 2.0f+2.0f*halfLength;
    Float hemisphereTextureCoordsVIncrement = 1.0f/(hemisphereRings*height);
    Rad hemisphereRingAngleIncrement(Constants::pi()/(2*hemisphereRings));

    /* Bottom cap vertex */
    capsule.capVertex(-height/2, -1.0f, 0.0f);

    /* Rings of bottom hemisphere */
    capsule.hemisphereVertexRings(hemisphereRings-1, -halfLength, -Rad(Constants::pi())/2+hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement);

    /* Rings of cylinder */
    capsule.cylinderVertexRings(cylinderRings+1, -halfLength, 2.0f*halfLength/cylinderRings, 1.0f/height, 2.0f*halfLength/(cylinderRings*height));

    /* Rings of top hemisphere */
    capsule.hemisphereVertexRings(hemisphereRings-1, halfLength, hemisphereRingAngleIncrement, hemisphereRingAngleIncrement, (1.0f + 2.0f*halfLength)/height+hemisphereTextureCoordsVIncrement, hemisphereTextureCoordsVIncrement);

    /* Top cap vertex */
    capsule.capVertex(height/2, 1.0f, 1.0f);

    /* Faces */
    capsule.bottomFaceRing();
    capsule.faceRings(hemisphereRings*2-2+cylinderRings);
    capsule.topFaceRing();

    return capsule.finalize();
}
Exemple #2
0
Trade::MeshData3D Cylinder::solid(const UnsignedInt rings, const UnsignedInt segments, const Float halfLength, const Flags flags) {
    CORRADE_ASSERT(rings >= 1 && segments >= 3, "Primitives::Cylinder::solid(): cylinder must have at least one ring and three segments", Trade::MeshData3D(MeshPrimitive::Triangles, {}, {}, {}, {}));

    Implementation::Spheroid cylinder(segments, flags & Flag::GenerateTextureCoords ? Implementation::Spheroid::TextureCoords::Generate : Implementation::Spheroid::TextureCoords::DontGenerate);

    const Float length = 2.0f*halfLength;
    const Float textureCoordsV = flags & Flag::CapEnds ? 1.0f/(length+2.0f) : 0.0f;

    /* Bottom cap */
    if(flags & Flag::CapEnds) {
        cylinder.capVertex(-halfLength, -1.0f, 0.0f);
        cylinder.capVertexRing(-halfLength, textureCoordsV, Vector3::yAxis(-1.0f));
    }

    /* Vertex rings */
    cylinder.cylinderVertexRings(rings+1, -halfLength, length/rings, textureCoordsV, length/(rings*(flags & Flag::CapEnds ? length + 2.0f : length)));

    /* Top cap */
    if(flags & Flag::CapEnds) {
        cylinder.capVertexRing(halfLength, 1.0f - textureCoordsV, Vector3::yAxis(1.0f));
        cylinder.capVertex(halfLength, 1.0f, 1.0f);
    }

    /* Faces */
    if(flags & Flag::CapEnds) cylinder.bottomFaceRing();
    cylinder.faceRings(rings, flags & Flag::CapEnds ? 1 : 0);
    if(flags & Flag::CapEnds) cylinder.topFaceRing();

    return cylinder.finalize();
}
Exemple #3
0
template<UnsignedInt dimensions> ImageData<dimensions>::operator CompressedImageView<dimensions>() const
{
    CORRADE_ASSERT(_compressed, "Trade::ImageData::type(): the image is not compressed", (CompressedImageView<dimensions>{_compressedStorage, _compressedFormat, _size}));
    return CompressedImageView<dimensions>{
        _compressedStorage,
        _compressedFormat, _size, _data};
}
Exemple #4
0
Trade::MeshData3D UVSphere::solid(UnsignedInt rings, UnsignedInt segments, TextureCoords textureCoords) {
    CORRADE_ASSERT(rings >= 2 && segments >= 3, "UVSphere must have at least two rings and three segments", Trade::MeshData3D(Mesh::Primitive::Triangles, {}, {}, {}, {}));

    Implementation::Spheroid sphere(segments, textureCoords == TextureCoords::Generate ?
        Implementation::Spheroid::TextureCoords::Generate :
        Implementation::Spheroid::TextureCoords::DontGenerate);

    Float textureCoordsVIncrement = 1.0f/rings;
    Rad ringAngleIncrement(Constants::pi()/rings);

    /* Bottom cap vertex */
    sphere.capVertex(-1.0f, -1.0f, 0.0f);

    /* Vertex rings */
    sphere.hemisphereVertexRings(rings-1, 0.0f, -Rad(Constants::pi())/2+ringAngleIncrement, ringAngleIncrement, textureCoordsVIncrement, textureCoordsVIncrement);

    /* Top cap vertex */
    sphere.capVertex(1.0f, 1.0f, 1.0f);

    /* Faces */
    sphere.bottomFaceRing();
    sphere.faceRings(rings-2);
    sphere.topFaceRing();

    return sphere.finalize();
}
Exemple #5
0
Shader& Shader::addFile(const std::string& filename) {
    CORRADE_ASSERT(Utility::Directory::fileExists(filename),
        "Shader file " << '\'' + filename + '\'' << " cannot be read.", *this);

    addSource(Utility::Directory::readString(filename));
    return *this;
}
Containers::Array<unsigned char> AbstractFontConverter::doExportFontToSingleData(AbstractFont&, GlyphCache&, const std::u32string&) const
#else
Containers::Array<unsigned char> AbstractFontConverter::doExportFontToSingleData(AbstractFont&, GlyphCache&, const std::vector<char32_t>&) const
#endif
{
    CORRADE_ASSERT(false,
        "Text::AbstractFontConverter::exportFontToSingleData(): feature advertised but not implemented", nullptr);
}
Exemple #7
0
AbstractTexture* AbstractTexture::generateMipmap() {
    #ifndef MAGNUM_TARGET_GLES
    CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE, "AbstractTexture: rectangle textures cannot have mipmaps", this);
    #endif

    (this->*mipmapImplementation)();
    return this;
}
std::vector<std::pair<std::string, Containers::Array<char>>> AbstractFontConverter::doExportGlyphCacheToData(GlyphCache& cache, const std::string& filename) const {
    CORRADE_ASSERT(!(features() & Feature::MultiFile),
                   "Text::AbstractFontConverter::exportGlyphCacheToData(): feature advertised but not implemented", {});

    std::vector<std::pair<std::string, Containers::Array<char>>> out;
    out.emplace_back(filename, std::move(doExportGlyphCacheToSingleData(cache)));
    return out;
}
Exemple #9
0
AbstractTexture* AbstractTexture::setMinificationFilter(Filter filter, Mipmap mipmap) {
    #ifndef MAGNUM_TARGET_GLES
    CORRADE_ASSERT(_target != GL_TEXTURE_RECTANGLE || mipmap == Mipmap::Base, "AbstractTexture: rectangle textures cannot have mipmaps", this);
    #endif

    (this->*parameteriImplementation)(GL_TEXTURE_MIN_FILTER,
        static_cast<GLint>(filter)|static_cast<GLint>(mipmap));
    return this;
}
Exemple #10
0
bool Sdl2Application::tryCreateContext(const Configuration& configuration) {
    CORRADE_ASSERT(!context, "Platform::Sdl2Application::tryCreateContext(): context already created", false);

    /* Enable double buffering and 24bt depth buffer */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    /* Multisampling */
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration.sampleCount() > 1 ? 1 : 0);
    SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration.sampleCount());

    #ifndef CORRADE_TARGET_EMSCRIPTEN
    /* Context flags */
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(configuration.flags()));
    #endif

    /* Flags: if not hidden, set as shown */
    Uint32 windowFlags(configuration.windowFlags());
    if(!(configuration.windowFlags() & Configuration::WindowFlag::Hidden)) windowFlags |= SDL_WINDOW_SHOWN;

    /** @todo Remove when Emscripten has proper SDL2 support */
    #ifndef CORRADE_TARGET_EMSCRIPTEN
    /* Set context version, if requested */
    if(configuration.version() != Version::None) {
        Int major, minor;
        std::tie(major, minor) = version(configuration.version());
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);

        #ifndef MAGNUM_TARGET_GLES
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, configuration.version() >= Version::GL310 ?
            SDL_GL_CONTEXT_PROFILE_CORE : SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
        #else
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
        #endif
    }

    #ifdef MAGNUM_TARGET_GLES
    else {
        #ifdef MAGNUM_TARGET_GLES3
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        #elif defined(MAGNUM_TARGET_GLES2)
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
        #else
        #error Unsupported OpenGL ES version
        #endif
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
    }

    /* On OS X we need to create 3.2 context, as the default (2.1) contains
       compatibility features which are not implemented for newer GL versions
       in Apple's GL drivers, thus we would be forever stuck on 2.1 without the
       new features. In practice SDL fails to create 2.1 context on recent OS X
       versions. */
    #elif defined(__APPLE__)
    else {
Exemple #11
0
template<class Transformation> Object<Transformation>& Object<Transformation>::setParentKeepTransformation(Object<Transformation>* parent) {
    CORRADE_ASSERT(scene() == parent->scene(), "SceneGraph::Object::setParentKeepTransformation(): both parents must be in the same scene", *this);

    const auto transformation = Implementation::Transformation<Transformation>::compose(
        Implementation::Transformation<Transformation>::inverted(parent->absoluteTransformation()), absoluteTransformation());
    setParent(parent);
    Transformation::setTransformation(transformation);

    return *this;
}
Exemple #12
0
Trade::MeshData2D Capsule2D::wireframe(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, Float halfLength) {
    CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1, "Capsule must have at least one hemisphere ring, one cylinder ring and three segments", Trade::MeshData2D(MeshPrimitive::Lines, std::vector<UnsignedInt>{}, std::vector<std::vector<Vector2>>{}, std::vector<std::vector<Vector2>>{}));

    std::vector<Vector2> positions;
    positions.reserve(hemisphereRings*4+2+(cylinderRings-1)*2);
    const Rad angleIncrement(Constants::pi()/(2.0f*hemisphereRings));
    const Float cylinderIncrement = 2.0f*halfLength/cylinderRings;

    /* Bottom cap vertex */
    positions.emplace_back(0.0f, -halfLength-1.0f);

    /* Bottom hemisphere */
    for(UnsignedInt i = 0; i != hemisphereRings; ++i) {
        const Rad angle(Float(i+1)*angleIncrement);
        const Float x = Math::sin(angle);
        const Float y = -Math::cos(angle)-halfLength;
        positions.insert(positions.end(), {{-x, y}, {x, y}});
    }

    /* Cylinder (bottom and top vertices are done within caps */
    for(UnsignedInt i = 0; i != cylinderRings-1; ++i) {
        const Float y = (i+1)*cylinderIncrement-halfLength;
        positions.insert(positions.end(), {{-1.0f, y}, {1.0f, y}});
    }

    /* Top hemisphere */
    for(UnsignedInt i = 0; i != hemisphereRings; ++i) {
        const Rad angle(Float(i)*angleIncrement);
        const Float x = Math::cos(angle);
        const Float y = Math::sin(angle)+halfLength;
        positions.insert(positions.end(), {{-x, y}, {x, y}});
    }

    /* Top cap vertex */
    positions.emplace_back(0.0f, halfLength+1.0f);

    std::vector<UnsignedInt> indices;
    indices.reserve(hemisphereRings*8+cylinderRings*4);

    /* Bottom cap indices */
    indices.insert(indices.end(), {0, 1, 0, 2});

    /* Side indices */
    for(UnsignedInt i = 0; i != cylinderRings+hemisphereRings*2-2; ++i)
        indices.insert(indices.end(), {i*2+1, i*2+3,
                                       i*2+2, i*2+4});

    /* Top cap indices */
    indices.insert(indices.end(),
        {UnsignedInt(positions.size())-3, UnsignedInt(positions.size())-1,
         UnsignedInt(positions.size())-2, UnsignedInt(positions.size())-1});

    return Trade::MeshData2D(MeshPrimitive::Lines, std::move(indices), {std::move(positions)}, std::vector<std::vector<Vector2>>{});
}
std::vector<std::pair<std::string, Containers::Array<char>>> AbstractFontConverter::doExportFontToData(AbstractFont& font, GlyphCache& cache, const std::string& filename, const std::u32string& characters) const
#else
std::vector<std::pair<std::string, Containers::Array<char>>> AbstractFontConverter::doExportFontToData(AbstractFont& font, GlyphCache& cache, const std::string& filename, const std::vector<char32_t>& characters) const
#endif
{
    CORRADE_ASSERT(!(features() & Feature::MultiFile),
                   "Text::AbstractFontConverter::exportFontToData(): feature advertised but not implemented", {});

    std::vector<std::pair<std::string, Containers::Array<char>>> out;
    out.emplace_back(filename, std::move(doExportFontToSingleData(font, cache, characters)));
    return out;
}
std::unique_ptr<GlyphCache> AbstractFontConverter::doImportGlyphCacheFromFile(const std::string& filename) const {
    CORRADE_ASSERT(features() & Feature::ConvertData && !(features() & Feature::MultiFile),
                   "Text::AbstractFontConverter::importGlyphCacheFromFile(): not implemented", nullptr);

    /* Open file */
    if(!Utility::Directory::fileExists(filename)) {
        Error() << "Trade::AbstractFontConverter::importGlyphCacheFromFile(): cannot open file" << filename;
        return nullptr;
    }

    return doImportGlyphCacheFromSingleData(Utility::Directory::read(filename));
}
Exemple #15
0
std::pair<Float, Float> AbstractFont::doOpenFile(const std::string& filename, const Float size) {
    CORRADE_ASSERT(features() & Feature::OpenData && !(features() & Feature::MultiFile),
        "Text::AbstractFont::openFile(): not implemented", {});

    /* Open file */
    if(!Utility::Directory::fileExists(filename)) {
        Error() << "Trade::AbstractFont::openFile(): cannot open file" << filename;
        return {};
    }

    return doOpenSingleData(Utility::Directory::read(filename), size);
}
Exemple #16
0
void* Buffer::mapSub(const GLintptr offset, const GLsizeiptr length, const MapAccess access) {
    /** @todo Enable also in Emscripten (?) when extension loader is available */
    #ifdef CORRADE_TARGET_NACL
    CORRADE_ASSERT(!_mappedBuffer, "Buffer::mapSub(): the buffer is already mapped", nullptr);
    return _mappedBuffer = glMapBufferSubDataCHROMIUM(GLenum(bindInternal(_targetHint)), offset, length, GLenum(access));
    #else
    CORRADE_INTERNAL_ASSERT(false);
    static_cast<void>(offset);
    static_cast<void>(length);
    static_cast<void>(access);
    #endif
}
Exemple #17
0
Trade::MeshData3D UVSphere::wireframe(const UnsignedInt rings, const UnsignedInt segments) {
    CORRADE_ASSERT(rings >= 2 && rings%2 == 0 && segments >= 4 && segments%2 == 0, "Primitives::UVSphere::wireframe(): improper parameters", Trade::MeshData3D(Mesh::Primitive::Lines, {}, {}, {}, {}));

    Implementation::WireframeSpheroid sphere(segments/4);

    /* Make sphere */
    sphere.bottomHemisphere(0.0f, rings/2);
    sphere.ring(0.0f);
    sphere.topHemisphere(0.0f, rings/2);

    return sphere.finalize();
}
Exemple #18
0
bool Shader::compile() {
    CORRADE_ASSERT(sources.size() > 1, "Shader::compile(): no files added", false);

    /* Array of source string pointers and their lengths */
    /** @todo Use `Containers::ArrayTuple` to avoid one allocation if it ever
        gets to be implemented (we need properly aligned memory too) */
    Containers::Array<const GLchar*> pointers(sources.size());
    Containers::Array<GLint> sizes(sources.size());
    for(std::size_t i = 0; i != sources.size(); ++i) {
        pointers[i] = static_cast<const GLchar*>(sources[i].data());
        sizes[i] = sources[i].size();
    }

    /* Create shader and set its source */
    glShaderSource(_id, sources.size(), pointers, sizes);

    /* Compile shader */
    glCompileShader(_id);

    /* Check compilation status */
    GLint success, logLength;
    glGetShaderiv(_id, GL_COMPILE_STATUS, &success);
    glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength);

    /* Error or warning message. The string is returned null-terminated, scrap
       the \0 at the end afterwards */
    std::string message(logLength, '\0');
    if(message.size() > 1)
        glGetShaderInfoLog(_id, message.size(), nullptr, &message[0]);
    message.resize(std::max(logLength, 1)-1);

    /* Show error log */
    if(!success) {
        Error out;
        out.setFlag(Debug::NewLineAtTheEnd, false);
        out.setFlag(Debug::SpaceAfterEachValue, false);
        out << "Shader: " << shaderName(_type)
            << " shader failed to compile with the following message:\n"
            << message;

    /* Or just message, if any */
    } else if(!message.empty()) {
        Error out;
        out.setFlag(Debug::NewLineAtTheEnd, false);
        out.setFlag(Debug::SpaceAfterEachValue, false);
        out << "Shader: " << shaderName(_type)
            << " shader was successfully compiled with the following message:\n"
            << message;
    }

    return success;
}
bool AbstractFontConverter::doExportGlyphCacheToFile(GlyphCache& cache, const std::string& filename) const {
    CORRADE_ASSERT(features() & Feature::ConvertData,
                   "Text::AbstractFontConverter::exportGlyphCacheToFile(): not implemented", false);

    /* Export all data */
    const auto data = doExportGlyphCacheToData(cache, filename);
    for(const auto& d: data) if(!Utility::Directory::write(d.first, d.second)) {
            Error() << "Text::AbstractFontConverter::exportGlyphCacheToFile(): cannot write to file" << d.first;
            return false;
        }

    return true;
}
Exemple #20
0
template<> Long AbstractQuery::result<Long>() {
    CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});

    /** @todo Re-enable when extension loader is available for ES */
    Long result;
    #ifndef MAGNUM_TARGET_GLES
    glGetQueryObjecti64v(_id, GL_QUERY_RESULT, &result);
    #else
    CORRADE_INTERNAL_ASSERT(false);
    //glGetQueryObjecti64vEXT(_id, GL_QUERY_RESULT, &result);
    #endif
    return result;
}
bool AbstractImageConverter::doExportToFile(const ImageView2D& image, const std::string& filename) {
    CORRADE_ASSERT(features() & Feature::ConvertData, "Trade::AbstractImageConverter::exportToFile(): not implemented", false);

    const auto data = doExportToData(image);
    if(!data) return false;

    /* Open file */
    if(!Utility::Directory::write(filename, data)) {
        Error() << "Trade::AbstractImageConverter::exportToFile(): cannot write to file" << filename;
        return false;
    }

    return true;
}
Exemple #22
0
template<> UnsignedInt AbstractQuery::result<UnsignedInt>() {
    CORRADE_ASSERT(!target, "AbstractQuery::result(): the query is currently running", {});

    /** @todo Re-enable when extension loader is available for ES */
    UnsignedInt result;
    #ifndef MAGNUM_TARGET_GLES2
    glGetQueryObjectuiv(_id, GL_QUERY_RESULT, &result);
    #elif defined(CORRADE_TARGET_NACL)
    glGetQueryObjectuivEXT(_id, GL_QUERY_RESULT_EXT, &result);
    #else
    CORRADE_INTERNAL_ASSERT(false);
    #endif
    return result;
}
Exemple #23
0
bool AbstractQuery::resultAvailable() {
    CORRADE_ASSERT(!target, "AbstractQuery::resultAvailable(): the query is currently running", false);

    /** @todo Re-enable when extension loader is available for ES */
    GLuint result;
    #ifndef MAGNUM_TARGET_GLES2
    glGetQueryObjectuiv(_id, GL_QUERY_RESULT_AVAILABLE, &result);
    #elif defined(CORRADE_TARGET_NACL)
    glGetQueryObjectuivEXT(_id, GL_QUERY_RESULT_AVAILABLE_EXT, &result);
    #else
    CORRADE_INTERNAL_ASSERT(false);
    #endif
    return result == GL_TRUE;
}
std::pair<std::vector<UnsignedInt>, std::vector<UnsignedInt>> combineIndexArrays(const std::vector<UnsignedInt>& interleavedArrays, const UnsignedInt stride) {
    CORRADE_ASSERT(stride != 0, "MeshTools::combineIndexArrays(): stride can't be zero", {});
    CORRADE_ASSERT(interleavedArrays.size() % stride == 0, "MeshTools::combineIndexArrays(): array size is not divisible by stride", {});

    /* Hash map with index combinations, containing just indices into
       interleavedArrays vector, hashing and comparison is done using IndexHash
       and IndexEqual functors. Reserving more buckets than necessary (i.e. as
       if each combination was unique). */
    std::unordered_map<UnsignedInt, UnsignedInt, IndexHash, IndexEqual> indexCombinations(
        interleavedArrays.size()/stride,
        IndexHash(interleavedArrays, stride),
        IndexEqual(interleavedArrays, stride));

    /* Make the index combinations unique. Original indices into original
       `interleavedArrays` array were 0, 1, 2, 3, ..., `combinedIndices`
       contains new ones into new (shorter) `newInterleavedArrays` array. */
    std::vector<UnsignedInt> combinedIndices;
    combinedIndices.reserve(interleavedArrays.size()/stride);
    std::vector<UnsignedInt> newInterleavedArrays;
    for(std::size_t oldIndex = 0, end = interleavedArrays.size()/stride; oldIndex != end; ++oldIndex) {
        /* Try to insert new index combination to the map */
        const auto result = indexCombinations.emplace(oldIndex, indexCombinations.size());

        /* Add the (either new or already existing) index to resulting index array */
        combinedIndices.push_back(result.first->second);

        /* If this is new combination, copy it to new interleaved arrays */
        if(result.second) newInterleavedArrays.insert(newInterleavedArrays.end(),
            interleavedArrays.begin()+oldIndex*stride,
            interleavedArrays.begin()+(oldIndex+1)*stride);
    }

    CORRADE_INTERNAL_ASSERT(combinedIndices.size() == interleavedArrays.size()/stride &&
                            newInterleavedArrays.size() <= interleavedArrays.size());

    return {std::move(combinedIndices), std::move(newInterleavedArrays)};
}
bool AbstractXApplication::tryCreateContext(const Configuration& configuration) {
    CORRADE_ASSERT(!_context, "AbstractXApplication::tryCreateContext(): context already created", false);

    _viewportSize = configuration.size();

    /* Get default X display */
    _display = XOpenDisplay(nullptr);

    /* Get visual ID */
    VisualID visualId = _contextHandler->getVisualId(_display);

    /* Get visual info */
    XVisualInfo *visInfo, visTemplate;
    int visualCount;
    visTemplate.visualid = visualId;
    visInfo = XGetVisualInfo(_display, VisualIDMask, &visTemplate, &visualCount);
    if(!visInfo) {
        Error() << "Platform::WindowlessGlxApplication::tryCreateContext(): cannot get X visual";
        return false;
    }

    /* Create X Window */
    Window root = RootWindow(_display, DefaultScreen(_display));
    XSetWindowAttributes attr;
    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = XCreateColormap(_display, root, visInfo->visual, AllocNone);
    attr.event_mask = 0;
    unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask;
    _window = XCreateWindow(_display, root, 20, 20, configuration.size().x(), configuration.size().y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
    XSetStandardProperties(_display, _window, configuration.title().data(), nullptr, 0, nullptr, 0, nullptr);
    XFree(visInfo);

    /* Be notified about closing the window */
    _deleteWindow = XInternAtom(_display, "WM_DELETE_WINDOW", True);
    XSetWMProtocols(_display, _window, &_deleteWindow, 1);

    /* Create context */
    _contextHandler->createContext(configuration, _window);

    /* Capture exposure, keyboard and mouse button events */
    XSelectInput(_display, _window, INPUT_MASK);

    /* Set OpenGL context as current */
    _contextHandler->makeCurrent();

    _context.reset(new Platform::Context);
    return true;
}
Exemple #26
0
bool Shader::compile() {
    CORRADE_ASSERT(sources.size() > 1, "Shader::compile(): no files added", false);

    /* Array of sources */
    const GLchar** _sources = new const GLchar*[sources.size()];
    for(std::size_t i = 0; i != sources.size(); ++i)
        _sources[i] = static_cast<const GLchar*>(sources[i].c_str());

    /* Create shader and set its source */
    glShaderSource(_id, sources.size(), _sources, nullptr);

    /* Compile shader */
    glCompileShader(_id);
    delete _sources;

    /* Check compilation status */
    GLint success, logLength;
    glGetShaderiv(_id, GL_COMPILE_STATUS, &success);
    glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength);

    /* Error or warning message. The string is returned null-terminated, scrap
       the \0 at the end afterwards */
    std::string message(logLength, '\0');
    if(message.size() > 1)
        glGetShaderInfoLog(_id, message.size(), nullptr, &message[0]);
    message.resize(std::max(logLength, 1)-1);

    /* Show error log */
    if(!success) {
        Error out;
        out.setFlag(Debug::NewLineAtTheEnd, false);
        out.setFlag(Debug::SpaceAfterEachValue, false);
        out << "Shader: " << shaderName(_type)
            << " shader failed to compile with the following message:\n"
            << message;

    /* Or just message, if any */
    } else if(!message.empty()) {
        Error out;
        out.setFlag(Debug::NewLineAtTheEnd, false);
        out.setFlag(Debug::SpaceAfterEachValue, false);
        out << "Shader: " << shaderName(_type)
            << " shader was successfully compiled with the following message:\n"
            << message;
    }

    return success;
}
bool WindowlessCglApplication::tryCreateContext(const Configuration&) {
    CORRADE_ASSERT(!_context, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false);

    int formatCount;
    CGLPixelFormatAttribute attributes32[] = {
        kCGLPFAAccelerated,
        kCGLPFAOpenGLProfile,
        CGLPixelFormatAttribute(kCGLOGLPVersion_3_2_Core),
        CGLPixelFormatAttribute(0)
    };
    if(CGLChoosePixelFormat(attributes32, &_pixelFormat, &formatCount) != kCGLNoError) {
        Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot choose pixel format for GL 3.2, falling back to 3.0";

        CGLPixelFormatAttribute attributes30[] = {
            kCGLPFAAccelerated,
            kCGLPFAOpenGLProfile,
            CGLPixelFormatAttribute(kCGLOGLPVersion_GL3_Core),
            CGLPixelFormatAttribute(0)
        };
        if(CGLChoosePixelFormat(attributes30, &_pixelFormat, &formatCount) != kCGLNoError) {
            Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot choose pixel format for GL 3.0, falling back to 2.1";

            CGLPixelFormatAttribute attributes21[] = {
                kCGLPFAAccelerated,
                kCGLPFAOpenGLProfile,
                CGLPixelFormatAttribute(kCGLOGLPVersion_Legacy),
                CGLPixelFormatAttribute(0)
            };
            if(CGLChoosePixelFormat(attributes21, &_pixelFormat, &formatCount) != kCGLNoError) {
                Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot choose pixel format";
                return false;
            }
        }
    }

    if(CGLCreateContext(_pixelFormat, nullptr, &_glContext) != kCGLNoError) {
        Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot create context";
        return false;
    }

    if(CGLSetCurrentContext(_glContext) != kCGLNoError) {
        Error() << "Platform::WindowlessCglApplication::tryCreateContext(): cannot make context current";
        return false;
    }

    _context.reset(new Platform::Context);
    return true;
}
Exemple #28
0
Trade::MeshData2D Circle::wireframe(UnsignedInt segments) {
    CORRADE_ASSERT(segments >= 3, "Primitives::Circle::wireframe(): segments must be >= 3",
        Trade::MeshData2D(Mesh::Primitive::LineLoop, {}, {}, {}));

    std::vector<Vector2> positions;
    positions.reserve(segments);

    /* Points on circle */
    const Rad angleIncrement(2*Constants::pi()/segments);
    for(UnsignedInt i = 0; i != segments; ++i) {
        const Rad angle(i*angleIncrement);
        positions.emplace_back(Math::cos(angle), Math::sin(angle));
    }

    return Trade::MeshData2D(Mesh::Primitive::LineLoop, {}, {std::move(positions)}, {});
}
Trade::MeshData3D Cylinder::wireframe(const UnsignedInt rings, const UnsignedInt segments, const Float halfLength) {
    CORRADE_ASSERT(rings >= 1 && segments >= 4 && segments%4 == 0, "Primitives::Cylinder::wireframe(): improper parameters", Trade::MeshData3D(MeshPrimitive::Lines, {}, {}, {}, {}));

    Implementation::WireframeSpheroid cylinder(segments/4);

    const Float increment = 2*halfLength/rings;

    /* Rings */
    cylinder.ring(-halfLength);
    for(UnsignedInt i = 0; i != rings; ++i) {
        cylinder.cylinder();
        cylinder.ring(-halfLength + (i+1)*increment);
    }

    return cylinder.finalize();
}
bool AbstractFontConverter::doExportFontToFile(AbstractFont& font, GlyphCache& cache, const std::string& filename, const std::u32string& characters) const
#else
bool AbstractFontConverter::doExportFontToFile(AbstractFont& font, GlyphCache& cache, const std::string& filename, const std::vector<char32_t>& characters) const
#endif
{
    CORRADE_ASSERT(features() & Feature::ConvertData,
                   "Text::AbstractFontConverter::exportFontToFile(): not implemented", false);

    /* Export all data */
    const auto data = doExportFontToData(font, cache, filename, characters);
    for(const auto& d: data) if(!Utility::Directory::write(d.first, d.second)) {
            Error() << "Text::AbstractFontConverter::exportFontToFile(): cannot write to file" << d.first;
            return false;
        }

    return true;
}