<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreGLES2FrameBufferObject.h"
#include "OgreGLES2HardwarePixelBuffer.h"
#include "OgreGLES2FBORenderTexture.h"
#include "OgreGLES2DepthBuffer.h"
#include "OgreGLUtil.h"
#include "OgreRoot.h"
#include "OgreGLES2RenderSystem.h"
#include "OgreGLES2Support.h"

namespace Ogre {

//-----------------------------------------------------------------------------
    GLES2FrameBufferObject::GLES2FrameBufferObject(GLES2FBOManager *manager, uint fsaa):
        mManager(manager), mNumSamples(fsaa)
    {
        GLES2Support* glSupport = getGLES2SupportRef();

        // Generate framebuffer object
        OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mFB));

	   if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_DEBUG))
       {
           OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mFB, 0, ("FBO #" + StringConverter::toString(mFB)).c_str()));
       }

        // Check multisampling if supported
        GLint maxSamples = 0;
        if(glSupport->hasMinGLVersion(3, 0))
        {
            // Check samples supported
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));
            OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamples));
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
        }
        mNumSamples = std::min(mNumSamples, (GLsizei)maxSamples);

        // Will we need a second FBO to do multisampling?
        if (mNumSamples)
        {
            OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mMultisampleFB));
            if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_DEBUG))
            {
                OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mMultisampleFB, 0, ("MSAA FBO #" + StringConverter::toString(mMultisampleFB)).c_str()));
            }
        }
        else
        {
            mMultisampleFB = 0;
        }

        // Initialise state
        mDepth.buffer = 0;
        mStencil.buffer = 0;
        for(size_t x = 0; x < OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
        {
            mColour[x].buffer=0;
        }
    }

    GLES2FrameBufferObject::~GLES2FrameBufferObject()
    {
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
        mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        // Delete framebuffer object
        OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mFB));

        if (mMultisampleFB)
            OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mMultisampleFB));
    }

#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
    void GLES2FrameBufferObject::notifyOnContextLost()
    {
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
        mManager->releaseRenderBuffer(mMultisampleColourBuffer);

        OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mFB));

        if (mMultisampleFB)
            OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mMultisampleFB));
    }

    void GLES2FrameBufferObject::notifyOnContextReset(const GLES2SurfaceDesc &target)
    {
        // Generate framebuffer object
        OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mFB));
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));

        // Bind target to surface 0 and initialise
        bindSurface(0, target);
    }
#endif

    void GLES2FrameBufferObject::bindSurface(size_t attachment, const GLES2SurfaceDesc &target)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment] = target;
        // Re-initialise
        if(mColour[0].buffer)
            initialise();
    }

    void GLES2FrameBufferObject::unbindSurface(size_t attachment)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment].buffer = 0;
        // Re-initialise if buffer 0 still bound
        if(mColour[0].buffer)
            initialise();
    }

    void GLES2FrameBufferObject::initialise()
    {
        // Release depth and stencil, if they were bound
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
        mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        // First buffer must be bound
        if(!mColour[0].buffer)
        {
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                "Attachment 0 must have surface attached",
                "GLES2FrameBufferObject::initialise");
        }

        // If we're doing multisampling, then we need another FBO which contains a
        // renderbuffer which is set up to multisample, and we'll blit it to the final
        // FBO afterwards to perform the multisample resolve. In that case, the
        // mMultisampleFB is bound during rendering and is the one with a depth/stencil

        // Store basic stats
        uint32 width = mColour[0].buffer->getWidth();
        uint32 height = mColour[0].buffer->getHeight();
        GLuint format = mColour[0].buffer->getGLFormat();
        ushort maxSupportedMRTs = Root::getSingleton().getRenderSystem()->getCapabilities()->getNumMultiRenderTargets();

        // Bind simple buffer to add colour attachments
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));

        // Bind all attachment points to frame buffer
        for(unsigned int x = 0; x < maxSupportedMRTs; ++x)
        {
            if(mColour[x].buffer)
            {
                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible size ";
                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
                    ss << ". It must be of the same as the size of surface 0, ";
                    ss << width << "x" << height;
                    ss << ".";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLES2FrameBufferObject::initialise");
                }
                if(mColour[x].buffer->getGLFormat() != format)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible format.";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLES2FrameBufferObject::initialise");
                }
                if(getFormat() == PF_DEPTH)
                    mColour[x].buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT, mColour[x].zoffset);
                else
                    mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0+x, mColour[x].zoffset);
            }
            else
            {
                // Detach
                OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0+x), GL_RENDERBUFFER, 0));
            }
        }

        // Now deal with depth / stencil
        if (mMultisampleFB)
        {
            // Bind multisample buffer
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFB));

            // Create AA render buffer (colour)
            // note, this can be shared too because we blit it to the final FBO
            // right after the render is finished
            mMultisampleColourBuffer = mManager->requestRenderBuffer(format, width, height, mNumSamples);

            // Attach it, because we won't be attaching below and non-multisample has
            // actually been attached to other FBO
            mMultisampleColourBuffer.buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0,
                mMultisampleColourBuffer.zoffset);

            // depth & stencil will be dealt with below
        }

        // Depth buffer is not handled here anymore.
        // See GLES2FrameBufferObject::attachDepthBuffer() & RenderSystem::setDepthBufferFor()

#if OGRE_NO_GLES3_SUPPORT == 0
        GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
        GLsizei n=0;
        for(unsigned int x=0; x<maxSupportedMRTs; ++x)
        {
            // Fill attached colour buffers
            if(mColour[x].buffer)
            {
                if(getFormat() == PF_DEPTH)
                    bufs[x] = GL_DEPTH_ATTACHMENT;
                else
                    bufs[x] = GL_COLOR_ATTACHMENT0 + x;
                // Keep highest used buffer + 1
                n = x+1;
            }
            else
            {
                bufs[x] = GL_NONE;
            }
        }

        // Drawbuffer extension supported, use it
        if(getFormat() != PF_DEPTH)
            OGRE_CHECK_GL_ERROR(glDrawBuffers(n, bufs));

        if (mMultisampleFB)
        {
            // we need a read buffer because we'll be blitting to mFB
            OGRE_CHECK_GL_ERROR(glReadBuffer(bufs[0]));
        }
        else
        {
            // No read buffer, by default, if we want to read anyway we must not forget to set this.
            OGRE_CHECK_GL_ERROR(glReadBuffer(GL_NONE));
        }
#endif
        // Check status
        GLuint status;
        OGRE_CHECK_GL_ERROR(status = glCheckFramebufferStatus(GL_FRAMEBUFFER));

        // Bind main buffer
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
        // The screen buffer is 1 on iOS
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 1));
#else
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
#endif

        switch(status)
        {
        case GL_FRAMEBUFFER_COMPLETE:
            // All is good
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                "All framebuffer formats with this texture internal format unsupported",
                "GLES2FrameBufferObject::initialise");
        default:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                "Framebuffer incomplete or other FBO status error",
                "GLES2FrameBufferObject::initialise");
        }

    }

    void GLES2FrameBufferObject::bind()
    {
        // Bind it to FBO
        const GLuint fb = mMultisampleFB ? mMultisampleFB : mFB;
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fb));
    }

    void GLES2FrameBufferObject::swapBuffers()
    {
        if (mMultisampleFB)
        {
#if OGRE_NO_GLES3_SUPPORT == 0
            GLint oldfb = 0;
            OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb));

            // Blit from multisample buffer to final buffer, triggers resolve
            uint32 width = mColour[0].buffer->getWidth();
            uint32 height = mColour[0].buffer->getHeight();
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, mMultisampleFB));
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFB));
            OGRE_CHECK_GL_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
            // Unbind
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, oldfb));
#endif
        }
    }

    void GLES2FrameBufferObject::attachDepthBuffer( DepthBuffer *depthBuffer )
    {
        GLES2DepthBuffer *glDepthBuffer = static_cast<GLES2DepthBuffer*>(depthBuffer);
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFB ? mMultisampleFB : mFB ));

        if( glDepthBuffer )
        {
            GLES2RenderBuffer *depthBuf   = glDepthBuffer->getDepthBuffer();
            GLES2RenderBuffer *stencilBuf = glDepthBuffer->getStencilBuffer();

            //Attach depth buffer, if it has one.
            if( depthBuf )
                depthBuf->bindToFramebuffer( GL_DEPTH_ATTACHMENT, 0 );

            //Attach stencil buffer, if it has one.
            if( stencilBuf )
                stencilBuf->bindToFramebuffer( GL_STENCIL_ATTACHMENT, 0 );
        }
        else
        {
            OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                                          GL_RENDERBUFFER, 0));
            OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                                                          GL_RENDERBUFFER, 0));
        }
    }
    //-----------------------------------------------------------------------------
    void GLES2FrameBufferObject::detachDepthBuffer()
    {
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFB ? mMultisampleFB : mFB ));
        OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0 ));
        OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                                                      GL_RENDERBUFFER, 0 ));
    }

    uint32 GLES2FrameBufferObject::getWidth()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getWidth();
    }
    uint32 GLES2FrameBufferObject::getHeight()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getHeight();
    }
    PixelFormat GLES2FrameBufferObject::getFormat()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getFormat();
    }
    GLsizei GLES2FrameBufferObject::getFSAA()
    {
        return mNumSamples;
    }
//-----------------------------------------------------------------------------
}
<commit_msg>GLES2: multi-sampled FBO requires GLES3 at compile time for now<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreGLES2FrameBufferObject.h"
#include "OgreGLES2HardwarePixelBuffer.h"
#include "OgreGLES2FBORenderTexture.h"
#include "OgreGLES2DepthBuffer.h"
#include "OgreGLUtil.h"
#include "OgreRoot.h"
#include "OgreGLES2RenderSystem.h"
#include "OgreGLES2Support.h"

namespace Ogre {

//-----------------------------------------------------------------------------
    GLES2FrameBufferObject::GLES2FrameBufferObject(GLES2FBOManager *manager, uint fsaa):
        mManager(manager), mNumSamples(fsaa)
    {
        // Generate framebuffer object
        OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mFB));

	   if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_DEBUG))
       {
           OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mFB, 0, ("FBO #" + StringConverter::toString(mFB)).c_str()));
       }

        // Check multisampling if supported
        GLint maxSamples = 0;
        if(!OGRE_NO_GLES3_SUPPORT)
        {
            // Check samples supported
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));
            OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_MAX_SAMPLES_APPLE, &maxSamples));
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
        }
        mNumSamples = std::min(mNumSamples, (GLsizei)maxSamples);

        // Will we need a second FBO to do multisampling?
        if (mNumSamples)
        {
            OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mMultisampleFB));
            if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_DEBUG))
            {
                OGRE_CHECK_GL_ERROR(glLabelObjectEXT(GL_BUFFER_OBJECT_EXT, mMultisampleFB, 0, ("MSAA FBO #" + StringConverter::toString(mMultisampleFB)).c_str()));
            }
        }
        else
        {
            mMultisampleFB = 0;
        }

        // Initialise state
        mDepth.buffer = 0;
        mStencil.buffer = 0;
        for(size_t x = 0; x < OGRE_MAX_MULTIPLE_RENDER_TARGETS; ++x)
        {
            mColour[x].buffer=0;
        }
    }

    GLES2FrameBufferObject::~GLES2FrameBufferObject()
    {
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
        mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        // Delete framebuffer object
        OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mFB));

        if (mMultisampleFB)
            OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mMultisampleFB));
    }

