//--------------------------------------------------------------------------------------------------
/// Set up camera/viewport and render
//--------------------------------------------------------------------------------------------------
void OverlayNavigationCube::render(OpenGLContext* oglContext, const Vec2i& position, const Vec2ui& size, bool software, const Mat4d& viewMatrix)
{
    if (size.x() <= 0 || size.y() <= 0)
    {
        return;
    }

    if (m_axis.isNull()) 
    {
        createAxisGeometry(software);
    }

    if (m_cubeGeos.size() == 0)
    {
        createCubeGeos();

        // Create the shader for the cube geometry
        ShaderProgramGenerator gen("CubeGeoShader", ShaderSourceProvider::instance());
        gen.configureStandardHeadlightColor();
        m_cubeGeoShader = gen.generate();
        m_cubeGeoShader->linkProgram(oglContext);
    }

    // Position the camera far enough away to make the axis and the text fit within the viewport
    Mat4d axisMatrix = viewMatrix;
    axisMatrix.setTranslation(Vec3d(0, 0, -2.0));

    // Setup camera
    Camera cam;
    cam.setProjectionAsPerspective(40.0, 0.05, 100.0);
    cam.setViewMatrix(axisMatrix);
    cam.setViewport(position.x(), position.y(), size.x(), size.y());

    // Setup viewport
    cam.viewport()->applyOpenGL(oglContext, Viewport::CLEAR_DEPTH);
    cam.applyOpenGL();


    // Do the actual rendering
    // -----------------------------------------------
    MatrixState matrixState(cam);
    if (software)
    {
        renderAxisImmediateMode(oglContext, matrixState);
    }
    else
    {
        renderAxis(oglContext, matrixState);
    }

    renderCubeGeos(oglContext, software, matrixState);

    renderAxisLabels(oglContext, software, matrixState);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST(ModelBasicListTest, MergePartsWithTransformation)
{
    Vec3fArray* verts = new Vec3fArray;
    verts->reserve(3);
    verts->add(Vec3f(0, 0, 0));
    verts->add(Vec3f(1, 0, 0));
    verts->add(Vec3f(1, 1, 0));

    Vec3fArray* norms = new Vec3fArray;
    norms->resize(3);
    norms->set(0, Vec3f::Z_AXIS);
    norms->set(1, Vec3f::Z_AXIS);
    norms->set(2, Vec3f::Z_AXIS);

    DrawableGeo* myGeo = new DrawableGeo;
    myGeo->setFromTriangleVertexArray(verts);
    myGeo->setNormalArray(norms);

    Part* myPart = new Part;
    myPart->setDrawable(myGeo);

    Part* myPart2 = new Part;
    myPart2->setDrawable(myGeo);

    ref<ModelBasicList> myModel = new ModelBasicList;
    myModel->addPart(myPart);
    myModel->addPart(myPart2);
    EXPECT_EQ(2, myModel->partCount());

    Mat4d matrix;
    matrix.setTranslation(Vec3d(10, 20, 30));
    Transform* transform = new Transform;
    transform->setLocalTransform(matrix);
    myPart2->setTransform(transform);


    myModel->mergeParts(1000, 1000);
    EXPECT_EQ(1, myModel->partCount());

    Part* mergedPart = myModel->part(0);
    DrawableGeo* mergedGeo = dynamic_cast<DrawableGeo*>(mergedPart->drawable());
    const Vec3fArray* vertices = mergedGeo->vertexArray();
    EXPECT_EQ(6, vertices->size());

    Vec3f v5 = vertices->get(5);
    EXPECT_EQ(11, v5.x());
    EXPECT_EQ(21, v5.y());
    EXPECT_EQ(30, v5.z());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
TEST(ModelBasicListTest, MergePartsCheckBB)
{
    Vec3fArray* verts = new Vec3fArray;
    verts->reserve(3);
    verts->add(Vec3f(0, 0, 0));
    verts->add(Vec3f(1, 0, 0));
    verts->add(Vec3f(1, 1, 0));

    Vec3fArray* norms = new Vec3fArray;
    norms->resize(3);
    norms->set(0, Vec3f::Z_AXIS);
    norms->set(1, Vec3f::Z_AXIS);
    norms->set(2, Vec3f::Z_AXIS);

    DrawableGeo* myGeo = new DrawableGeo;
    myGeo->setFromTriangleVertexArray(verts);
    myGeo->setNormalArray(norms);


    ref<ModelBasicList> myModel = new ModelBasicList;

    {
        Part* myPart = new Part;
        myPart->setDrawable(myGeo);
        Mat4d matrix;
        matrix.setTranslation(Vec3d(10, 20, 30));
        Transform* transform = new Transform;
        transform->setLocalTransform(matrix);
        myPart->setTransform(transform);
        myModel->addPart(myPart);
    }

    {
        Part* myPart2 = new Part;
        myPart2->setDrawable(myGeo);
        Mat4d matrix;
        matrix.setTranslation(Vec3d(20, 20, 30));
        Transform* transform2 = new Transform;
        transform2->setLocalTransform(matrix);
        myPart2->setTransform(transform2);
        myModel->addPart(myPart2);
    }

    {
        Part* myPart3 = new Part;
        myPart3->setDrawable(myGeo);
        Mat4d matrix;
        matrix.setTranslation(Vec3d(100, 20, 30));
        Transform* transform3 = new Transform;
        transform3->setLocalTransform(matrix);
        myPart3->setTransform(transform3);
        myModel->addPart(myPart3);
    }

    {
        Part* myPart4 = new Part;
        myPart4->setDrawable(myGeo);
        Mat4d matrix;
        matrix.setTranslation(Vec3d(110, 20, 30));
        Transform* transform4 = new Transform;
        transform4->setLocalTransform(matrix);
        myPart4->setTransform(transform4);
        myModel->addPart(myPart4);
    }

    EXPECT_EQ(4, myModel->partCount());

    myModel->mergeParts(1, 1000);
    EXPECT_EQ(4, myModel->partCount());

    myModel->mergeParts(20, 1000);
    EXPECT_EQ(2, myModel->partCount());

    myModel->mergeParts(200, 1000);
    EXPECT_EQ(1, myModel->partCount());

}