Cube does not move in a simple 3d viewer

In this simple program, the cube is drawn, but I’m unable to move it with the mouse. I tried and tried to fix it without success. It might be a very simple issue. Can you help me, please?

/**
 * animator.cpp
 */
#include <iostream>
#include "animator.h"

namespace belem
{

Animator::Animator() :
    mAnimation(NONE),
    mInteractor(0),
    mFrame(0),
    mFrames(0),
    mFramesPerSecond(30.),
    mHeight(0),
    mTic(std::chrono::system_clock::now()),
    mWidth(0)
{
    stopwatch();
}

Animator::~Animator()
{
}

void Animator::animate()
{
    if (elapsedSeconds() < 1.0 / mFramesPerSecond) {
        return;
    }

    switch(mAnimation) {
        case FIRST_PERSON:
            firstperson();
            break;
        case ORBIT:
            orbit();
            break;
        case PAN:
            pan();
            break;
        case ROLL:
            roll();
            break;
        case ZOOM:
            zoom();
            break;
        case NONE: default:
            return;
            break;
    }

    stopwatch();
}

double Animator::elapsedSeconds()
{
    std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
    std::chrono::duration<double> seconds = now - mTic;
    return seconds.count();
}

void Animator::firstperson()
{
}

void Animator::orbit()
{
    Camera *c = mInteractor->getCamera();
    if (0 == mFrame) {
        mFrames = 5 * mFramesPerSecond;
        c->setEye(1., 1., 1.);
        c->setUp(-0., -0., 1.);
        c->setCenter(0, 0, 0);
        c->update();
        mInteractor->setCamera(c);
    }

    double x = fmod(mFrame*4, mWidth);
    double y = mHeight * .74;
    mInteractor->setLeftClicked(true);
    mInteractor->setClickPoint(x, y);

    if (++mFrame >= mFrames) {
        mInteractor->setLeftClicked(false);
        reset();
    }
}

void Animator::pan()
{
}

void Animator::reset()
{
    mAnimation = NONE;
    mFrame = 0;
}

void Animator::roll()
{
}

void Animator::setAnimation(AnimationType type)
{
    mAnimation = type;
}

void Animator::setInteractor(TrackBallInteractor *i)
{
    mInteractor = i;
}

void Animator::setScreenSize(int w, int h)
{
    mWidth = w;
    mHeight = h;
}

void Animator::stopwatch()
{
    mTic = std::chrono::system_clock::now();
}

void Animator::zoom()
{
}

}

/**
 * camera.cpp
 */
#include <camera.h>
#include <iostream>

#define GLM_FORCE_RADIANS
#include <glm/gtc/matrix_transform.hpp> // lookAt
#include <glm/gtc/type_ptr.hpp> // value_ptr

namespace belem
{

Camera::Camera()
{
    reset();
}

Camera::~Camera()
{
}

const glm::vec3 & Camera::getCenter()
{
	return mCenter;
}

const glm::vec3 & Camera::getEye()
{
	return mEye;
}

const glm::mat4 & Camera::getMatrix()
{
	return mMatrix;
}

const float* Camera::getMatrixFlat()
{
	return glm::value_ptr(mMatrix);
}

const glm::vec3 & Camera::getUp()
{
	return mUp;
}

void Camera::reset()
{
	mEye.x = 0.f;
	mEye.y = 0.f;
	mEye.z = 1.f;
	mCenter.x = 0.f;
	mCenter.y = 0.f;
	mCenter.z = 0.f;
	mUp.x = 0.f;
	mUp.y = 1.f;
	mUp.z = 0.f;

    update();
}

void Camera::setEye(float x, float y, float z)
{
	mEye.x = x;
	mEye.y = y;
	mEye.z = z;
}

void Camera::setEye(const glm::vec3 & e)
{
    mEye = e;
}

void Camera::setCenter(float x, float y, float z)
{
	mCenter.x = x;
	mCenter.y = y;
	mCenter.z = z;
}

void Camera::setCenter(const glm::vec3 & c)
{
    mCenter = c;
}

void Camera::setUp(float x, float y, float z)
{
	mUp.x = x;
	mUp.y = y;
	mUp.z = z;
}

void Camera::setUp(const glm::vec3 & u)
{
    mUp = u;
}

void Camera::update()
{
    mMatrix = glm::lookAt(mEye, mCenter, mUp);
}

} // end namespace belem