#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
    void GLES2FrameBufferObject::notifyOnContextLost()
    {
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
        mManager->releaseRenderBuffer(mMultisampleColourBuffer);

        OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mFB));

        if (mMultisampleFB)
            OGRE_CHECK_GL_ERROR(glDeleteFramebuffers(1, &mMultisampleFB));
    }

    void GLES2FrameBufferObject::notifyOnContextReset(const GLES2SurfaceDesc &target)
    {
        // Generate framebuffer object
        OGRE_CHECK_GL_ERROR(glGenFramebuffers(1, &mFB));
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));

        // Bind target to surface 0 and initialise
        bindSurface(0, target);
    }
#endif

    void GLES2FrameBufferObject::bindSurface(size_t attachment, const GLES2SurfaceDesc &target)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment] = target;
        // Re-initialise
        if(mColour[0].buffer)
            initialise();
    }

    void GLES2FrameBufferObject::unbindSurface(size_t attachment)
    {
        assert(attachment < OGRE_MAX_MULTIPLE_RENDER_TARGETS);
        mColour[attachment].buffer = 0;
        // Re-initialise if buffer 0 still bound
        if(mColour[0].buffer)
            initialise();
    }

    void GLES2FrameBufferObject::initialise()
    {
        // Release depth and stencil, if they were bound
        mManager->releaseRenderBuffer(mDepth);
        mManager->releaseRenderBuffer(mStencil);
        mManager->releaseRenderBuffer(mMultisampleColourBuffer);
        // First buffer must be bound
        if(!mColour[0].buffer)
        {
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                "Attachment 0 must have surface attached",
                "GLES2FrameBufferObject::initialise");
        }

        // If we're doing multisampling, then we need another FBO which contains a
        // renderbuffer which is set up to multisample, and we'll blit it to the final
        // FBO afterwards to perform the multisample resolve. In that case, the
        // mMultisampleFB is bound during rendering and is the one with a depth/stencil

        // Store basic stats
        uint32 width = mColour[0].buffer->getWidth();
        uint32 height = mColour[0].buffer->getHeight();
        GLuint format = mColour[0].buffer->getGLFormat();
        ushort maxSupportedMRTs = Root::getSingleton().getRenderSystem()->getCapabilities()->getNumMultiRenderTargets();

        // Bind simple buffer to add colour attachments
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mFB));

        // Bind all attachment points to frame buffer
        for(unsigned int x = 0; x < maxSupportedMRTs; ++x)
        {
            if(mColour[x].buffer)
            {
                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible size ";
                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
                    ss << ". It must be of the same as the size of surface 0, ";
                    ss << width << "x" << height;
                    ss << ".";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLES2FrameBufferObject::initialise");
                }
                if(mColour[x].buffer->getGLFormat() != format)
                {
                    StringStream ss;
                    ss << "Attachment " << x << " has incompatible format.";
                    OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, ss.str(), "GLES2FrameBufferObject::initialise");
                }
                if(getFormat() == PF_DEPTH)
                    mColour[x].buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT, mColour[x].zoffset);
                else
                    mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0+x, mColour[x].zoffset);
            }
            else
            {
                // Detach
                OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer(GL_FRAMEBUFFER, static_cast<GLenum>(GL_COLOR_ATTACHMENT0+x), GL_RENDERBUFFER, 0));
            }
        }

        // Now deal with depth / stencil
        if (mMultisampleFB)
        {
            // Bind multisample buffer
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFB));

            // Create AA render buffer (colour)
            // note, this can be shared too because we blit it to the final FBO
            // right after the render is finished
            mMultisampleColourBuffer = mManager->requestRenderBuffer(format, width, height, mNumSamples);

            // Attach it, because we won't be attaching below and non-multisample has
            // actually been attached to other FBO
            mMultisampleColourBuffer.buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0,
                mMultisampleColourBuffer.zoffset);

            // depth & stencil will be dealt with below
        }

        // Depth buffer is not handled here anymore.
        // See GLES2FrameBufferObject::attachDepthBuffer() & RenderSystem::setDepthBufferFor()

#if OGRE_NO_GLES3_SUPPORT == 0
        GLenum bufs[OGRE_MAX_MULTIPLE_RENDER_TARGETS];
        GLsizei n=0;
        for(unsigned int x=0; x<maxSupportedMRTs; ++x)
        {
            // Fill attached colour buffers
            if(mColour[x].buffer)
            {
                if(getFormat() == PF_DEPTH)
                    bufs[x] = GL_DEPTH_ATTACHMENT;
                else
                    bufs[x] = GL_COLOR_ATTACHMENT0 + x;
                // Keep highest used buffer + 1
                n = x+1;
            }
            else
            {
                bufs[x] = GL_NONE;
            }
        }

        // Drawbuffer extension supported, use it
        if(getFormat() != PF_DEPTH)
            OGRE_CHECK_GL_ERROR(glDrawBuffers(n, bufs));

        if (mMultisampleFB)
        {
            // we need a read buffer because we'll be blitting to mFB
            OGRE_CHECK_GL_ERROR(glReadBuffer(bufs[0]));
        }
        else
        {
            // No read buffer, by default, if we want to read anyway we must not forget to set this.
            OGRE_CHECK_GL_ERROR(glReadBuffer(GL_NONE));
        }
#endif
        // Check status
        GLuint status;
        OGRE_CHECK_GL_ERROR(status = glCheckFramebufferStatus(GL_FRAMEBUFFER));

        // Bind main buffer
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
        // The screen buffer is 1 on iOS
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 1));
#else
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
#endif

        switch(status)
        {
        case GL_FRAMEBUFFER_COMPLETE:
            // All is good
            break;
        case GL_FRAMEBUFFER_UNSUPPORTED:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                "All framebuffer formats with this texture internal format unsupported",
                "GLES2FrameBufferObject::initialise");
        default:
            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
                "Framebuffer incomplete or other FBO status error",
                "GLES2FrameBufferObject::initialise");
        }

    }

    void GLES2FrameBufferObject::bind()
    {
        // Bind it to FBO
        const GLuint fb = mMultisampleFB ? mMultisampleFB : mFB;
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fb));
    }

    void GLES2FrameBufferObject::swapBuffers()
    {
        if (mMultisampleFB)
        {
#if OGRE_NO_GLES3_SUPPORT == 0
            GLint oldfb = 0;
            OGRE_CHECK_GL_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb));

            // Blit from multisample buffer to final buffer, triggers resolve
            uint32 width = mColour[0].buffer->getWidth();
            uint32 height = mColour[0].buffer->getHeight();
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, mMultisampleFB));
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFB));
            OGRE_CHECK_GL_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST));
            // Unbind
            OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, oldfb));
#endif
        }
    }

    void GLES2FrameBufferObject::attachDepthBuffer( DepthBuffer *depthBuffer )
    {
        GLES2DepthBuffer *glDepthBuffer = static_cast<GLES2DepthBuffer*>(depthBuffer);
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFB ? mMultisampleFB : mFB ));

        if( glDepthBuffer )
        {
            GLES2RenderBuffer *depthBuf   = glDepthBuffer->getDepthBuffer();
            GLES2RenderBuffer *stencilBuf = glDepthBuffer->getStencilBuffer();

            //Attach depth buffer, if it has one.
            if( depthBuf )
                depthBuf->bindToFramebuffer( GL_DEPTH_ATTACHMENT, 0 );

            //Attach stencil buffer, if it has one.
            if( stencilBuf )
                stencilBuf->bindToFramebuffer( GL_STENCIL_ATTACHMENT, 0 );
        }
        else
        {
            OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                                          GL_RENDERBUFFER, 0));
            OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                                                          GL_RENDERBUFFER, 0));
        }
    }
    //-----------------------------------------------------------------------------
    void GLES2FrameBufferObject::detachDepthBuffer()
    {
        OGRE_CHECK_GL_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, mMultisampleFB ? mMultisampleFB : mFB ));
        OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0 ));
        OGRE_CHECK_GL_ERROR(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
                                                      GL_RENDERBUFFER, 0 ));
    }

    uint32 GLES2FrameBufferObject::getWidth()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getWidth();
    }
    uint32 GLES2FrameBufferObject::getHeight()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getHeight();
    }
    PixelFormat GLES2FrameBufferObject::getFormat()
    {
        assert(mColour[0].buffer);
        return mColour[0].buffer->getFormat();
    }
    GLsizei GLES2FrameBufferObject::getFSAA()
    {
        return mNumSamples;
    }
//-----------------------------------------------------------------------------
}
<|endoftext|>


<commit_before>//! @Alan
//!
//! Exercise 6.33:
//! Write a recursive function to print the contents of a vector.
//!
//  question about this exercise on stackoverflow:
//  http://stackoverflow.com/questions/20184299/how-to-understand-and-fix-the-segmentation-fault-in-this-code

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

using namespace std;

//!
//! @brief      my code...can handle fixed size vector, cann't handle vectors
//!             that change size during rumtime..
//!
//! @author     @Alan
//!
//! @badcode    Misc Comment: Stop using underscores to start your variable names.
//!             _v is a really bad name, just go with v. @ RichardPlunkett.
//!
template<class T>
void  vector_print(const vector<T> &_v);

//!
//! @brief      a better approach
//!
//! @author     @Shafik Yaghmour from Stack Overflow.
//!
template <typename Iterator>
void printVector( Iterator first, Iterator last);

int main()
{
    string s;
    vector<string> v;

    cout<<"Please Enter:\n";
    while(cin>>s)
    {
        v.push_back(s);
        printVector(v.begin(),v.end());
    }
}

//!
//! @brief      a better approach
//!
//! @author     @Shafik Yaghmour from Stack Overflow.
//!
template <typename Iterator>
void printVector( Iterator first, Iterator last)
{
    if( first != last )
    {
        std::cout << *first << " " ;
        printVector( std::next( first ), last ) ;
    }
}

//!
//! @brief      my code...can handle fixed size vector, cann't handle vectors
//!             that change size during rumtime..
//!
//! @author     @Alan
//!
//! @badcode    Misc Comment: Stop using underscores to start your variable names.
//!             _v is a really bad name, just go with v. @ RichardPlunkett.
//!
template<class T>
void vector_print(const vector<T> &_v)
{
    static
           typename vector<T>::const_iterator it = _v.begin();
    cout << *it
            <<" ";

    ++it;

    if(it != _v.end())
    {
        vector_print(_v);
    }
}

<commit_msg>Delete ex6_33_generics_version.cpp<commit_after><|endoftext|>


<commit_before>#include "cmainwindow.h"
#include "ui_cmainwindow.h"
#include "compiler/compiler_warnings_control.h"

