/*
---------------------------------------------------------------------------
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 to generate face
* normals for all imported faces.
*/



// internal headers
#include "GenVertexNormalsProcess.h"
#include "ProcessHelper.h"
#include "Exceptional.h"
#include "qnan.h"

using namespace Assimp;

// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
GenVertexNormalsProcess::GenVertexNormalsProcess()
: configMaxAngle( AI_DEG_TO_RAD( 175.f ) ) {
    // empty
}

// ------------------------------------------------------------------------------------------------
// Destructor, private as well
GenVertexNormalsProcess::~GenVertexNormalsProcess() {
    // nothing to do here
}

// ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field.
bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
{
    return (pFlags & aiProcess_GenSmoothNormals) != 0;
}

// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
{
    // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property
    configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,(ai_real)175.0);
    configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,(ai_real)175.0),(ai_real)0.0));
}

// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void GenVertexNormalsProcess::Execute( aiScene* pScene)
{
    DefaultLogger::get()->debug("GenVertexNormalsProcess begin");

    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
        throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");

    bool bHas = false;
    for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
    {
        if(GenMeshVertexNormals( pScene->mMeshes[a],a))
            bHas = true;
    }

    if (bHas)   {
        DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
            "Vertex normals have been calculated");
    }
    else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
        "Normals are already there");
}

// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
{
    if (NULL != pMesh->mNormals)
        return false;

    // If the mesh consists of lines and/or points but not of
    // triangles or higher-order polygons the normal vectors
    // are undefined.
    if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
    {
        DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes");
        return false;
    }

    // Allocate the array to hold the output normals
    const float qnan = std::numeric_limits<ai_real>::quiet_NaN();
    pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];

    // Compute per-face normals but store them per-vertex
    for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
    {
        const aiFace& face = pMesh->mFaces[a];
        if (face.mNumIndices < 3)
        {
            // either a point or a line -> no normal vector
            for (unsigned int i = 0;i < face.mNumIndices;++i) {
                pMesh->mNormals[face.mIndices[i]] = aiVector3D(qnan);
            }

            continue;
        }

        const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
        const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
        const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
        const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));

        for (unsigned int i = 0;i < face.mNumIndices;++i) {
            pMesh->mNormals[face.mIndices[i]] = vNor;
        }
    }

    // Set up a SpatialSort to quickly find all vertices close to a given position
    // check whether we can reuse the SpatialSort of a previous step.
    SpatialSort* vertexFinder = NULL;
    SpatialSort  _vertexFinder;
    ai_real posEpsilon = ai_real( 1e-5 );
    if (shared) {
        std::vector<std::pair<SpatialSort,ai_real> >* avf;
        shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
        if (avf)
        {
            std::pair<SpatialSort,ai_real>& blubb = avf->operator [] (meshIndex);
            vertexFinder = &blubb.first;
            posEpsilon = blubb.second;
        }
    }
    if (!vertexFinder)  {
        _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
        vertexFinder = &_vertexFinder;
        posEpsilon = ComputePositionEpsilon(pMesh);
    }
    std::vector<unsigned int> verticesFound;
    aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices];

    if (configMaxAngle >= AI_DEG_TO_RAD( 175.f ))   {
        // There is no angle limit. Thus all vertices with positions close
        // to each other will receive the same vertex normal. This allows us
        // to optimize the whole algorithm a little bit ...
        std::vector<bool> abHad(pMesh->mNumVertices,false);
        for (unsigned int i = 0; i < pMesh->mNumVertices;++i)   {
            if (abHad[i]) {
                continue;
            }

            // Get all vertices that share this one ...
            vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound);

            aiVector3D pcNor;
            for (unsigned int a = 0; a < verticesFound.size(); ++a) {
                const aiVector3D& v = pMesh->mNormals[verticesFound[a]];
                if (is_not_qnan(v.x))pcNor += v;
            }
            pcNor.NormalizeSafe();

            // Write the smoothed normal back to all affected normals
            for (unsigned int a = 0; a < verticesFound.size(); ++a)
            {
                unsigned int vidx = verticesFound[a];
                pcNew[vidx] = pcNor;
                abHad[vidx] = true;
            }
        }
    }
    // Slower code path if a smooth angle is set. There are many ways to achieve
    // the effect, this one is the most straightforward one.
    else    {
        const ai_real fLimit = std::cos(configMaxAngle);
        for (unsigned int i = 0; i < pMesh->mNumVertices;++i)   {
            // Get all vertices that share this one ...
            vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);

            aiVector3D vr = pMesh->mNormals[i];
            ai_real vrlen = vr.Length();

            aiVector3D pcNor;
            for (unsigned int a = 0; a < verticesFound.size(); ++a) {
                aiVector3D v = pMesh->mNormals[verticesFound[a]];

                // check whether the angle between the two normals is not too large
                // HACK: if v.x is qnan the dot product will become qnan, too
                //   therefore the comparison against fLimit should be false
                //   in every case.
                if (v * vr >= fLimit * vrlen * v.Length())
                    pcNor += v;
            }
            pcNew[i] = pcNor.NormalizeSafe();
        }
    }

    delete[] pMesh->mNormals;
    pMesh->mNormals = pcNew;

    return true;
}