/**
 * renderer.cpp
 */
#include <renderer.h>

namespace belem
{

Renderer::Renderer() : mCamera(0)
{
}

Renderer::~Renderer()
{
}

const Camera* Renderer::getCamera()
{
    return mCamera;
}

void Renderer::setCamera(Camera *c)
{
	mCamera = c;
}

} // end namespace belem

/**
 * trackball.cpp
 */
#include <glm/gtx/norm.hpp> // length2
#include <glm/vec3.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/constants.hpp> // pi
#include <trackball.h>
#include <iostream>

namespace belem
{

const glm::vec3 TrackBallInteractor::X(1.f, 0.f, 0.f);
const glm::vec3 TrackBallInteractor::Y(0.f, 1.f, 0.f);
const glm::vec3 TrackBallInteractor::Z(0.f, 0.f, 1.f);

TrackBallInteractor::TrackBallInteractor()
    : mCamera(nullptr),
      mCameraMotionLeftClick(ARC),
      mCameraMotionMiddleClick(ROLL),
      mCameraMotionRightClick(FIRSTPERSON),
      mCameraMotionScroll(ZOOM),
      mClickPoint(),
      mHeight(1),
      mIsDragging(false),
      mIsLeftClick(false),
      mIsMiddleClick(false),
      mIsRightClick(false),
      mIsScrolling(false),
      mPanScale(0.005f),
      mPrevClickPoint(),
      mRollScale(0.005f),
      mRollSum(0.0f),
      mRotation(1.0f, 0.0f, 0.0f, 0.0f),
      mRotationSum(1.0f, 0.0f, 0.0f, 0.0f),
      mSpeed(1.0f),
      mStartVector(),
      mStopVector(),
      mTranslateLength(0.0f),
      mWidth(1),
      mZoomSum(0.0f),
      mZoomScale(0.1f) // mZoomScale initialized last to avoid warning
{
}

TrackBallInteractor::~TrackBallInteractor()
{
}

char TrackBallInteractor::clickQuadrant(float x, float y)
{
    float halfw = .5 * mWidth;
    float halfh = .5 * mHeight;

    if (x > halfw) {
        // Opengl image coordinates origin is upperleft.
        if (y < halfh) {
            return 1;
        } else {
            return 4;
        }
    } else {
        if (y < halfh) {
            return 2;
        } else {
            return 3;
        }
    }
}

void TrackBallInteractor::computeCameraEye(glm::vec3 & eye)
{
    glm::vec3 orientation = mRotationSum * Z;

    if (mZoomSum) {
        mTranslateLength += mZoomScale * mZoomSum;
        mZoomSum = 0; // Freeze zooming after applying.
    }

    eye = mTranslateLength * orientation + mCamera->getCenter();
}

void TrackBallInteractor::computeCameraUp(glm::vec3 & up)
{
    up = glm::normalize(mRotationSum * Y);
}

void TrackBallInteractor::computePan(glm::vec3 & pan)
{
    glm::vec2 click = mClickPoint - mPrevClickPoint;
    glm::vec3 look = mCamera->getEye() - mCamera->getCenter();
    float length = glm::length(look);
    glm::vec3 right = glm::normalize(mRotationSum * X);

    pan = (mCamera->getUp() * -click.y + right * click.x) *
          mPanScale * mSpeed * length;
}

void TrackBallInteractor::computePointOnSphere(
    const glm::vec2 & point, glm::vec3 & result)
{
    // https://www.opengl.org/wiki/Object_Mouse_Trackball
    float x = (2.f * point.x - mWidth) / mWidth;
    float y = (mHeight - 2.f * point.y) / mHeight;

    float length2 = x*x + y*y;

    if (length2 <= .5) {
        result.z = sqrt(1.0 - length2);
    } else {
        result.z = 0.5 / sqrt(length2);
    }

    float norm = 1.0 / sqrt(length2 + result.z*result.z);

    result.x = x * norm;
    result.y = y * norm;
    result.z *= norm;
}

void TrackBallInteractor::computeRotationBetweenVectors(
    const glm::vec3 & u, const glm::vec3 & v, glm::quat & result)
{
 	float cosTheta = glm::dot(u, v);
    glm::vec3 rotationAxis;
    static const float EPSILON = 1.0e-5f;

 	if (cosTheta < -1.0f + EPSILON){
 		// Parallel and opposite directions.
 		rotationAxis = glm::cross(glm::vec3(0.f, 0.f, 1.f), u);

 		if (glm::length2(rotationAxis) < 0.01 ) {
            // Still parallel, retry.
            rotationAxis = glm::cross(glm::vec3(1.f, 0.f, 0.f), u);
        }

 		rotationAxis = glm::normalize(rotationAxis);
 		result = glm::angleAxis(180.0f, rotationAxis);
 	} else if (cosTheta > 1.0f - EPSILON) {
        // Parallel and same direction.
        result = glm::quat(1, 0, 0, 0);
        return;
    } else {
        float theta = acos(cosTheta);
        rotationAxis = glm::cross(u, v);

        rotationAxis = glm::normalize(rotationAxis);
        result = glm::angleAxis(theta * mSpeed, rotationAxis);
    }
}

void TrackBallInteractor::drag()
{
    if (mPrevClickPoint == mClickPoint) {
        // Not moving during drag state, so skip unnecessary processing.
        return;
    }

    computePointOnSphere(mClickPoint, mStopVector);
    computeRotationBetweenVectors(mStartVector,
                                  mStopVector,
                                  mRotation);
    // Reverse so scene moves with cursor and not away due to camera model.
    mRotation = glm::inverse(mRotation);

    drag(mIsLeftClick, mCameraMotionLeftClick);
    drag(mIsMiddleClick, mCameraMotionMiddleClick);
    drag(mIsRightClick, mCameraMotionRightClick);

    // After applying drag, reset relative start state.
    mPrevClickPoint = mClickPoint;
    mStartVector = mStopVector;
}

void TrackBallInteractor::drag(bool isClicked, CameraMotionType motion)
{
    if (!isClicked) {
        return;
    }

    switch(motion) {
        case ARC:
            dragArc();
            break;
        case FIRSTPERSON:
            dragFirstPerson();
            break;
        case PAN:
            dragPan();
            break;
        case ROLL:
            rollCamera();
            break;
        case ZOOM:
            dragZoom();
            break;
        default: break;
    }
}

void TrackBallInteractor::dragArc()
{
    mRotationSum *= mRotation; // Accumulate quaternions.

    updateCameraEyeUp(true, true);
}

void TrackBallInteractor::dragFirstPerson()
{
    glm::vec3 pan;
    computePan(pan);
    mCamera->setCenter(pan + mCamera->getCenter());
    mCamera->update();
    freezeTransform();
}

void TrackBallInteractor::dragPan()
{
    glm::vec3 pan;
    computePan(pan);
    mCamera->setCenter(pan + mCamera->getCenter());
    mCamera->setEye(pan + mCamera->getEye());
    mCamera->update();
    freezeTransform();
}

void TrackBallInteractor::dragZoom()
{
    glm::vec2 dir = mClickPoint - mPrevClickPoint;
    float ax = fabs(dir.x);
    float ay = fabs(dir.y);

    if (ay >= ax) {
        setScrollDirection(dir.y <= 0);
    } else {
        setScrollDirection(dir.x <= 0);
    }

    updateCameraEyeUp(true, false);
}

void TrackBallInteractor::freezeTransform()
{
    if (mCamera) {
        // Opengl is ZYX order.
        // Flip orientation to rotate scene with sticky cursor.
        mRotationSum = glm::inverse(glm::quat(mCamera->getMatrix()));
        mTranslateLength = glm::length(mCamera->getEye()-mCamera->getCenter());
    }
}

Camera* TrackBallInteractor::getCamera()
{
    return mCamera;
}

TrackBallInteractor::CameraMotionType TrackBallInteractor::getMotionLeftClick()
{
    return mCameraMotionLeftClick;
}

TrackBallInteractor::CameraMotionType TrackBallInteractor::getMotionMiddleClick()
{
    return mCameraMotionMiddleClick;
}

TrackBallInteractor::CameraMotionType TrackBallInteractor::getMotionRightClick()
{
    return mCameraMotionRightClick;
}

TrackBallInteractor::CameraMotionType TrackBallInteractor::getMotionScroll()
{
    return mCameraMotionScroll;
}

void TrackBallInteractor::rollCamera()
{
    glm::vec2 delta = mClickPoint - mPrevClickPoint;
    char quad = clickQuadrant(mClickPoint.x, mClickPoint.y);
    switch (quad) {
        case 1:
            delta.y = -delta.y;
            delta.x = -delta.x;
            break;
        case 2:
            delta.x = -delta.x;
            break;
        case 3:
            break;
        case 4:
            delta.y = -delta.y;
        default:
            break;
    }

    glm::vec3 axis = glm::normalize(mCamera->getCenter() - mCamera->getEye());
    float angle = mRollScale * mSpeed * (delta.x + delta.y + mRollSum);
    glm::quat rot = glm::angleAxis(angle, axis);
    mCamera->setUp(rot * mCamera->getUp());
    mCamera->update();
    freezeTransform();
    mRollSum = 0;
}

void TrackBallInteractor::scroll()
{
    switch(mCameraMotionScroll) {
        case ROLL:
            rollCamera();
            break;
        case ZOOM:
            updateCameraEyeUp(true, false);
            break;
        default: break;
    }
}

void TrackBallInteractor::setCamera(Camera *c)
{
    mCamera = c;
    freezeTransform();
}

void TrackBallInteractor::setClickPoint(double x, double y)
{
    mPrevClickPoint = mClickPoint;
    mClickPoint.x = x;
    mClickPoint.y = y;
}

void TrackBallInteractor::setLeftClicked(bool value)
{
	mIsLeftClick = value;
}

void TrackBallInteractor::setMiddleClicked(bool value)
{
    mIsMiddleClick = value;
}

void TrackBallInteractor::setMotionLeftClick(CameraMotionType motion)
{
    mCameraMotionLeftClick = motion;
}

void TrackBallInteractor::setMotionMiddleClick(CameraMotionType motion)
{
    mCameraMotionMiddleClick = motion;
}

void TrackBallInteractor::setMotionRightClick(CameraMotionType motion)
{
    mCameraMotionRightClick = motion;
}

void TrackBallInteractor::setMotionScroll(CameraMotionType motion)
{
    mCameraMotionScroll = motion;
}

void TrackBallInteractor::setRightClicked(bool value)
{
	mIsRightClick = value;
}

void TrackBallInteractor::setScreenSize(float width, float height)
{
    if (width > 1 && height > 1) {
        mWidth = width;
        mHeight = height;
    }
}

void TrackBallInteractor::setScrollDirection(bool up)
{
    mIsScrolling = true;
    float inc = mSpeed * (up ? -1.f : 1.f);
    mZoomSum += inc;
    mRollSum += inc;
}

void TrackBallInteractor::setSpeed(float s)
{
    mSpeed = s;
}

void TrackBallInteractor::update()
{
    const bool isClick = mIsLeftClick || mIsMiddleClick || mIsRightClick;

    if (! mIsDragging)
    {
        if (isClick)
        {
			mIsDragging = true;
            computePointOnSphere(mClickPoint, mStartVector);
        } else if (mIsScrolling) {
            scroll();
            mIsScrolling = false;
        }
    }
    else
    {
        if (isClick)
        {
            drag();
        } else
        {
            mIsDragging = false;
        }
    }
}

void TrackBallInteractor::updateCameraEyeUp(bool eye, bool up)
{
    if (eye) {
        glm::vec3 eye;
        computeCameraEye(eye);
        mCamera->setEye(eye);
    }
    if (up) {
        glm::vec3 up;
        computeCameraUp(up);
        mCamera->setUp(up);
    }
    mCamera->update();
}

} // end namespace belem