#include "settings/csettings.h"
#include "uisettings.h"

DISABLE_COMPILER_WARNINGS
#include <QFileDialog>
#include <QFileInfo>
#include <QFontDialog>
#include <QPropertyAnimation>
#include <QSlider>
#include <QSpinBox>
#include <QStandardPaths>
#include <QStringBuilder>
#include <QToolBar>
RESTORE_COMPILER_WARNINGS

CMainWindow::CMainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::CMainWindow),
	_reader(this)
{
	ui->setupUi(this);

	// Reading animation
	_textFadeEffect.setOpacity(1.0f);
	_textFadeOutAnimation = new QPropertyAnimation(&_textFadeEffect, "opacity", this);
	_textFadeOutAnimation->setStartValue(1.0f);
	_textFadeOutAnimation->setEndValue(0.0f);

	ui->_text->setGraphicsEffect(&_textFadeEffect);
	updateReadingAnimationDuration();

// Toolbars
	initToolBars();

// Actions
	initActions();
}

CMainWindow::~CMainWindow()
{
	_reader.resetAndStop();
	_textFadeOutAnimation->stop();

	delete ui;
	ui = nullptr;
}

void CMainWindow::initToolBars()
{
// Reading settings toolbar
	// Font size
	_textSizeSlider = new QSlider(Qt::Horizontal);
	_textSizeSlider->setMinimum(20);
	_textSizeSlider->setMaximum(300);
	_textSizeSlider->setValue(CSettings().value(UI_FONT_SIZE_SETTING, UI_FONT_SIZE_DEFAULT).toInt());

	connect(_textSizeSlider, &QSlider::valueChanged, [this](int size){
		QFont font = ui->_text->font();
		font.setPointSize(size);
		ui->_text->setFont(font);

		CSettings().setValue(UI_FONT_SIZE_SETTING, size);
	});
	_textSizeSlider->valueChanged(_textSizeSlider->value());

	_readingSettingsToolbar = addToolBar(tr("Reading settings"));
	_readingSettingsToolbar->addWidget(new QLabel(tr("Text size") + "  "));
	_readingSettingsToolbar->addWidget(_textSizeSlider);

	// Reading speed
	_readingSettingsToolbar->addSeparator();
	_readingSettingsToolbar->addWidget(new QLabel(tr("Reading speed") + "  "));

	_readingSpeedSlider = new QSlider(Qt::Horizontal);
	_readingSpeedSpinBox = new QSpinBox();

	_readingSpeedSlider->setMinimum(100);
	_readingSpeedSpinBox->setMinimum(100);
	_readingSpeedSlider->setMaximum(800);
	_readingSpeedSpinBox->setMaximum(800);

	_readingSpeedSlider->setTickInterval(50);
	_readingSpeedSlider->setTickPosition(QSlider::TicksBothSides);

	_readingSpeedSpinBox->setSuffix(" WPM");
	_readingSpeedSpinBox->setAccelerated(true);

	connect(_readingSpeedSlider, &QSlider::valueChanged, _readingSpeedSpinBox, &QSpinBox::setValue);
	connect(_readingSpeedSpinBox, (void (QSpinBox::*)(int))&QSpinBox::valueChanged, _readingSpeedSlider, &QSlider::setValue);

	connect(_readingSpeedSlider, &QSlider::valueChanged, [this](int WPM){
		_reader.setReadingSpeed(WPM);
		updateReadingAnimationDuration();
	});

	_readingSpeedSlider->setValue(_reader.readingSpeed());

	_readingSettingsToolbar->addWidget(_readingSpeedSlider);
	_readingSettingsToolbar->addWidget(_readingSpeedSpinBox);
}

void CMainWindow::initActions()
{
	connect(ui->action_Font, &QAction::triggered, [this](){
		QFontDialog fontDialog(ui->_text->font(), this);
		connect(&fontDialog, &QFontDialog::fontSelected, [this](const QFont &font){
			ui->_text->setFont(font);
			_textSizeSlider->setValue(font.pointSize());
		});
		fontDialog.exec();
	});

	ui->actionOpen->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon));
	connect(ui->actionOpen, &QAction::triggered, [this](){
		const QString filePath = QFileDialog::getOpenFileName(this,
			tr("Pick a text file to open"),
			CSettings().value(UI_OPEN_FILE_LAST_USED_DIR_SETTING, QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).front()).toString());

		if (!filePath.isEmpty())
		{
			CSettings().setValue(UI_OPEN_FILE_LAST_USED_DIR_SETTING, filePath);
			setWindowTitle(qApp->applicationName() % " - " % QFileInfo(filePath).baseName());
			_reader.loadFromFile(filePath);
		}
	});

	ui->action_Read->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaPlay));
	connect(ui->action_Read, &QAction::triggered, [this](){
		if (_reader.state() == CReader::Paused)
			_reader.resumeReading();
		else
			_reader.pauseReading();
	});

	ui->action_Pause->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaPause));
	connect(ui->action_Pause, &QAction::triggered, [this](){
		_reader.pauseReading();
	});

	ui->actionStop->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSkipBackward));
	connect(ui->actionStop, &QAction::triggered, [this](){
		_reader.resetAndStop();
		ui->_text->clear();
	});

	connect(ui->action_Exit, &QAction::triggered, qApp, &QApplication::exit);
}

void CMainWindow::updateDisplay(const size_t currentTextFragmentIndex)
{
	QMetaObject::Connection* connection = new QMetaObject::Connection();
	const QString text = _reader.textFragment(currentTextFragmentIndex)._textFragment._text;
	*connection = connect(_textFadeOutAnimation, &QPropertyAnimation::finished, [this, text, connection]() {
		disconnect(*connection);
		delete connection;

		_textFadeEffect.setOpacity(1.0f);
		ui->_text->setText(text);
	});

	_textFadeOutAnimation->start();

}

void CMainWindow::stateChanged(const CReader::State newState)
{
	if (newState == CReader::Reading)
	{
		ui->action_Pause->setEnabled(true);
	}
	else if (newState == CReader::Paused)
	{
		ui->action_Pause->setEnabled(false);
	}
}

void CMainWindow::updateReadingAnimationDuration()
{
	const auto animationDurationMs = 60 * 1000 / _reader.readingSpeed() / 2;

	_textFadeOutAnimation->setEasingCurve(animationDurationMs > 90 ? QEasingCurve::Linear : QEasingCurve::InQuad);
	_textFadeOutAnimation->setDuration(std::min(animationDurationMs, 150U));
}
<commit_msg>Only using animation when the current and the new text fragments match<commit_after>#include "cmainwindow.h"
#include "ui_cmainwindow.h"
#include "compiler/compiler_warnings_control.h"

#include "settings/csettings.h"
#include "uisettings.h"

DISABLE_COMPILER_WARNINGS
#include <QFileDialog>
#include <QFileInfo>
#include <QFontDialog>
#include <QPropertyAnimation>
#include <QSlider>
#include <QSpinBox>
#include <QStandardPaths>
#include <QStringBuilder>
#include <QToolBar>
RESTORE_COMPILER_WARNINGS

CMainWindow::CMainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::CMainWindow),
	_reader(this)
{
	ui->setupUi(this);

	// Reading animation
	_textFadeEffect.setOpacity(1.0f);
	_textFadeOutAnimation = new QPropertyAnimation(&_textFadeEffect, "opacity", this);
	_textFadeOutAnimation->setStartValue(1.0f);
	_textFadeOutAnimation->setEndValue(0.0f);
	_textFadeOutAnimation->setEasingCurve(QEasingCurve::OutCubic);

	ui->_text->setGraphicsEffect(&_textFadeEffect);
	updateReadingAnimationDuration();

// Toolbars
	initToolBars();

// Actions
	initActions();
}

CMainWindow::~CMainWindow()
{
	_reader.resetAndStop();
	_textFadeOutAnimation->stop();

	delete ui;
	ui = nullptr;
}

void CMainWindow::initToolBars()
{
// Reading settings toolbar
	// Font size
	_textSizeSlider = new QSlider(Qt::Horizontal);
	_textSizeSlider->setMinimum(20);
	_textSizeSlider->setMaximum(300);
	_textSizeSlider->setValue(CSettings().value(UI_FONT_SIZE_SETTING, UI_FONT_SIZE_DEFAULT).toInt());

	connect(_textSizeSlider, &QSlider::valueChanged, [this](int size){
		QFont font = ui->_text->font();
		font.setPointSize(size);
		ui->_text->setFont(font);

		CSettings().setValue(UI_FONT_SIZE_SETTING, size);
	});
	_textSizeSlider->valueChanged(_textSizeSlider->value());

	_readingSettingsToolbar = addToolBar(tr("Reading settings"));
	_readingSettingsToolbar->addWidget(new QLabel(tr("Text size") + "  "));
	_readingSettingsToolbar->addWidget(_textSizeSlider);

	// Reading speed
	_readingSettingsToolbar->addSeparator();
	_readingSettingsToolbar->addWidget(new QLabel(tr("Reading speed") + "  "));

	_readingSpeedSlider = new QSlider(Qt::Horizontal);
	_readingSpeedSpinBox = new QSpinBox();

	_readingSpeedSlider->setMinimum(100);
	_readingSpeedSpinBox->setMinimum(100);
	_readingSpeedSlider->setMaximum(800);
	_readingSpeedSpinBox->setMaximum(800);

	_readingSpeedSlider->setTickInterval(50);
	_readingSpeedSlider->setTickPosition(QSlider::TicksBothSides);

	_readingSpeedSpinBox->setSuffix(" WPM");
	_readingSpeedSpinBox->setAccelerated(true);

	connect(_readingSpeedSlider, &QSlider::valueChanged, _readingSpeedSpinBox, &QSpinBox::setValue);
	connect(_readingSpeedSpinBox, (void (QSpinBox::*)(int))&QSpinBox::valueChanged, _readingSpeedSlider, &QSlider::setValue);

	connect(_readingSpeedSlider, &QSlider::valueChanged, [this](int WPM){
		_reader.setReadingSpeed(WPM);
		updateReadingAnimationDuration();
	});

	_readingSpeedSlider->setValue(_reader.readingSpeed());

	_readingSettingsToolbar->addWidget(_readingSpeedSlider);
	_readingSettingsToolbar->addWidget(_readingSpeedSpinBox);
}

