// Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto.  Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#include "OgnTestDeformerDatabase.h"
#include <omni/graph/core/CppWrappers.h>

#include <cmath>

namespace omni
{
namespace graph
{
namespace test
{

namespace
{

class PointComputeArgs
{
public:
    PointComputeArgs(const GfVec3f& inputPoint, float height, float width, float freq, GfVec3f& outputPoint)
        : m_inputPoint(inputPoint), m_height(height), m_width(width), m_freq(freq), m_outputPoint(outputPoint)
    {
    }

    const GfVec3f& m_inputPoint;
    float m_height;
    float m_width;
    float m_freq;
    GfVec3f& m_outputPoint;
};

}

// minimal compute node example that reads one float and writes one float
// e.g. out value = 3.0f * in value
class OgnTestDeformer
{
public:
    static bool compute(OgnTestDeformerDatabase& db)
    {
        const auto& points = db.inputs.points();
        const auto& multiplier = db.inputs.multiplier();
        const auto& wavelength = db.inputs.wavelength();
        auto& outputPoints = db.outputs.points();

        size_t numPoints = points.size();

        // If there are no points to deform then we can bail early
        if (numPoints == 0)
        {
            return true;
        }

        // allocate output data
        outputPoints.resize(numPoints);

        float width = wavelength;
        float height = 10.0f * multiplier;
        float freq = 10.0f;

        // compute deformation
        std::transform(points.begin(), points.end(), outputPoints.begin(), [=](const GfVec3f& point) -> GfVec3f {
            float tx = freq * (point[0] - width) / width;
            float ty = 1.5f * freq * (point[1] - width) / width;
            float z = point[2] + height * (sin(tx) + cos(ty));
            return { point[0], point[1], z };
        });

        return true;
    }
};

REGISTER_OGN_NODE()

} // namespace examples
} // namespace graph
} // namespace omni