/**
 * window.cpp
 */
#include "window.h"

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#include <glm/glm.hpp>
#include <iostream>

namespace belem
{

static const char* HELP =
    "           c: Print camera Eye, Center, Up\n"
    "           r: Reset view\n"
    "           t: Toggle right button to do Pan or First-Person\n"
    "     x, y, z: Snap camera to axis\n"
    "   Hold Ctrl: Increase speed\n"
    "  Hold Shift: Reduce speed\n"
    "  Left-Click: Rotate\n"
    "Middle-Click: Pan or First-Person\n"
    " Right-Click: Roll\n"
    "Scroll-Wheel: Dolly (zoom)\n";

Window::Window() : mWindow(0)
{
}

Window::~Window()
{
}


void Window::buttonCallback(GLFWwindow *window, int button,
                                      int action, int mods)
{
    switch(action)
    {
        case GLFW_PRESS:
        {
            switch(button)
            {
                case GLFW_MOUSE_BUTTON_LEFT:
                    instance().mInteractor.setLeftClicked(true);
                    break;
                case GLFW_MOUSE_BUTTON_MIDDLE:
                    instance().mInteractor.setMiddleClicked(true);
                    break;
                case GLFW_MOUSE_BUTTON_RIGHT:
                    instance().mInteractor.setRightClicked(true);
                    break;
            }

            double xpos, ypos;
            glfwGetCursorPos(window, & xpos, & ypos);
            instance().mInteractor.setClickPoint(xpos, ypos);
            break;
        }
        case GLFW_RELEASE:
        {
            switch(button)
            {
                case GLFW_MOUSE_BUTTON_LEFT:
                    instance().mInteractor.setLeftClicked(false);
                    break;
                case GLFW_MOUSE_BUTTON_MIDDLE:
                    instance().mInteractor.setMiddleClicked(false);
                    break;
                case GLFW_MOUSE_BUTTON_RIGHT:
                    instance().mInteractor.setRightClicked(false);
                    break;
            }
            break;
        }
        default: break;
    }
}

void Window::errorCallback(int error, const char* description)
{
    std::cerr << description << std::endl;
}

Window & Window::instance()
{
	static Window i;
	return i;
}

void Window::keyCallback(GLFWwindow *window, int key, int scancode,
                                   int action, int mods)
{
    float length;

    switch(action) {
        case GLFW_PRESS:
            switch(key)
            {
                case GLFW_KEY_ESCAPE:
                    // Exit app on ESC key.
                    glfwSetWindowShouldClose(window, GL_TRUE);
                    break;
                case GLFW_KEY_LEFT_CONTROL:
                case GLFW_KEY_RIGHT_CONTROL:
                    instance().mInteractor.setSpeed(5.f);
                    break;
                case GLFW_KEY_LEFT_SHIFT:
                case GLFW_KEY_RIGHT_SHIFT:
                    instance().mInteractor.setSpeed(.1f);
                    break;
                case GLFW_KEY_F1:
                    instance().mAnimator.setAnimation(Animator::ORBIT);
                    break;
                case GLFW_KEY_C:
                    std::cout
                        << "(" << instance().mCamera.getEye().x
                        << "," << instance().mCamera.getEye().y
                        << "," << instance().mCamera.getEye().z << ") "
                        << "(" << instance().mCamera.getCenter().x
                        << "," << instance().mCamera.getCenter().y
                        << "," << instance().mCamera.getCenter().z << ") "
                        << "(" << instance().mCamera.getUp().x
                        << "," << instance().mCamera.getUp().y
                        << "," << instance().mCamera.getUp().z  << ")\n";
                	fflush(stdout);
                    break;
                case GLFW_KEY_R:
                    // Reset the view.
                    instance().mCamera.reset();
                    instance().mInteractor.setCamera(& instance().mCamera);
                    break;
                case GLFW_KEY_T:
                    // Toogle motion type.
                    if (instance().mInteractor.getMotionRightClick() ==
                            TrackBallInteractor::FIRSTPERSON) {
                        instance().mInteractor.setMotionRightClick(
                                TrackBallInteractor::PAN);
                    } else {
                        instance().mInteractor.setMotionRightClick(
                                TrackBallInteractor::FIRSTPERSON);
                    }
                    break;
                case GLFW_KEY_X:
                    // Snap view to axis.
                    length = glm::length(instance().mCamera.getEye() -
                                         instance().mCamera.getCenter());
                    instance().mCamera.setEye(length,0,0);
                    instance().mCamera.setUp(0,1,0);
                    instance().mCamera.update();
                    instance().mInteractor.setCamera(& instance().mCamera);
                    break;
                case GLFW_KEY_Y:
                    length = glm::length(instance().mCamera.getEye() -
                                         instance().mCamera.getCenter());
                    instance().mCamera.setEye(0,length,0);
                    instance().mCamera.setUp(1,0,0);
                    instance().mCamera.update();
                    instance().mInteractor.setCamera(& instance().mCamera);
                    break;
                case GLFW_KEY_Z:
                    length = glm::length(instance().mCamera.getEye() -
                                         instance().mCamera.getCenter());
                    instance().mCamera.setEye(0,0,length);
                    instance().mCamera.setUp(1,0,0);
                    instance().mCamera.update();
                    instance().mInteractor.setCamera(& instance().mCamera);
                    break;
                default: break;
            }
            break;
        case GLFW_RELEASE:
            switch(key)
            {
                case GLFW_KEY_LEFT_CONTROL:
                case GLFW_KEY_RIGHT_CONTROL:
                case GLFW_KEY_LEFT_SHIFT:
                case GLFW_KEY_RIGHT_SHIFT:
                    instance().mInteractor.setSpeed(1.f);
                    break;
            }
            break;
        default: break;
    }
}

void Window::moveCallback(GLFWwindow *window, double xpos, double ypos)
{
    instance().mInteractor.setClickPoint(xpos, ypos);
}

void Window::scrollCallback(GLFWwindow *window, double xpos, double ypos)
{
    instance().mInteractor.setScrollDirection(xpos + ypos > 0 ? true : false);
}

void Window::sizeCallback(GLFWwindow *window, int width, int height)
{
    instance().mRenderer.resize(width, height);
    instance().mInteractor.setScreenSize(width, height);
    instance().mAnimator.setScreenSize(width, height);
}

int Window::run(int width, int height)
{
    int exitcode = EXIT_SUCCESS;

    glfwSetErrorCallback(& Window::errorCallback);

    if (!glfwInit())
    {
        exitcode = EXIT_FAILURE;
        goto recover;
    }
    mWindow = glfwCreateWindow(width, height, "Belém", NULL, NULL);
    if (!mWindow)
    {
        glfwTerminate();
        exitcode = EXIT_FAILURE;
        goto recover;
    }
    std::cout << HELP;
    glfwMakeContextCurrent(mWindow);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
    	// Handle GLAD initialization error
    	glfwTerminate();
    	return -1;
    }
    // OpenGL is now ready to use
    mRenderer.init();
    glfwSwapInterval(1);
    glfwSetCursorPosCallback(mWindow, & Window::moveCallback);
    glfwSetKeyCallback(mWindow, & Window::keyCallback);
    glfwSetMouseButtonCallback(mWindow, & Window::buttonCallback);
    glfwSetScrollCallback(mWindow, & Window::scrollCallback);
    glfwSetWindowSizeCallback(mWindow, &Window::sizeCallback);
    mInteractor.setCamera(& mCamera);
    mRenderer.setCamera(& mCamera);
    mAnimator.setInteractor(& mInteractor);
    mRenderer.init();
    sizeCallback(mWindow, width, height); // Set initial size.
    while (!glfwWindowShouldClose(mWindow))
    {
        mAnimator.animate();
        mInteractor.update();
        mRenderer.render();
        glfwSwapBuffers(mWindow);
        glfwPollEvents();
    }
    glfwDestroyWindow(mWindow);
    glfwTerminate();

recover:
    return exitcode;
}

} // end namespace belem