void CMainWindow::initActions()
{
	connect(ui->action_Font, &QAction::triggered, [this](){
		QFontDialog fontDialog(ui->_text->font(), this);
		connect(&fontDialog, &QFontDialog::fontSelected, [this](const QFont &font){
			ui->_text->setFont(font);
			_textSizeSlider->setValue(font.pointSize());
		});
		fontDialog.exec();
	});

	ui->actionOpen->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirOpenIcon));
	connect(ui->actionOpen, &QAction::triggered, [this](){
		const QString filePath = QFileDialog::getOpenFileName(this,
			tr("Pick a text file to open"),
			CSettings().value(UI_OPEN_FILE_LAST_USED_DIR_SETTING, QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).front()).toString());

		if (!filePath.isEmpty())
		{
			CSettings().setValue(UI_OPEN_FILE_LAST_USED_DIR_SETTING, filePath);
			setWindowTitle(qApp->applicationName() % " - " % QFileInfo(filePath).baseName());
			ui->_text->clear();
			_reader.loadFromFile(filePath);
		}
	});

	ui->action_Read->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaPlay));
	connect(ui->action_Read, &QAction::triggered, [this](){
		if (_reader.state() == CReader::Paused)
			_reader.resumeReading();
		else
			_reader.pauseReading();
	});

	ui->action_Pause->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaPause));
	connect(ui->action_Pause, &QAction::triggered, [this](){
		_reader.pauseReading();
	});

	ui->actionStop->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaSkipBackward));
	connect(ui->actionStop, &QAction::triggered, [this](){
		_reader.resetAndStop();
		ui->_text->clear();
	});

	connect(ui->action_Exit, &QAction::triggered, qApp, &QApplication::exit);
}

void CMainWindow::updateDisplay(const size_t currentTextFragmentIndex)
{
	const QString text = _reader.textFragment(currentTextFragmentIndex)._textFragment._text;

	// If the new text fragment equals the previous one, use animation to make it obvious
	if (ui->_text->text() != text)
		ui->_text->setText(text);
	else
	{
		QMetaObject::Connection* connection = new QMetaObject::Connection();
		*connection = connect(_textFadeOutAnimation, &QPropertyAnimation::finished, [this, text, connection]() {
			disconnect(*connection);
			delete connection;

			_textFadeEffect.setOpacity(1.0f);
			ui->_text->setText(text);
		});

		_textFadeOutAnimation->start();
	}
}

void CMainWindow::stateChanged(const CReader::State newState)
{
	if (newState == CReader::Reading)
	{
		ui->action_Pause->setEnabled(true);
	}
	else if (newState == CReader::Paused)
	{
		ui->action_Pause->setEnabled(false);
	}
}

void CMainWindow::updateReadingAnimationDuration()
{
	const auto animationDurationMs = 60 * 1000 * 2 / _reader.readingSpeed() / 3;
	_textFadeOutAnimation->setDuration(std::min(animationDurationMs, 150U));
}
<|endoftext|>


<commit_before>#include <fc/network/udp_socket.hpp>
#include <fc/network/ip.hpp>
#include <fc/fwd_impl.hpp>

namespace fc
{
  class udp_socket::impl : public fc::retainable
  {
    public:
      impl(){}
      ~impl(){}

      std::shared_ptr<boost::asio::ip::udp::socket> _sock;
  };

  udp_socket::udp_socket()
    : my(new impl())
  {
  }

  void udp_socket::initialize(boost::asio::io_service& service)
  {
    my->_sock.reset(new boost::asio::ip::udp::socket(service));
  }

  udp_socket::~udp_socket()
  {
    try
    {
      if(my->_sock)
        my->_sock->close(); //close boost socket to make any pending reads run their completion handler
    }
    catch (...) //avoid destructor throw and likely this is just happening because socket wasn't open.
    {
    }
  }

  void udp_socket::send_to(const char* buffer, size_t length, boost::asio::ip::udp::endpoint& to)
  {
    try
    {
      my->_sock->send_to(boost::asio::buffer(buffer, length), to);
    }
    catch(const boost::system::system_error& e)
    {
      if(e.code() != boost::asio::error::would_block)
        throw;
    }

    my->_sock->async_send_to(boost::asio::buffer(buffer, length), to,
                             [this](const boost::system::error_code& /*ec*/, std::size_t /*bytes_transferred*/)
    {
      // Swallow errors.  Currently only used for GELF logging, so depend on local
      // log to catch anything that doesn't make it across the network.
    });
  }

  void udp_socket::send_to(const std::shared_ptr<const char>& buffer, size_t length,
                           boost::asio::ip::udp::endpoint& to)
  {
    try
    {
      my->_sock->send_to(boost::asio::buffer(buffer.get(), length), to);
    }
    catch(const boost::system::system_error& e)
    {
      if(e.code() != boost::asio::error::would_block)
        throw;
    }

    my->_sock->async_send_to(boost::asio::buffer(buffer.get(), length), to,
                             [this](const boost::system::error_code& /*ec*/, std::size_t /*bytes_transferred*/)
    {
      // Swallow errors.  Currently only used for GELF logging, so depend on local
      // log to catch anything that doesn't make it across the network.
    });
  }

  void udp_socket::open()
  {
    my->_sock->open(boost::asio::ip::udp::v4());
    my->_sock->non_blocking(true);
  }

  void udp_socket::close()
  {
    my->_sock->close();
  }

  const boost::asio::ip::udp::endpoint udp_socket::local_endpoint() const
  {
    return my->_sock->local_endpoint();
  }

  void udp_socket::connect(const boost::asio::ip::udp::endpoint& e)
  {
    my->_sock->connect(e);
  }

  void udp_socket::set_reuse_address( bool s )
  {
    my->_sock->set_option( boost::asio::ip::udp::socket::reuse_address(s) );
  }

}
<commit_msg>Address review comments, add copyright, remove extraneous header.<commit_after>/**
 *  @file
 *  @copyright defined in eos/LICENSE.txt
 */
#include <fc/network/udp_socket.hpp>
#include <fc/network/ip.hpp>

namespace fc
{
  class udp_socket::impl : public fc::retainable
  {
    public:
      impl(){}
      ~impl(){}

      std::shared_ptr<boost::asio::ip::udp::socket> _sock;
  };

  udp_socket::udp_socket()
    : my(new impl())
  {
  }

  void udp_socket::initialize(boost::asio::io_service& service)
  {
    my->_sock.reset(new boost::asio::ip::udp::socket(service));
  }

  udp_socket::~udp_socket()
  {
    try
    {
      if(my->_sock)
        my->_sock->close(); //close boost socket to make any pending reads run their completion handler
    }
    catch (...) //avoid destructor throw and likely this is just happening because socket wasn't open.
    {
    }
  }

  void udp_socket::send_to(const char* buffer, size_t length, boost::asio::ip::udp::endpoint& to)
  {
    try
    {
      my->_sock->send_to(boost::asio::buffer(buffer, length), to);
    }
    catch(const boost::system::system_error& e)
    {
      if(e.code() != boost::asio::error::would_block)
        throw;
    }

    auto send_buffer_ptr = std::make_shared<std::vector<char>>(buffer, buffer+length);
    my->_sock->async_send_to(boost::asio::buffer(send_buffer_ptr.get(), length), to,
                             [send_buffer_ptr](const boost::system::error_code& /*ec*/, std::size_t /*bytes_transferred*/)
    {
      // Swallow errors.  Currently only used for GELF logging, so depend on local
      // log to catch anything that doesn't make it across the network.
    });
  }

  void udp_socket::send_to(const std::shared_ptr<const char>& buffer, size_t length,
                           boost::asio::ip::udp::endpoint& to)
  {
    try
    {
      my->_sock->send_to(boost::asio::buffer(buffer.get(), length), to);
    }
    catch(const boost::system::system_error& e)
    {
      if(e.code() != boost::asio::error::would_block)
        throw;
    }

    auto preserved_buffer_ptr = buffer;
    my->_sock->async_send_to(boost::asio::buffer(preserved_buffer_ptr.get(), length), to,
                             [preserved_buffer_ptr](const boost::system::error_code& /*ec*/, std::size_t /*bytes_transferred*/)
    {
      // Swallow errors.  Currently only used for GELF logging, so depend on local
      // log to catch anything that doesn't make it across the network.
    });
  }

  void udp_socket::open()
  {
    my->_sock->open(boost::asio::ip::udp::v4());
    my->_sock->non_blocking(true);
  }

  void udp_socket::close()
  {
    my->_sock->close();
  }

  const boost::asio::ip::udp::endpoint udp_socket::local_endpoint() const
  {
    return my->_sock->local_endpoint();
  }

  void udp_socket::connect(const boost::asio::ip::udp::endpoint& e)
  {
    my->_sock->connect(e);
  }

  void udp_socket::set_reuse_address( bool s )
  {
    my->_sock->set_option( boost::asio::ip::udp::socket::reuse_address(s) );
  }

}
<|endoftext|>


<commit_before>#include <zlib.h>
#include <inttypes.h>
#include <memory>

#include "htslib/kseq.h"
#include "htslib/kstring.h"
#include "dlib/logging_util.h"
KSEQ_INIT(gzFile, gzread)

int usage(char **argv, int rc) {
    fprintf(stderr, "Usage: %s -l<blen> infq1 infq2 outfq1 outfq2 outfq3\n For converting non-duplex inline barcodes for compatibility with collapse secondary\n"
                    "-2: Get single-sided barcode from read2.\n", *argv);
    return rc;
}

void fqw(kseq_t *ks, int offset, FILE *fp) {
    fprintf(fp, "@%s %s\n%s\n+\n%s\n", ks->name.s,
            ks->comment.s, ks->seq.s + offset, ks->qual.s + offset);
}

void bcw(kseq_t *ks, char *s, char *q, FILE *fp) {
    fprintf(fp, "@%s %s\n%s\n+\n%s\n", ks->name.s,
            ks->comment.s, s, q);
}

int main(int argc, char **argv)
{
    if(argc < 6) return usage(argv, EXIT_FAILURE);
    int blen(-1), use_read1(1);
    int c;
    while((c = getopt(argc, argv, "l:2h?")) > 0) {
        switch(c) {
        case '2': use_read1 = 0;
        case 'l': blen  = atoi(optarg); break;
        case 'h': case '?': return usage(argv, EXIT_SUCCESS);
        }
    }
    if(blen < 0) {
        fprintf(stderr, "blen required. Abort!\n");
        return usage(argv, EXIT_FAILURE);
    }
    gzFile in1(gzopen(argv[optind], "rb")), in2(gzopen(argv[optind + 1], "rb"));
    kseq_t *ks1(kseq_init(in1)), *ks2(kseq_init(in2));
    FILE *out1(fopen(argv[optind + 2], "w")), *out2(fopen(argv[optind + 3], "w")), *outindex(fopen(argv[optind + 4], "w"));
    char bpos[128];
    bpos[blen] = '\0';
    kseq_t *bks(use_read1 ? ks1: ks2);
    while(kseq_read(ks1) >= 0 && kseq_read(ks2) >= 0) {
        memcpy(bpos, bks->seq.s, blen);
        fprintf(outindex, "@%s barcode\n%s\n+\n", ks1->name.s, bpos);
        fwrite(bks->qual.s, 20, 1, outindex);
        fputc('\n', outindex);
        memset(bks->seq.s, 'N', blen);
        memset(bks->qual.s, '#', blen);
        fqw(ks1, 0, out1);
        fqw(ks1, 0, out2);
    }
    kseq_destroy(ks1); kseq_destroy(ks2);
    gzclose(in1); gzclose(in2);
    fclose(out1); fclose(out2); fclose(outindex);
    return 0;
}
<commit_msg>Fix error in ssi2sec<commit_after>#include <zlib.h>
#include <inttypes.h>
#include <memory>

