//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
TEST(ArrayTest, CopyConvertedData)
{
    // Double array to float
    {
        DoubleArray ad;
        ad.resize(4);
        ad[0] = 0.0;
        ad[1] = 1.0;
        ad[2] = 2.0;
        ad[3] = 3.0;

        // Copy full array
        FloatArray af;
        af.resize(4);
        af.copyConvertedData(ad, 4, 0, 0);
        EXPECT_FLOAT_EQ(0.0f, af[0]);
        EXPECT_FLOAT_EQ(1.0f, af[1]);
        EXPECT_FLOAT_EQ(2.0f, af[2]);
        EXPECT_FLOAT_EQ(3.0f, af[3]);

        // Copy partial array to float array
        af.resize(2);
        af.setAll(0);
        af.copyConvertedData(ad, 2, 0, 1);

        EXPECT_FLOAT_EQ(1.0f, af[0]);
        EXPECT_FLOAT_EQ(2.0f, af[1]);
    }

    // Vec3d to Vec3f and Vec3i
    {
        Vec3dArray ad;
        ad.resize(2);
        ad[0].set(1.1, 2.5, 3.9);
        ad[1].set(11.1, 12.5, 13.9);

        Vec3fArray af;
        af.resize(2);
        af.copyConvertedData(ad, 2, 0, 0);
        EXPECT_FLOAT_EQ(1.1f,  af[0].x());
        EXPECT_FLOAT_EQ(2.5f,  af[0].y());
        EXPECT_FLOAT_EQ(3.9f,  af[0].z());
        EXPECT_FLOAT_EQ(11.1f, af[1].x());
        EXPECT_FLOAT_EQ(12.5f, af[1].y());
        EXPECT_FLOAT_EQ(13.9f, af[1].z());

        Array<Vec3i> ai;
        ai.resize(2);
        ai.copyConvertedData(ad, 2, 0, 0);
        EXPECT_EQ(1,  ai[0].x());
        EXPECT_EQ(2,  ai[0].y());
        EXPECT_EQ(3,  ai[0].z());
        EXPECT_EQ(11, ai[1].x());
        EXPECT_EQ(12, ai[1].y());
        EXPECT_EQ(13, ai[1].z());
    }
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void GeometryBuilder::addTriangleByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2)
{
    Vec3fArray verts;
    verts.resize(3);
    verts[0] = v0;
    verts[1] = v1;
    verts[2] = v2;

    uint firstVertexIdx = addVertices(verts);

    addTriangle(firstVertexIdx, firstVertexIdx + 1, firstVertexIdx + 2);
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void GeometryBuilder::addQuadByVertices(const Vec3f& v0, const Vec3f& v1, const Vec3f& v2, const Vec3f& v3)
{
    Vec3fArray verts;
    verts.resize(4);
    verts[0] = v0;
    verts[1] = v1;
    verts[2] = v2;
    verts[3] = v3;

    uint firstVertexIdx = addVertices(verts);

    addQuad(firstVertexIdx, firstVertexIdx + 1, firstVertexIdx + 2, firstVertexIdx + 3);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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, MergeParts)
{
    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());

    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(1, v5.x());
    EXPECT_EQ(1, v5.y());
    EXPECT_EQ(0, v5.z());
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
TEST(ArrayTest, ptrToIdx)
{
    // Vec3f array
    Vec3fArray vA;
    vA.resize(4);
    ASSERT_EQ(4u, vA.size());

    vA[0] = Vec3f(1,2,3);
    vA[1] = Vec3f(1.1f, 2.2f, 3.3f);
    vA[2] = Vec3f(0,0,0);
    vA[3] = Vec3f(4,5,6);

    Vec3f* p1 = vA.ptr(1);
    ASSERT_FLOAT_EQ(1.1f, p1->x());
    ASSERT_FLOAT_EQ(2.2f, p1->y());
    ASSERT_FLOAT_EQ(3.3f, p1->z());

    Vec3f* p3 = vA.ptr(3);
    ASSERT_FLOAT_EQ(4, p3->x());
    ASSERT_FLOAT_EQ(5, p3->y());
    ASSERT_FLOAT_EQ(6, p3->z());
}
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
TEST(ArrayTest, BasicVec3fArray)
{
    // Vec3f array
    Vec3fArray vA;
    vA.resize(4);
    ASSERT_EQ(4u, vA.size());

    vA[0] = Vec3f(1,2,3);
    vA[1] = Vec3f(1.1f, 2.2f, 3.3f);
    vA[2] = Vec3f(0,0,0);
    vA[3] = Vec3f(4,5,6);

    ASSERT_EQ(true, vA[0] == Vec3f(1, 2, 3));
    ASSERT_EQ(true, vA[1] == Vec3f(1.1f, 2.2f, 3.3f));
    ASSERT_EQ(true, vA[2] == Vec3f(0, 0, 0));
    ASSERT_EQ(true, vA[3] == Vec3f(4, 5, 6));

    const float* pf = vA.ptr()->ptr();

    ASSERT_FLOAT_EQ(1.0f, pf[0]);
    ASSERT_FLOAT_EQ(2.0f, pf[1]);
    ASSERT_FLOAT_EQ(3.0f, pf[2]);
    ASSERT_FLOAT_EQ(1.1f, pf[3]);
    ASSERT_FLOAT_EQ(2.2f, pf[4]);
    ASSERT_FLOAT_EQ(3.3f, pf[5]);
    ASSERT_FLOAT_EQ(0.0f, pf[6]);
    ASSERT_FLOAT_EQ(0.0f, pf[7]);
    ASSERT_FLOAT_EQ(0.0f, pf[8]);
    ASSERT_FLOAT_EQ(4.0f, pf[9]);
    ASSERT_FLOAT_EQ(5.0f, pf[10]);
    ASSERT_FLOAT_EQ(6.0f, pf[11]);

    vA.clear();

    ASSERT_EQ(0u, vA.size());
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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());

}