/**
 * cube.cpp
 */
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "world.h"
#include "camera.h"
#include "window.h"

namespace belem
{

const char* vertexShaderSource = R"(
    #version 460 core
    layout (location = 0) in vec3 aPos;
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    void main()
    {
        gl_Position = projection * view * model * vec4(aPos, 1.0);
    }
)";

const char* fragmentShaderSource = R"(
    #version 460 core
    out vec4 FragColor;
    void main()
    {
		// Orange color with alpha = 0.9
	    FragColor = vec4(1.0, 0.5, 0.2, 0.9); 
    } 
)";

void World::prepareCube()
{
   // Build and compile shader program
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // Set up vertex data and buffers
    float vertices[] = {
         0.5f,  0.5f,  0.5f,
         0.5f, -0.5f,  0.5f,
        -0.5f, -0.5f,  0.5f,
        -0.5f,  0.5f,  0.5f,

         0.5f,  0.5f, -0.5f,
         0.5f, -0.5f, -0.5f,
        -0.5f, -0.5f, -0.5f,
        -0.5f,  0.5f, -0.5f
    };
    unsigned int indices[] = {
        0, 1, 3,
        1, 2, 3,
        4, 5, 7,
        5, 6, 7,
        0, 1, 5,
        0, 5, 4,
        2, 3, 7,
        2, 7, 6,
        0, 3, 7,
        0, 7, 4,
        1, 2, 6,
        1, 6, 5
    };

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
}

void World::renderCube()
{
    // Set OpenGL state
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND); // Enable blending for transparency
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Set blending function
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Activate shader
    glUseProgram(shaderProgram);

    // Set transformation matrices
    glm::mat4 model = glm::mat4(1.0f);
    glm::mat4 view = Window::instance().getCamera().getMatrix();
    glm::mat4 projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

    // Draw the cube
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}

}