#include "htslib/kseq.h"
#include "htslib/kstring.h"
#include "dlib/logging_util.h"
KSEQ_INIT(gzFile, gzread)

int usage(char **argv, int rc) {
    fprintf(stderr, "Purpose: Convert single-sided inline to secondary index format.
                     Usage: %s -l<blen> infq1 infq2 outfq1 outfq2 outfq3\n For converting non-duplex inline barcodes for compatibility with collapse secondary\n"
                    "-2: Get single-sided barcode from read2.\n", *argv);
    return rc;
}

void fqw(kseq_t *ks, int offset, FILE *fp) {
    fprintf(fp, "@%s %s\n%s\n+\n%s\n", ks->name.s,
            ks->comment.s, ks->seq.s + offset, ks->qual.s + offset);
}

void bcw(kseq_t *ks, char *s, char *q, FILE *fp) {
    fprintf(fp, "@%s %s\n%s\n+\n%s\n", ks->name.s,
            ks->comment.s, s, q);
}

int main(int argc, char **argv)
{
    if(argc < 6) return usage(argv, EXIT_FAILURE);
    int blen(-1), use_read1(1);
    int c;
    while((c = getopt(argc, argv, "l:2h?")) > 0) {
        switch(c) {
        case '2': use_read1 = 0;
        case 'l': blen  = atoi(optarg); break;
        case 'h': case '?': return usage(argv, EXIT_SUCCESS);
        }
    }
    if(blen < 0) {
        fprintf(stderr, "blen required. Abort!\n");
        return usage(argv, EXIT_FAILURE);
    }
    gzFile in1(gzopen(argv[optind], "rb")), in2(gzopen(argv[optind + 1], "rb"));
    kseq_t *ks1(kseq_init(in1)), *ks2(kseq_init(in2));
    FILE *out1(fopen(argv[optind + 2], "w")), *out2(fopen(argv[optind + 3], "w")), *outindex(fopen(argv[optind + 4], "w"));
    char bpos[128];
    bpos[blen] = '\0';
    kseq_t *bks(use_read1 ? ks1: ks2);
    while(kseq_read(ks1) >= 0 && kseq_read(ks2) >= 0) {
        memcpy(bpos, bks->seq.s, blen);
        fprintf(outindex, "@%s barcode\n%s\n+\n", ks1->name.s, bpos);
        fwrite(bks->qual.s, 20, 1, outindex);
        fputc('\n', outindex);
        memset(bks->seq.s, 'N', blen);
        memset(bks->qual.s, '#', blen);
        fqw(ks1, 0, out1);
        fqw(ks2, 0, out2);
    }
    kseq_destroy(ks1); kseq_destroy(ks2);
    gzclose(in1); gzclose(in2);
    fclose(out1); fclose(out2); fclose(outindex);
    return 0;
}
<|endoftext|>


<commit_before>#include "textdraw.hpp"
#include "../glx.hpp"
#include "../sys_uniform_value.hpp"
#include "../gameloophelper.hpp"

namespace rs {
	namespace util {
		// ---------------------- TextHUD ----------------------
		const IdValue TextHUD::U_Text = GLEffect::GlxId::GenUnifId("mText");
		TextHUD::TextHUD(IdValue idTech):
			Text(idTech),
			_coordType(Coord::Window),
			_offset(0),
			_scale(1),
			_depth(1)
		{}
		spn::Mat33 TextHUD::_makeMatrix() const {
			float rx, ry,
				  ox, oy,
				  diry;
			auto lkb = sharedbase.lock();
			auto s = lkb->screenSize;
			rx = spn::Rcp22Bit(s.width/2);
			ry = spn::Rcp22Bit(s.height/2);
			if(_coordType == Coord::Window) {
				ox = -1.f;
				oy = 1.f;
				diry = -1.f;
			} else {
				ox = oy = 0.f;
				diry = 1.f;
			}
			auto& ofs = _offset;
			return spn::Mat33(rx*_scale.x,		0,						0,
							0,					ry*_scale.y,			0,
							ox + ofs.x*rx,		oy + ofs.y*ry*diry,		1);
		}
		void TextHUD::setWindowOffset(const spn::Vec2& ofs) {
			_coordType = Coord::Window;
			_offset = ofs;
		}
		void TextHUD::setScreenOffset(const spn::Vec2& ofs) {
			_coordType = Coord::Screen;
			_offset = ofs;
		}
		void TextHUD::setScale(const spn::Vec2& s) {
			_scale = s;
		}
		void TextHUD::setDepth(float d) {
			_depth = d;
		}
		void TextHUD::draw(GLEffect& e) const {
			// Zが0.0未満や1.0以上だと描画されないので、それより少し狭い範囲でクリップする
			float d = spn::Saturate(_depth, 0.f, 1.f-1e-4f);
			Text::draw(e, [d, this](auto& e){
				e.setUniform(unif2d::Depth, d);
				e.setUniform(U_Text, _makeMatrix(), true);
			});
		}
	}
}
<commit_msg>TextHUD: スケーリングの修正<commit_after>#include "textdraw.hpp"
#include "../glx.hpp"
#include "../sys_uniform_value.hpp"
#include "../gameloophelper.hpp"

namespace rs {
	namespace util {
		// ---------------------- TextHUD ----------------------
		const IdValue TextHUD::U_Text = GLEffect::GlxId::GenUnifId("mText");
		TextHUD::TextHUD(IdValue idTech):
			Text(idTech),
			_coordType(Coord::Window),
			_offset(0),
			_scale(1),
			_depth(1)
		{}
		spn::Mat33 TextHUD::_makeMatrix() const {
			float rx, ry,
				  ox, oy,
				  diry;
			auto lkb = sharedbase.lock();
			auto s = lkb->screenSize;
			rx = spn::Rcp22Bit(s.width/2);
			ry = spn::Rcp22Bit(s.height/2);
			auto ofs = _offset;
			if(_coordType == Coord::Window) {
				ox = -1.f;
				oy = 1.f;
				diry = -1.f;
				ofs.x *= rx;
				ofs.y *= ry;
			} else {
				ox = oy = 0.f;
				diry = 1.f;
			}
			return spn::Mat33(rx*_scale.x,		0,						0,
							0,					ry*_scale.y,			0,
							ox + ofs.x,			oy + ofs.y*diry,		1);
		}
		void TextHUD::setWindowOffset(const spn::Vec2& ofs) {
			_coordType = Coord::Window;
			_offset = ofs;
		}
		void TextHUD::setScreenOffset(const spn::Vec2& ofs) {
			_coordType = Coord::Screen;
			_offset = ofs;
		}
		void TextHUD::setScale(const spn::Vec2& s) {
			_scale = s;
		}
		void TextHUD::setDepth(float d) {
			_depth = d;
		}
		void TextHUD::draw(GLEffect& e) const {
			// Zが0.0未満や1.0以上だと描画されないので、それより少し狭い範囲でクリップする
			float d = spn::Saturate(_depth, 0.f, 1.f-1e-4f);
			Text::draw(e, [d, this](auto& e){
				e.setUniform(unif2d::Depth, d);
				e.setUniform(U_Text, _makeMatrix(), true);
			});
		}
	}
}
<|endoftext|>


<commit_before>#pragma once
#include<string>
#include<cstdint>
#include<fstream>
#include<array>
#include<vector>
#include<algorithm>
namespace bmslib {

	std::vector<std::string> split_naive(const std::string &s, char delim) {
		std::vector<std::string> elems;
		std::string item;
		for (char ch : s) {
			if (ch == delim) {
				if (!item.empty())
					elems.push_back(item);
				item.clear();
			}
			else {
				item += ch;
			}
		}
		if (!item.empty())
			elems.push_back(item);
		return elems;
	}

	std::string trim(const std::string& string, const char* trimCharacterList = " \t\v\r")
	{
		std::string result;

		// g镶ȊOʒu܂B
		std::string::size_type left = string.find_first_not_of(trimCharacterList);

		if (left != std::string::npos)
		{
			// g镶ȊOꍇ́A悤ɉE܂B
			std::string::size_type right = string.find_last_not_of(trimCharacterList);

			// ߂l肵܂Bł͉E猟ĂAg镶ȊOK݂̂ŔsvłB
			result = string.substr(left, right - left + 1);
		}

		return result;
	}

	enum Player {
		None,
		Single,
		Couple,
		Double,
		Battle
	};

	enum Rank {
		Veryhard,
		Hard,
		Normal,
		Easy
	};

	struct Header
	{
		Player player;
		std::string genre, title, artist, stagefile;
		double bpm;
		unsigned int level, volume, total;
		Rank rank;
		std::array<std::string, 575> wav, bmp;
	};

	enum Channel {
		None1,
		Backwav,
		Shortening,
		Changebpm,
		Bga,
		None2,
		Pooranim,
		Bgalayer,
		exBPM,
		Stop,
		None3,
		Key1,
		Key2,
		Key3,
		Key4,
		Key5,
		Key6,
		Key7,
		Key8,
		Key9,
		None4,
		Key1_2P,
		Key2_2P,
		Key3_2P,
		Key4_2P,
		Key5_2P,
		Key6_2P,
		Key7_2P,
		Key8_2P,
		Key9_2P,
	};

	struct Bar {
		Channel channel;
		int backchorus; // Set WAV number
		int length = 1000; // Default Value = 1000
		std::vector<double> bpms;
		int bga, pooranim, layerbga;
		std::array<std::vector<bool>, 9> objects;
	};

	struct Object {
		int data;
		long time;
		Channel channel;

		bool operator<(const Object obj) {
			return time < obj.time;
		}
	};

	struct Bms {
		Header header;
		std::vector<Object> bar;
	};

	Bms load_data(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;
		while (getline(file, line))
		{
			trim(line);
			if (line[0] == '#') {
				if (isdigit(line[1])) {
					auto str = split_naive(line,':');

					auto command = str[0];
					auto data = str[1];

					if (bms.bar.size() < std::stoi(command.substr(1, 3)) + 1){
						bms.bar.reserve(std::stoi(command.substr(1, 3)) + 1);
					}
					auto channel = static_cast<Channel>(std::stoi(command.substr(4, 2)));
					int num_bar = std::stoi(command.substr(0, 3));
					int num_note = data.size() / 2;
					for (int i = 0; i < num_note - 1; i++) {
						Object obj;
						obj.time = 9600 * num_bar + i*(9600 / num_note);
						obj.data = std::stoi(data.substr(i, 2));
						obj.channel = channel;
						bms.bar.push_back(obj);
					}
				}
			}
		}
		std::sort(bms.bar.begin(), bms.bar.end());
	}

