/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------

Copyright (c) 2006-2017, assimp team


All rights reserved.

Redistribution and use of this software 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 the assimp team, nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission of the assimp team.

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.
---------------------------------------------------------------------------
*/
/** @file Implementation of the post processing step "MakeVerboseFormat"
*/


#include "MakeVerboseFormat.h"
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>

using namespace Assimp;

// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::MakeVerboseFormatProcess()
{
    // nothing to do here
}
// ------------------------------------------------------------------------------------------------
MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
{
    // nothing to do here
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MakeVerboseFormatProcess::Execute( aiScene* pScene)
{
    ai_assert(NULL != pScene);
    DefaultLogger::get()->debug("MakeVerboseFormatProcess begin");

    bool bHas = false;
    for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
    {
        if( MakeVerboseFormat( pScene->mMeshes[a]))
            bHas = true;
    }
    if (bHas) DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ...");
    else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");

    pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;

}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
{
    ai_assert(NULL != pcMesh);

    unsigned int iOldNumVertices = pcMesh->mNumVertices;
    const unsigned int iNumVerts = pcMesh->mNumFaces*3;

    aiVector3D* pvPositions = new aiVector3D[ iNumVerts ];

    aiVector3D* pvNormals = NULL;
    if (pcMesh->HasNormals())
    {
        pvNormals = new aiVector3D[iNumVerts];
    }
    aiVector3D* pvTangents = NULL, *pvBitangents = NULL;
    if (pcMesh->HasTangentsAndBitangents())
    {
        pvTangents = new aiVector3D[iNumVerts];
        pvBitangents = new aiVector3D[iNumVerts];
    }

    aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {0};
    aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {0};

    unsigned int p = 0;
    while (pcMesh->HasTextureCoords(p))
        apvTextureCoords[p++] = new aiVector3D[iNumVerts];

    p = 0;
    while (pcMesh->HasVertexColors(p))
        apvColorSets[p++] = new aiColor4D[iNumVerts];

    // allocate enough memory to hold output bones and vertex weights ...
    std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones];
    for (unsigned int i = 0;i < pcMesh->mNumBones;++i) {
        newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3);
    }

    // iterate through all faces and build a clean list
    unsigned int iIndex = 0;
    for (unsigned int a = 0; a< pcMesh->mNumFaces;++a)
    {
        aiFace* pcFace = &pcMesh->mFaces[a];
        for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex)
        {
            // need to build a clean list of bones, too
            for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
            {
                for (unsigned int a = 0;  a < pcMesh->mBones[i]->mNumWeights;a++)
                {
                    const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a];
                    if(pcFace->mIndices[q] == w.mVertexId)
                    {
                        aiVertexWeight wNew;
                        wNew.mVertexId = iIndex;
                        wNew.mWeight = w.mWeight;
                        newWeights[i].push_back(wNew);
                    }
                }
            }

            pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]];

            if (pcMesh->HasNormals())
            {
                pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]];
            }
            if (pcMesh->HasTangentsAndBitangents())
            {
                pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]];
                pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]];
            }

            unsigned int p = 0;
            while (pcMesh->HasTextureCoords(p))
            {
                apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]];
                ++p;
            }
            p = 0;
            while (pcMesh->HasVertexColors(p))
            {
                apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]];
                ++p;
            }
            pcFace->mIndices[q] = iIndex;
        }
    }



    // build output vertex weights
    for (unsigned int i = 0;i < pcMesh->mNumBones;++i)
    {
        delete [] pcMesh->mBones[i]->mWeights;
        if (!newWeights[i].empty()) {
            pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()];
            aiVertexWeight *weightToCopy = &( newWeights[i][0] );
            memcpy(pcMesh->mBones[i]->mWeights, weightToCopy,
                sizeof(aiVertexWeight) * newWeights[i].size());
        } else {
            pcMesh->mBones[i]->mWeights = NULL;
        }
    }
    delete[] newWeights;

    // delete the old members
    delete[] pcMesh->mVertices;
    pcMesh->mVertices = pvPositions;

    p = 0;
    while (pcMesh->HasTextureCoords(p))
    {
        delete[] pcMesh->mTextureCoords[p];
        pcMesh->mTextureCoords[p] = apvTextureCoords[p];
        ++p;
    }
    p = 0;
    while (pcMesh->HasVertexColors(p))
    {
        delete[] pcMesh->mColors[p];
        pcMesh->mColors[p] = apvColorSets[p];
        ++p;
    }
    pcMesh->mNumVertices = iNumVerts;

    if (pcMesh->HasNormals())
    {
        delete[] pcMesh->mNormals;
        pcMesh->mNormals = pvNormals;
    }
    if (pcMesh->HasTangentsAndBitangents())
    {
        delete[] pcMesh->mTangents;
        pcMesh->mTangents = pvTangents;
        delete[] pcMesh->mBitangents;
        pcMesh->mBitangents = pvBitangents;
    }
    return (pcMesh->mNumVertices != iOldNumVertices);
}
