/*
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 GenUVCoords step */


#include "ComputeUVMappingProcess.h"
#include "ProcessHelper.h"
#include "Exceptional.h"

using namespace Assimp;

namespace {

    const static aiVector3D base_axis_y(0.0,1.0,0.0);
    const static aiVector3D base_axis_x(1.0,0.0,0.0);
    const static aiVector3D base_axis_z(0.0,0.0,1.0);
    const static ai_real angle_epsilon = ai_real( 0.95 );
}

// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
ComputeUVMappingProcess::ComputeUVMappingProcess()
{
    // nothing to do here
}

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

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

// ------------------------------------------------------------------------------------------------
// Check whether a ray intersects a plane and find the intersection point
inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
    const aiVector3D& planeNormal, aiVector3D& pos)
{
    const ai_real b = planeNormal * (planePos - ray.pos);
    ai_real h = ray.dir * planeNormal;
    if ((h < 10e-5 && h > -10e-5) || (h = b/h) < 0)
        return false;

    pos = ray.pos + (ray.dir * h);
    return true;
}

// ------------------------------------------------------------------------------------------------
// Find the first empty UV channel in a mesh
inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
{
    for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
        if (!mesh->mTextureCoords[m])return m;

    DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
    return UINT_MAX;
}

// ------------------------------------------------------------------------------------------------
// Try to remove UV seams
void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
{
    // TODO: just a very rough algorithm. I think it could be done
    // much easier, but I don't know how and am currently too tired to
    // to think about a better solution.

    const static ai_real LOWER_LIMIT = ai_real( 0.1 );
    const static ai_real UPPER_LIMIT = ai_real( 0.9 );

    const static ai_real LOWER_EPSILON = ai_real( 10e-3 );
    const static ai_real UPPER_EPSILON = ai_real( 1.0-10e-3 );

    for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
    {
        const aiFace& face = mesh->mFaces[fidx];
        if (face.mNumIndices < 3) continue; // triangles and polygons only, please

        unsigned int small = face.mNumIndices, large = small;
        bool zero = false, one = false, round_to_zero = false;

        // Check whether this face lies on a UV seam. We can just guess,
        // but the assumption that a face with at least one very small
        // on the one side and one very large U coord on the other side
        // lies on a UV seam should work for most cases.
        for (unsigned int n = 0; n < face.mNumIndices;++n)
        {
            if (out[face.mIndices[n]].x < LOWER_LIMIT)
            {
                small = n;

                // If we have a U value very close to 0 we can't
                // round the others to 0, too.
                if (out[face.mIndices[n]].x <= LOWER_EPSILON)
                    zero = true;
                else round_to_zero = true;
            }
            if (out[face.mIndices[n]].x > UPPER_LIMIT)
            {
                large = n;

                // If we have a U value very close to 1 we can't
                // round the others to 1, too.
                if (out[face.mIndices[n]].x >= UPPER_EPSILON)
                    one = true;
            }
        }
        if (small != face.mNumIndices && large != face.mNumIndices)
        {
            for (unsigned int n = 0; n < face.mNumIndices;++n)
            {
                // If the u value is over the upper limit and no other u
                // value of that face is 0, round it to 0
                if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
                    out[face.mIndices[n]].x = 0.0;

                // If the u value is below the lower limit and no other u
                // value of that face is 1, round it to 1
                else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
                    out[face.mIndices[n]].x = 1.0;

                // The face contains both 0 and 1 as UV coords. This can occur
                // for faces which have an edge that lies directly on the seam.
                // Due to numerical inaccuracies one U coord becomes 0, the
                // other 1. But we do still have a third UV coord to determine
                // to which side we must round to.
                else if (one && zero)
                {
                    if (round_to_zero && out[face.mIndices[n]].x >=  UPPER_EPSILON)
                        out[face.mIndices[n]].x = 0.0;
                    else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
                        out[face.mIndices[n]].x = 1.0;
                }
            }
        }
    }
}

// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
    aiVector3D center, min, max;
    FindMeshCenter(mesh, center, min, max);

    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
    // currently the mapping axis will always be one of x,y,z, except if the
    // PretransformVertices step is used (it transforms the meshes into worldspace,
    // thus changing the mapping axis)
    if (axis * base_axis_x >= angle_epsilon)    {

        // For each point get a normalized projection vector in the sphere,
        // get its longitude and latitude and map them to their respective
        // UV axes. Problems occur around the poles ... unsolvable.
        //
        // The spherical coordinate system looks like this:
        // x = cos(lon)*cos(lat)
        // y = sin(lon)*cos(lat)
        // z = sin(lat)
        //
        // Thus we can derive:
        // lat  = arcsin (z)
        // lon  = arctan (y/x)
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
            out[pnt] = aiVector3D((std::atan2(diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
                (std::asin  (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
        }
    }
    else if (axis * base_axis_y >= angle_epsilon)   {
        // ... just the same again
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
            out[pnt] = aiVector3D((std::atan2(diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
                (std::asin  (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
        }
    }
    else if (axis * base_axis_z >= angle_epsilon)   {
        // ... just the same again
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
            out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
                (std::asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
        }
    }
    // slower code path in case the mapping axis is not one of the coordinate system axes
    else    {
        aiMatrix4x4 mTrafo;
        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);

        // again the same, except we're applying a transformation now
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
            out[pnt] = aiVector3D((std::atan2(diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
                (std::asin(diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.0);
        }
    }


    // Now find and remove UV seams. A seam occurs if a face has a tcoord
    // close to zero on the one side, and a tcoord close to one on the
    // other side.
    RemoveUVSeams(mesh,out);
}

// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
    aiVector3D center, min, max;

    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
    // currently the mapping axis will always be one of x,y,z, except if the
    // PretransformVertices step is used (it transforms the meshes into worldspace,
    // thus changing the mapping axis)
    if (axis * base_axis_x >= angle_epsilon)    {
        FindMeshCenter(mesh, center, min, max);
        const ai_real diff = max.x - min.x;

        // If the main axis is 'z', the z coordinate of a point 'p' is mapped
        // directly to the texture V axis. The other axis is derived from
        // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
        // 'c' is the center point of the mesh.
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D& pos = mesh->mVertices[pnt];
            aiVector3D& uv  = out[pnt];

            uv.y = (pos.x - min.x) / diff;
            uv.x = (std::atan2( pos.z - center.z, pos.y - center.y) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
        }
    }
    else if (axis * base_axis_y >= angle_epsilon)   {
        FindMeshCenter(mesh, center, min, max);
        const ai_real diff = max.y - min.y;

        // just the same ...
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D& pos = mesh->mVertices[pnt];
            aiVector3D& uv  = out[pnt];

            uv.y = (pos.y - min.y) / diff;
            uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
        }
    }
    else if (axis * base_axis_z >= angle_epsilon)   {
        FindMeshCenter(mesh, center, min, max);
        const ai_real diff = max.z - min.z;

        // just the same ...
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D& pos = mesh->mVertices[pnt];
            aiVector3D& uv  = out[pnt];

            uv.y = (pos.z - min.z) / diff;
            uv.x = (std::atan2( pos.y - center.y, pos.x - center.x) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
        }
    }
    // slower code path in case the mapping axis is not one of the coordinate system axes
    else {
        aiMatrix4x4 mTrafo;
        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
        FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
        const ai_real diff = max.y - min.y;

        // again the same, except we're applying a transformation now
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
            const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
            aiVector3D& uv  = out[pnt];

            uv.y = (pos.y - min.y) / diff;
            uv.x = (std::atan2( pos.x - center.x, pos.z - center.z) +(ai_real)AI_MATH_PI ) / (ai_real)AI_MATH_TWO_PI;
        }
    }

    // Now find and remove UV seams. A seam occurs if a face has a tcoord
    // close to zero on the one side, and a tcoord close to one on the
    // other side.
    RemoveUVSeams(mesh,out);
}

// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{
    ai_real diffu,diffv;
    aiVector3D center, min, max;

    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
    // currently the mapping axis will always be one of x,y,z, except if the
    // PretransformVertices step is used (it transforms the meshes into worldspace,
    // thus changing the mapping axis)
    if (axis * base_axis_x >= angle_epsilon)    {
        FindMeshCenter(mesh, center, min, max);
        diffu = max.z - min.z;
        diffv = max.y - min.y;

        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D& pos = mesh->mVertices[pnt];
            out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.0);
        }
    }
    else if (axis * base_axis_y >= angle_epsilon)   {
        FindMeshCenter(mesh, center, min, max);
        diffu = max.x - min.x;
        diffv = max.z - min.z;

        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D& pos = mesh->mVertices[pnt];
            out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
        }
    }
    else if (axis * base_axis_z >= angle_epsilon)   {
        FindMeshCenter(mesh, center, min, max);
        diffu = max.y - min.y;
        diffv = max.z - min.z;

        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D& pos = mesh->mVertices[pnt];
            out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.0);
        }
    }
    // slower code path in case the mapping axis is not one of the coordinate system axes
    else
    {
        aiMatrix4x4 mTrafo;
        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
        FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
        diffu = max.x - min.x;
        diffv = max.z - min.z;

        // again the same, except we're applying a transformation now
        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
            const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
            out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.0);
        }
    }

    // shouldn't be necessary to remove UV seams ...
}

// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
{
    DefaultLogger::get()->error("Mapping type currently not implemented");
}

// ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::Execute( aiScene* pScene)
{
    DefaultLogger::get()->debug("GenUVCoordsProcess begin");
    char buffer[1024];

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

    std::list<MappingInfo> mappingStack;

    /*  Iterate through all materials and search for non-UV mapped textures
     */
    for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
    {
        mappingStack.clear();
        aiMaterial* mat = pScene->mMaterials[i];
        for (unsigned int a = 0; a < mat->mNumProperties;++a)
        {
            aiMaterialProperty* prop = mat->mProperties[a];
            if (!::strcmp( prop->mKey.data, "$tex.mapping"))
            {
                aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
                if (aiTextureMapping_UV != mapping)
                {
                    if (!DefaultLogger::isNullLogger())
                    {
                        ai_snprintf(buffer, 1024, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
                            TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
                            MappingTypeToString(mapping));

                        DefaultLogger::get()->info(buffer);
                    }

                    if (aiTextureMapping_OTHER == mapping)
                        continue;

                    MappingInfo info (mapping);

                    // Get further properties - currently only the major axis
                    for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
                    {
                        aiMaterialProperty* prop2 = mat->mProperties[a2];
                        if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
                            continue;

                        if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis"))  {
                            info.axis = *((aiVector3D*)prop2->mData);
                            break;
                        }
                    }

                    unsigned int idx( 99999999 );

                    // Check whether we have this mapping mode already
                    std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
                    if (mappingStack.end() != it)
                    {
                        idx = (*it).uv;
                    }
                    else
                    {
                        /*  We have found a non-UV mapped texture. Now
                        *   we need to find all meshes using this material
                        *   that we can compute UV channels for them.
                        */
                        for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
                        {
                            aiMesh* mesh = pScene->mMeshes[m];
                            unsigned int outIdx = 0;
                            if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
                                !mesh->mNumVertices)
                            {
                                continue;
                            }

                            // Allocate output storage
                            aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];

                            switch (mapping)
                            {
                            case aiTextureMapping_SPHERE:
                                ComputeSphereMapping(mesh,info.axis,p);
                                break;
                            case aiTextureMapping_CYLINDER:
                                ComputeCylinderMapping(mesh,info.axis,p);
                                break;
                            case aiTextureMapping_PLANE:
                                ComputePlaneMapping(mesh,info.axis,p);
                                break;
                            case aiTextureMapping_BOX:
                                ComputeBoxMapping(mesh,p);
                                break;
                            default:
                                ai_assert(false);
                            }
                            if (m && idx != outIdx)
                            {
                                DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
                                    "this material have equal numbers of UV channels. The UV index stored in  "
                                    "the material structure does therefore not apply for all meshes. ");
                            }
                            idx = outIdx;
                        }
                        info.uv = idx;
                        mappingStack.push_back(info);
                    }

                    // Update the material property list
                    mapping = aiTextureMapping_UV;
                    ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
                }
            }
        }
    }
    DefaultLogger::get()->debug("GenUVCoordsProcess finished");
}