	Bms loadheader(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;

		while (getline(file, line))
		{

			if (line[0] == '#') {

				if (!isdigit(line[1])) {

					auto strs = split_naive(line, ' ');
					std::string command = strs[0].substr(1);
					std::string arg1;
					if (strs.size() == 1) {
						arg1 = "";
					}
					else {
						arg1 = strs[1];
					}

					if (!std::strcmp(command.c_str(), "PLAYER")) {

						bms.header.player = static_cast<Player>(std::stoi(arg1.c_str()));
					}
					if (!std::strcmp(command.c_str(), "GENRE")) {
						bms.header.genre = arg1;
					}
					if (!std::strcmp(command.c_str(), "TITLE")) {
						std::string rs;
						for (int i = 1; i < strs.size() - 1; i++) {
							rs += strs[i];
							rs += " ";
						}
						bms.header.title = rs;
					}
					if (!std::strcmp(command.c_str(), "ARTIST")) {
						bms.header.artist = arg1;
					}
					if (!std::strcmp(command.c_str(), "BPM")) {
						bms.header.bpm = std::stof(arg1);
					}
					if (!std::strcmp(command.c_str(), "PLAYLEVEL")) {
						bms.header.level = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "RANK")) {
						bms.header.rank = static_cast<Rank>(std::stoi(arg1));
					}
					if (!std::strcmp(command.c_str(), "VOLWAV")) {
						bms.header.volume = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "TOTAL")) {
						bms.header.total = std::stoi(arg1);
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "WAV")) {
						bms.header.wav[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "BMP")) {
						bms.header.bmp[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.c_str(), "StageFile")) {
						bms.header.stagefile = arg1;
					}
				}
			}
		}
		return bms;
	}

	void save(std::string filename, const Bms& bms) {

	}
}<commit_msg>STAGEFILEヘッダ読み込みが行われないばぐのしゅうせい<commit_after>#pragma once
#include<string>
#include<cstdint>
#include<fstream>
#include<array>
#include<vector>
#include<algorithm>
namespace bmslib {

	std::vector<std::string> split_naive(const std::string &s, char delim) {
		std::vector<std::string> elems;
		std::string item;
		for (char ch : s) {
			if (ch == delim) {
				if (!item.empty())
					elems.push_back(item);
				item.clear();
			}
			else {
				item += ch;
			}
		}
		if (!item.empty())
			elems.push_back(item);
		return elems;
	}

	std::string trim(const std::string& string, const char* trimCharacterList = " \t\v\r")
	{
		std::string result;

		// g镶ȊOʒu܂B
		std::string::size_type left = string.find_first_not_of(trimCharacterList);

		if (left != std::string::npos)
		{
			// g镶ȊOꍇ́A悤ɉE܂B
			std::string::size_type right = string.find_last_not_of(trimCharacterList);

			// ߂l肵܂Bł͉E猟ĂAg镶ȊOK݂̂ŔsvłB
			result = string.substr(left, right - left + 1);
		}

		return result;
	}

	enum Player {
		None,
		Single,
		Couple,
		Double,
		Battle
	};

	enum Rank {
		Veryhard,
		Hard,
		Normal,
		Easy
	};

	struct Header
	{
		Player player;
		std::string genre, title, artist, stagefile;
		double bpm;
		unsigned int level, volume, total;
		Rank rank;
		std::array<std::string, 575> wav, bmp;
	};

	enum Channel {
		None1,
		Backwav,
		Shortening,
		Changebpm,
		Bga,
		None2,
		Pooranim,
		Bgalayer,
		exBPM,
		Stop,
		None3,
		Key1,
		Key2,
		Key3,
		Key4,
		Key5,
		Key6,
		Key7,
		Key8,
		Key9,
		None4,
		Key1_2P,
		Key2_2P,
		Key3_2P,
		Key4_2P,
		Key5_2P,
		Key6_2P,
		Key7_2P,
		Key8_2P,
		Key9_2P,
	};

	struct Bar {
		Channel channel;
		int backchorus; // Set WAV number
		int length = 1000; // Default Value = 1000
		std::vector<double> bpms;
		int bga, pooranim, layerbga;
		std::array<std::vector<bool>, 9> objects;
	};

	struct Object {
		int data;
		long time;
		Channel channel;

		bool operator<(const Object obj) {
			return time < obj.time;
		}
	};

	struct Bms {
		Header header;
		std::vector<Object> bar;
	};

	Bms load_data(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;
		while (getline(file, line))
		{
			trim(line);
			if (line[0] == '#') {
				if (isdigit(line[1])) {
					auto str = split_naive(line,':');

					auto command = str[0];
					auto data = str[1];

					if (bms.bar.size() < std::stoi(command.substr(1, 3)) + 1){
						bms.bar.reserve(std::stoi(command.substr(1, 3)) + 1);
					}
					auto channel = static_cast<Channel>(std::stoi(command.substr(4, 2)));
					int num_bar = std::stoi(command.substr(0, 3));
					int num_note = data.size() / 2;
					for (int i = 0; i < num_note - 1; i++) {
						Object obj;
						obj.time = 9600 * num_bar + i*(9600 / num_note);
						obj.data = std::stoi(data.substr(i, 2));
						obj.channel = channel;
						bms.bar.push_back(obj);
					}
				}
			}
		}
		std::sort(bms.bar.begin(), bms.bar.end());
	}

	Bms loadheader(std::string bmsfile) {
		std::ifstream file(bmsfile);
		std::string line;
		if (file.fail())
		{
			return Bms();
		}
		Bms bms;

		while (getline(file, line))
		{

			if (line[0] == '#') {

				if (!isdigit(line[1])) {

					auto strs = split_naive(line, ' ');
					std::string command = strs[0].substr(1);
					std::string arg1;
					if (strs.size() == 1) {
						arg1 = "";
					}
					else {
						arg1 = strs[1];
					}

					if (!std::strcmp(command.c_str(), "PLAYER")) {

						bms.header.player = static_cast<Player>(std::stoi(arg1.c_str()));
					}
					if (!std::strcmp(command.c_str(), "GENRE")) {
						bms.header.genre = arg1;
					}
					if (!std::strcmp(command.c_str(), "TITLE")) {
						std::string rs;
						for (int i = 1; i < strs.size() - 1; i++) {
							rs += strs[i];
							rs += " ";
						}
						bms.header.title = rs;
					}
					if (!std::strcmp(command.c_str(), "ARTIST")) {
						bms.header.artist = arg1;
					}
					if (!std::strcmp(command.c_str(), "BPM")) {
						bms.header.bpm = std::stof(arg1);
					}
					if (!std::strcmp(command.c_str(), "PLAYLEVEL")) {
						bms.header.level = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "RANK")) {
						bms.header.rank = static_cast<Rank>(std::stoi(arg1));
					}
					if (!std::strcmp(command.c_str(), "VOLWAV")) {
						bms.header.volume = std::stoi(arg1);
					}
					if (!std::strcmp(command.c_str(), "TOTAL")) {
						bms.header.total = std::stoi(arg1);
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "WAV")) {
						bms.header.wav[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.substr(0, 3).c_str(), "BMP")) {
						bms.header.bmp[std::stoi(command.substr(3, 2), nullptr, 36)] = arg1;
					}
					if (!std::strcmp(command.c_str(), "StageFile") || !std::strcmp(command.c_str(), "STAGEFILE")) {
						bms.header.stagefile = arg1;
					}
				}
			}
		}
		return bms;
	}

	void save(std::string filename, const Bms& bms) {

	}
}<|endoftext|>


<commit_before>#include <winsock2.h>
#include <stdio.h>

#include "socket.h"

#ifdef WIN32
bool wsaStartupDone = false;
#endif

ClientSocket::ClientSocket()
{
    sockfd = -1;
}

void ClientSocket::connectTo(std::string host, int port)
{
    struct sockaddr_in serv_addr;
#ifdef WIN32
    if (!wsaStartupDone)
    {
        WSADATA wsaData = {0};
        WSAStartup(MAKEWORD(1, 1), &wsaData);
        wsaStartupDone = true;
    }
#endif

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr(host.c_str());
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("Connect to %s:%d failed\n", host.c_str(), port);
        close();
        return;
    }
}

ClientSocket::~ClientSocket()
{
    close();
}

void ClientSocket::sendNr(int nr)
{
    sendAll(&nr, sizeof(int));
}

