#include "UnitTestPCH.h"

#include <assimp/scene.h>
#include <JoinVerticesProcess.h>


using namespace std;
using namespace Assimp;

class JoinVerticesTest : public ::testing::Test
{
public:

    virtual void SetUp();
    virtual void TearDown();

protected:

    JoinVerticesProcess* piProcess;
    aiMesh* pcMesh;
};

// ------------------------------------------------------------------------------------------------
void JoinVerticesTest::SetUp()
{
    // construct the process
    piProcess = new JoinVerticesProcess();

    // create a quite small mesh for testing purposes -
    // the mesh itself is *something* but it has redundant vertices
    pcMesh = new aiMesh();

    pcMesh->mNumVertices = 900;
    aiVector3D*& pv = pcMesh->mVertices = new aiVector3D[900];
    for (unsigned int i = 0; i < 3;++i)
    {
        const unsigned int base = i*300;
        for (unsigned int a = 0; a < 300;++a)
        {
            pv[base+a].x = pv[base+a].y = pv[base+a].z = (float)a;
        }
    }

    // generate faces - each vertex is referenced once
    pcMesh->mNumFaces = 300;
    pcMesh->mFaces = new aiFace[300];
    for (unsigned int i = 0,p = 0; i < 300;++i)
    {
        aiFace& face = pcMesh->mFaces[i];
        face.mIndices = new unsigned int[ face.mNumIndices = 3 ];
        for (unsigned int a = 0; a < 3;++a)
            face.mIndices[a] = p++;
    }

    // generate extra members - set them to zero to make sure they're identical
    pcMesh->mTextureCoords[0] = new aiVector3D[900];
    for (unsigned int i = 0; i < 900;++i)pcMesh->mTextureCoords[0][i] = aiVector3D( 0.f );

    pcMesh->mNormals = new aiVector3D[900];
    for (unsigned int i = 0; i < 900;++i)pcMesh->mNormals[i] = aiVector3D( 0.f );

    pcMesh->mTangents = new aiVector3D[900];
    for (unsigned int i = 0; i < 900;++i)pcMesh->mTangents[i] = aiVector3D( 0.f );

    pcMesh->mBitangents = new aiVector3D[900];
    for (unsigned int i = 0; i < 900;++i)pcMesh->mBitangents[i] = aiVector3D( 0.f );
}

// ------------------------------------------------------------------------------------------------
void JoinVerticesTest::TearDown()
{
    delete this->pcMesh;
    delete this->piProcess;
}

// ------------------------------------------------------------------------------------------------
TEST_F(JoinVerticesTest, testProcess)
{
    // execute the step on the given data
    piProcess->ProcessMesh(pcMesh,0);

    // the number of faces shouldn't change
    ASSERT_EQ(300U, pcMesh->mNumFaces);
    ASSERT_EQ(300U, pcMesh->mNumVertices);

    ASSERT_TRUE(NULL != pcMesh->mNormals);
    ASSERT_TRUE(NULL != pcMesh->mTangents);
    ASSERT_TRUE(NULL != pcMesh->mBitangents);
    ASSERT_TRUE(NULL != pcMesh->mTextureCoords[0]);

    // the order doesn't care
    float fSum = 0.f;
    for (unsigned int i = 0; i < 300;++i)
    {
        aiVector3D& v = pcMesh->mVertices[i];
        fSum += v.x + v.y + v.z;

        EXPECT_FALSE(pcMesh->mNormals[i].x);
        EXPECT_FALSE(pcMesh->mTangents[i].x);
        EXPECT_FALSE(pcMesh->mBitangents[i].x);
        EXPECT_FALSE(pcMesh->mTextureCoords[0][i].x);
    }
    EXPECT_EQ(150.f*299.f*3.f, fSum); // gaussian sum equation
}