void ClientSocket::sendAll(const void* data, int length)
{
    if (sockfd == -1)
        return;
    const char* ptr = (const char*)data;
    while(length > 0)
    {
        int n = send(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

int ClientSocket::recvNr()
{
    int ret = 0;
    recvAll(&ret, 4);
    return ret;
}

void ClientSocket::recvAll(void* data, int length)
{
    if (sockfd == -1)
        return;
    char* ptr = (char*)data;
    while(length > 0)
    {
        int n = recv(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

void ClientSocket::close()
{
    if (sockfd == -1)
        return;
#ifdef WIN32
    closesocket(sockfd);
#else
    close(sockfd);
#endif
    sockfd = -1;
}
<commit_msg>Add includes for linux/mac build of sockets.<commit_after>#include <stdio.h>

#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif

#include "socket.h"

#ifdef WIN32
bool wsaStartupDone = false;
#endif

ClientSocket::ClientSocket()
{
    sockfd = -1;

#ifdef WIN32
    if (!wsaStartupDone)
    {
        WSADATA wsaData = {0};
        //WSAStartup needs to be called on windows before sockets can be used. Request version 1.1, which is supported on windows 98 and higher.
        WSAStartup(MAKEWORD(1, 1), &wsaData);
        wsaStartupDone = true;
    }
#endif
}

void ClientSocket::connectTo(std::string host, int port)
{
    struct sockaddr_in serv_addr;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = inet_addr(host.c_str());
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("Connect to %s:%d failed\n", host.c_str(), port);
        close();
        return;
    }
}

ClientSocket::~ClientSocket()
{
    close();
}

void ClientSocket::sendNr(int nr)
{
    sendAll(&nr, sizeof(int));
}

void ClientSocket::sendAll(const void* data, int length)
{
    if (sockfd == -1)
        return;
    const char* ptr = (const char*)data;
    while(length > 0)
    {
        int n = send(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

int ClientSocket::recvNr()
{
    int ret = 0;
    recvAll(&ret, 4);
    return ret;
}

void ClientSocket::recvAll(void* data, int length)
{
    if (sockfd == -1)
        return;
    char* ptr = (char*)data;
    while(length > 0)
    {
        int n = recv(sockfd, ptr, length, 0);
        if (n <= 0)
        {
            close();
            return;
        }
        ptr += length;
        length -= n;
    }
}

void ClientSocket::close()
{
    if (sockfd == -1)
        return;
#ifdef WIN32
    closesocket(sockfd);
#else
    close(sockfd);
#endif
    sockfd = -1;
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: openni_viewer.cpp 5059 2012-03-14 02:12:17Z gedikli $
 *
 */

#include <boost/thread/thread.hpp>
#include <pcl/apps/timer.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/search/organized.h>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/image_viewer.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>

using namespace pcl;

#define SHOW_FPS 1

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class NILinemod
{
  public:
    typedef PointCloud<PointXYZRGBA> Cloud;
    typedef typename Cloud::ConstPtr CloudConstPtr;
    bool added;

    NILinemod (Grabber& grabber)
      : cloud_viewer_ ("PointCloud")
      , grabber_ (grabber)
      , image_viewer_ ("Image")
    {
      added = false;
    }

    /////////////////////////////////////////////////////////////////////////
//    void
//    image_callback (const boost::shared_ptr<openni_wrapper::Image>& image)
//    {
//      boost::mutex::scoped_lock lock (image_mutex_);
//      image_ = image;
//    }
//
//    boost::shared_ptr<openni_wrapper::Image>
//    getLatestImage ()
//    {
//      // Lock while we swap our image and reset it.
//      boost::mutex::scoped_lock lock (image_mutex_);
//      boost::shared_ptr<openni_wrapper::Image> temp_image;
//      temp_image.swap (image_);
//      return (temp_image);
//    }

    /////////////////////////////////////////////////////////////////////////
    void
    cloud_callback (const CloudConstPtr& cloud)
    {
      FPS_CALC ("cloud callback");
      boost::mutex::scoped_lock lock (cloud_mutex_);
      cloud_ = cloud;
      search_.setInputCloud (cloud);
    }

    CloudConstPtr
    getLatestCloud ()
    {
      // Lock while we swap our cloud and reset it.
      boost::mutex::scoped_lock lock (cloud_mutex_);
      CloudConstPtr temp_cloud;
      temp_cloud.swap (cloud_);
      return (temp_cloud);
    }

    /////////////////////////////////////////////////////////////////////////
    void
    keyboard_callback (const visualization::KeyboardEvent& event, void*)
    {
      //if (event.getKeyCode())
      //  cout << "the key \'" << event.getKeyCode() << "\' (" << event.getKeyCode() << ") was";
      //else
      //  cout << "the special key \'" << event.getKeySym() << "\' was";
      //if (event.keyDown())
      //  cout << " pressed" << endl;
      //else
      //  cout << " released" << endl;
    }

    void
    mouse_callback (const visualization::MouseEvent& mouse_event, void*)
    {
      if (mouse_event.getType() == visualization::MouseEvent::MouseButtonPress && mouse_event.getButton() == visualization::MouseEvent::LeftButton)
      {
        cout << "left button pressed @ " << mouse_event.getX () << " , " << mouse_event.getY () << endl;
      }
    }

    /////////////////////////////////////////////////////////////////////////
    void
    segment ()
    {
    }

    /////////////////////////////////////////////////////////////////////////
    void
    pp_callback (const pcl::visualization::PointPickingEvent& event, void*)
    {
      int idx = event.getPointIndex ();
      if (idx == -1)
        return;

      std::vector<int> indices (1);
      std::vector<float> distances (1);

      {
        // Use mutices to make sure we get the right cloud
        boost::mutex::scoped_lock lock1 (cloud_mutex_);
        //boost::mutex::scoped_lock lock2 (image_mutex_);

        pcl::PointXYZRGBA pos;
        event.getPoint (pos.x, pos.y, pos.z);

        std::stringstream ss;
        ss << "sphere_" << idx;
        cloud_viewer_.addSphere (pos, 0.01, 1.0, 0.0, 0.0, ss.str ());

        if (!search_.isValid ())
          return;

        search_.nearestKSearch (pos, 1, indices, distances);

        uint32_t width  = search_.getInputCloud ()->width,
                 height = search_.getInputCloud ()->height;

        int v = indices[0] / width,
            u = indices[0] % width;
        //image_viewer_.addCircle (u, height - v, 5, 1.0, 0.0, 0.0, "circles", 1.0);
        //image_viewer_.addBox (u-5, u+5, height-v-5, height-v+5, 0.0, 1.0, 0.0, "boxes", 0.5);
        image_viewer_.markPoint (u, v, pcl::visualization::red_color, pcl::visualization::blue_color, 10);
        added = !added;

        if (!added)
          //cloud_viewer_.close ();
          image_viewer_.removeLayer ("circles");
        //image_viewer_.markPoint (u, v, pcl::visualization::Vector3ub (1, 0, 0), pcl::visualization::Vector3ub (1, 0, 0), 0.1);//0.01, 1.0, 0.0, 0.0, ss.str ());
      }
    }

    /////////////////////////////////////////////////////////////////////////
    void
    init ()
    {
      cloud_viewer_.registerMouseCallback (&NILinemod::mouse_callback, *this);
      cloud_viewer_.registerKeyboardCallback(&NILinemod::keyboard_callback, *this);
      cloud_viewer_.registerPointPickingCallback (&NILinemod::pp_callback, *this);
      boost::function<void (const CloudConstPtr&) > cloud_cb = boost::bind (&NILinemod::cloud_callback, this, _1);
      cloud_connection = grabber_.registerCallback (cloud_cb);

      image_viewer_.registerMouseCallback (&NILinemod::mouse_callback, *this);
      image_viewer_.registerKeyboardCallback(&NILinemod::keyboard_callback, *this);
//      boost::function<void (const boost::shared_ptr<openni_wrapper::Image>&) > image_cb = boost::bind (&NILinemod::image_callback, this, _1);
//      image_connection = grabber_.registerCallback (image_cb);
    }

    /////////////////////////////////////////////////////////////////////////
    void
    run ()
    {
      grabber_.start ();

      bool image_init = false, cloud_init = false;
      unsigned char* rgb_data = 0;
      unsigned rgb_data_size = 0;

      while (!cloud_viewer_.wasStopped () && !image_viewer_.wasStopped ())
      {
        if (cloud_)
        {
          CloudConstPtr cloud = getLatestCloud ();
          if (!cloud_init)
          {
            cloud_viewer_.setPosition (0, 0);
            cloud_viewer_.setSize (cloud->width, cloud->height);
            cloud_init = !cloud_init;
          }

          if (!cloud_viewer_.updatePointCloud (cloud, "OpenNICloud"))
          {
            cloud_viewer_.addPointCloud (cloud, "OpenNICloud");
            cloud_viewer_.resetCameraViewpoint ("OpenNICloud");
          }

          if (!image_init)
          {
            image_viewer_.setPosition (cloud->width, 0);
            image_viewer_.setSize (cloud->width, cloud->height);
            image_init = !image_init;
          }

          image_viewer_.showRGBImage<PointXYZRGBA> (cloud);
        }

/*        if (image_)
        {
          boost::shared_ptr<openni_wrapper::Image> image = getLatestImage ();
          if (!image_init)
          {
            image_viewer_.setPosition (image->getWidth (), 0);
            image_viewer_.setSize (image->getWidth (), image->getHeight ());
            image_init = !image_init;
          }

          if (image->getEncoding() == openni_wrapper::Image::RGB)
            image_viewer_.showRGBImage (image->getMetaData ().Data (), image->getWidth (), image->getHeight ());
          else
          {
            if (rgb_data_size < image->getWidth () * image->getHeight ())
            {
              if (rgb_data)
                delete [] rgb_data;
              rgb_data_size = image->getWidth () * image->getHeight ();
              rgb_data = new unsigned char [rgb_data_size * 3];
            }
            image->fillRGB (image->getWidth (), image->getHeight (), rgb_data);
            image_viewer_.showRGBImage (rgb_data, image->getWidth (), image->getHeight ());
          }
        }*/

        cloud_viewer_.spinOnce ();
        image_viewer_.spinOnce ();
        boost::this_thread::sleep (boost::posix_time::microseconds (100));
      }

      grabber_.stop ();

//      if (rgb_data)
//        delete [] rgb_data;

      std::cerr << "finishing..." << std::endl;
      cloud_connection.disconnect ();
//      image_connection.disconnect ();
    }

    visualization::PCLVisualizer cloud_viewer_;
    Grabber& grabber_;
    boost::mutex cloud_mutex_;
    CloudConstPtr cloud_;

//    boost::mutex image_mutex_;
//    boost::shared_ptr<openni_wrapper::Image> image_;
    visualization::ImageViewer image_viewer_;

    search::OrganizedNeighbor<PointXYZRGBA> search_;
  private:
    boost::signals2::connection cloud_connection, image_connection;
};

/* ---[ */
int
main (int, char**)
{
  std::string device_id ("#1");
  OpenNIGrabber grabber (device_id);
  NILinemod openni_viewer (grabber);

  openni_viewer.init ();
  openni_viewer.run ();

  return (0);
}
/* ]--- */
<commit_msg>work on linemod trainer tool - need to do I/O and copy/paste the tracking in and we're done<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: openni_viewer.cpp 5059 2012-03-14 02:12:17Z gedikli $
 *
 */

#include <boost/thread/thread.hpp>
#include <pcl/apps/timer.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/search/organized.h>
#include <pcl/features/integral_image_normal.h>
#include <pcl/segmentation/organized_multi_plane_segmentation.h>
#include <pcl/segmentation/sac_segmentation.h>
#include <pcl/segmentation/extract_polygonal_prism_data.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/surface/convex_hull.h>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/image_viewer.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/segmentation/euclidean_cluster_comparator.h>
#include <pcl/segmentation/organized_connected_component_segmentation.h>

using namespace pcl;
using namespace std;

typedef PointXYZRGBA PointT;

#define SHOW_FPS 1

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class NILinemod
{
  public:
    typedef PointCloud<PointT> Cloud;
    typedef typename Cloud::Ptr CloudPtr;
    typedef typename Cloud::ConstPtr CloudConstPtr;
    bool added;

    NILinemod (Grabber& grabber)
      : cloud_viewer_ ("PointCloud")
      , grabber_ (grabber)
      , image_viewer_ ("Image")
      , first_frame_ (true)
    {
      added = false;
    }

    /////////////////////////////////////////////////////////////////////////
    void
    cloud_callback (const CloudConstPtr& cloud)
    {
      FPS_CALC ("cloud callback");
      boost::mutex::scoped_lock lock (cloud_mutex_);
      cloud_ = cloud;
      search_.setInputCloud (cloud);
    }

    CloudConstPtr
    getLatestCloud ()
    {
      // Lock while we swap our cloud and reset it.
      boost::mutex::scoped_lock lock (cloud_mutex_);
      CloudConstPtr temp_cloud;
      temp_cloud.swap (cloud_);
      return (temp_cloud);
    }

    /////////////////////////////////////////////////////////////////////////
    void
    keyboard_callback (const visualization::KeyboardEvent& event, void*)
    {
      //if (event.getKeyCode())
      //  cout << "the key \'" << event.getKeyCode() << "\' (" << event.getKeyCode() << ") was";
      //else
      //  cout << "the special key \'" << event.getKeySym() << "\' was";
      //if (event.keyDown())
      //  cout << " pressed" << endl;
      //else
      //  cout << " released" << endl;
    }

    /////////////////////////////////////////////////////////////////////////
    void
    mouse_callback (const visualization::MouseEvent& mouse_event, void*)
    {
      if (mouse_event.getType() == visualization::MouseEvent::MouseButtonPress && mouse_event.getButton() == visualization::MouseEvent::LeftButton)
      {
        cout << "left button pressed @ " << mouse_event.getX () << " , " << mouse_event.getY () << endl;
      }
    }

    /////////////////////////////////////////////////////////////////////////
    /** \brief Given a plane, and the set of inlier indices representing it,
      * segment out all the objects supported by it.
      */
    void
    segmentObject (const CloudConstPtr &cloud, const PointIndices::Ptr &plane_indices,
                   Cloud &object)
    {
      CloudPtr plane_hull (new Cloud);

      // Compute the convex hull
      ConvexHull<PointT> chull;
      chull.setDimension (2);
      chull.setInputCloud (cloud);
      chull.setIndices (plane_indices);
      chull.reconstruct (*plane_hull);

      // Extract all clusters on the hull
      PointIndices::Ptr inliers (new PointIndices);
      ExtractPolygonalPrismData<PointT> ex;
      ex.setInputCloud (cloud);
      ex.setInputPlanarHull (plane_hull);
      ex.setHeightLimits (0.01, 0.5);
      ex.segment (*inliers);

      // Use an organized clustering segmentation to extract the individual clusters
      EuclideanClusterComparator<PointT, Normal, Label>::Ptr euclidean_cluster_comparator (new EuclideanClusterComparator<PointT, Normal, Label>);
      euclidean_cluster_comparator->setInputCloud (cloud);
      // Set the entire scene to false, and the inliers of the objects located on top of the plane to true
      Label l; l.label = 0;
      PointCloud<Label>::Ptr scene (new PointCloud<Label> (cloud->width, cloud->height, l));
      for (int i = 0; i < static_cast<int> (inliers->indices.size ()); ++i)
        scene->points[inliers->indices[i]].label = 1;
      euclidean_cluster_comparator->setLabels (scene);

      vector<bool> exclude_labels (2);  exclude_labels[0] = true; exclude_labels[1] = false;
      euclidean_cluster_comparator->setExcludeLabels (exclude_labels);

      OrganizedConnectedComponentSegmentation<PointT, Label> euclidean_segmentation (euclidean_cluster_comparator);
      euclidean_segmentation.setInputCloud (cloud);

      PointCloud<Label> euclidean_labels;
      vector<PointIndices> euclidean_label_indices;
      euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);

      for (size_t i = 0; i < euclidean_label_indices.size (); i++)
      {
        if (euclidean_label_indices[i].indices.size () > 1000)
        {
          //pcl::PointCloud<PointT> cluster;
          pcl::copyPointCloud (*cloud, euclidean_label_indices[i].indices, object);
          std::cerr << "inliers: " << euclidean_label_indices[i].indices.size () << std::endl;
          //object_indices = euclidean_label_indices[i].indices;
          //clusters.push_back (cluster);
        }
      }
    }

    /////////////////////////////////////////////////////////////////////////
    void
    segment (const PointT &picked_point,
             PlanarRegion<PointT> &region,
             PointIndices &indices)
    {
      // First frame is segmented using an organized multi plane segmentation approach from points and their normals
      if (first_frame_)
      {
        // Estimate normals in the cloud
        IntegralImageNormalEstimation<PointT, Normal> ne;
        ne.setNormalEstimationMethod (ne.COVARIANCE_MATRIX);
        ne.setMaxDepthChangeFactor (0.02f);
        ne.setNormalSmoothingSize (10.0f);
        PointCloud<Normal>::Ptr normal_cloud (new PointCloud<Normal>);
        ne.setInputCloud (search_.getInputCloud ());
        ne.compute (*normal_cloud);

        // Segment out all planes
        OrganizedMultiPlaneSegmentation<PointT, Normal, Label> mps;
        mps.setMinInliers (5000);
        mps.setAngularThreshold (0.017453 * 3.0); //3 degrees
        mps.setDistanceThreshold (0.03); //2cm
        mps.setInputNormals (normal_cloud);
        mps.setInputCloud (search_.getInputCloud ());

        vector<PlanarRegion<PointT> > regions;
        //mps.segmentAndRefine (regions);
        vector<ModelCoefficients> model_coefficients;
        vector<PointIndices> inlier_indices;
        PointCloud<Label>::Ptr labels (new PointCloud<Label>);
        vector<PointIndices> label_indices;
        vector<PointIndices> boundary_indices;
        PointIndices::Ptr plane_boundaries;
        mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
        //mps.segmentAndRefine (regions);//, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);

        double max_dist = numeric_limits<double>::max ();
        // Compute the distances from all the planar regions to the picked point, and select the closest region
        int idx = -1;
        for (size_t i = 0; i < regions.size (); ++i)
        {
          double dist = pointToPlaneDistance (picked_point, regions[i].getCoefficients ());
          if (dist < max_dist)
          {
            max_dist = dist;
            idx = i;
          }
        }

        // Get the plane that holds the object of interest
        if (idx != -1)
        {
          region = regions[idx];
          plane_boundaries.reset (new PointIndices (inlier_indices[idx]));
        }

        // Segment the object of interest
        if (plane_boundaries && !plane_boundaries->indices.empty ())
        {
          CloudPtr object (new Cloud);
          segmentObject (search_.getInputCloud (), plane_boundaries, *object);
          visualization::PointCloudColorHandlerCustom<PointT> red (object, 255, 0, 0);
          if (!cloud_viewer_.updatePointCloud (object, red, "object"))
            cloud_viewer_.addPointCloud (object, red, "object");
        }
        //first_frame_ = false;
      }
      // Subsequent frames are segmented by "tracking" the parameters of the previous frame
      // We do this by using the estimated inliers from previous frames in the current frame,
      // and refining the coefficients
      else
      {
        SACSegmentation<PointT> seg;
        seg.setOptimizeCoefficients (true);
        seg.setModelType (SACMODEL_PLANE);
        seg.setMethodType (SAC_RANSAC);
        seg.setMaxIterations (1000);
        seg.setDistanceThreshold (0.01);
        seg.setInputCloud (search_.getInputCloud ());
        //seg.setIndices (indices);
        ModelCoefficients coefficients;
        PointIndices inliers;
        seg.segment (inliers, coefficients);
      }
    }

    /////////////////////////////////////////////////////////////////////////
    void
    pp_callback (const visualization::PointPickingEvent& event, void*)
    {
      int idx = event.getPointIndex ();
      if (idx == -1)
        return;

      vector<int> indices (1);
      vector<float> distances (1);

      {
        // Use mutices to make sure we get the right cloud
        boost::mutex::scoped_lock lock1 (cloud_mutex_);
        //boost::mutex::scoped_lock lock2 (image_mutex_);

        PointT pos;
        event.getPoint (pos.x, pos.y, pos.z);

        stringstream ss;
        ss << "sphere_" << idx;
        cloud_viewer_.addSphere (pos, 0.01, 1.0, 0.0, 0.0, ss.str ());

        if (!search_.isValid ())
          return;

        search_.nearestKSearch (pos, 1, indices, distances);

        uint32_t width  = search_.getInputCloud ()->width,
                 height = search_.getInputCloud ()->height;

        int v = height - indices[0] / width,
            u = indices[0] % width;
        image_viewer_.addCircle (u, v, 5, 1.0, 0.0, 0.0, "circles", 1.0);
        image_viewer_.addBox (u-5, u+5, v-5, v+5, 0.0, 1.0, 0.0, "boxes", 0.5);
        image_viewer_.markPoint (u, v, visualization::red_color, visualization::blue_color, 10);
        added = !added;

        PlanarRegion<PointT> region;
        PointIndices region_indices;
        segment (pos, region, region_indices);

        cloud_viewer_.addPolygon (region, 0.0, 1.0, 0.0);
        cloud_viewer_.setShapeRenderingProperties (visualization::PCL_VISUALIZER_LINE_WIDTH, 10, "polygon");

        if (region.getContour ().empty ())
        {
          PCL_ERROR ("No region detected. Please select another point and continue.\n");
          return;
        }

/*        search_.nearestKSearch (region.getContour ()[0], 1, indices, distances);
        int v_p = height - indices[0] / width,
            u_p = indices[0] % width;
        for (int i = 1; i < region.getContour ().size (); ++i)
        {
          search_.nearestKSearch (region.getContour ()[i], 1, indices, distances);
          int v = height - indices[0] / width,
              u = indices[0] % width;

          image_viewer_.addLine (u_p, v_p, u, v, 0.0, 1.0, 0.0);
          v_p = v; u_p = u;
        }*/
      }
    }

    /////////////////////////////////////////////////////////////////////////
    void
    init ()
    {
      cloud_viewer_.registerMouseCallback (&NILinemod::mouse_callback, *this);
      cloud_viewer_.registerKeyboardCallback(&NILinemod::keyboard_callback, *this);
      cloud_viewer_.registerPointPickingCallback (&NILinemod::pp_callback, *this);
      boost::function<void (const CloudConstPtr&) > cloud_cb = boost::bind (&NILinemod::cloud_callback, this, _1);
      cloud_connection = grabber_.registerCallback (cloud_cb);

      image_viewer_.registerMouseCallback (&NILinemod::mouse_callback, *this);
      image_viewer_.registerKeyboardCallback(&NILinemod::keyboard_callback, *this);
    }

    /////////////////////////////////////////////////////////////////////////
    void
    run ()
    {
      grabber_.start ();

      bool image_init = false, cloud_init = false;
      unsigned char* rgb_data = 0;
      unsigned rgb_data_size = 0;

      while (!cloud_viewer_.wasStopped () && !image_viewer_.wasStopped ())
      {
        if (cloud_)
        {
          CloudConstPtr cloud = getLatestCloud ();
          if (!cloud_init)
          {
            cloud_viewer_.setPosition (0, 0);
            cloud_viewer_.setSize (cloud->width, cloud->height);
            cloud_init = !cloud_init;
          }

          if (!cloud_viewer_.updatePointCloud (cloud, "OpenNICloud"))
          {
            cloud_viewer_.addPointCloud (cloud, "OpenNICloud");
            cloud_viewer_.resetCameraViewpoint ("OpenNICloud");
          }

          if (!image_init)
          {
            image_viewer_.setPosition (cloud->width, 0);
            image_viewer_.setSize (cloud->width, cloud->height);
            image_init = !image_init;
          }

          image_viewer_.showRGBImage<PointT> (cloud);
        }

        cloud_viewer_.spinOnce ();
        image_viewer_.spinOnce ();
        boost::this_thread::sleep (boost::posix_time::microseconds (100));
      }

      grabber_.stop ();

      cloud_connection.disconnect ();
    }

    visualization::PCLVisualizer cloud_viewer_;
    Grabber& grabber_;
    boost::mutex cloud_mutex_;
    CloudConstPtr cloud_;

    visualization::ImageViewer image_viewer_;

    search::OrganizedNeighbor<PointT> search_;
  private:
    boost::signals2::connection cloud_connection, image_connection;
    bool first_frame_;
};

/* ---[ */
int
main (int, char**)
{
  string device_id ("#1");
  OpenNIGrabber grabber (device_id);
  NILinemod openni_viewer (grabber);

  openni_viewer.init ();
  openni_viewer.run ();

  return (0);
}
/* ]--- */
<|endoftext|>