/******************************************************************************
 * Copyright 2023 NVIDIA Corporation. All rights reserved.
 *****************************************************************************/

// # RTC Kernel:
// ** Structured volume basic **

// # Summary:
// A simple volume kernel for structure volumes.
// It samples the volume scalar value for the current position and
// maps it to color through the colormap. This is very similar to what
// IndeX does by default when not Visual ELements are used.

NV_IDX_XAC_VERSION_1_0

// DON'T CHANGE THIS STRUCT !!!
// It maps the GUI parameters from the Custom Visual Element GUI to this kernel.
// floats maps {pfloat1, pfloat2, pfloat3, pfloat4} GUI Parameters.
// ints maps {pint1, pint2, pint3, pint4} GUI Parameters.
struct Custom_params
{
    float4 floats;  // floats array
    int4 ints;      // ints array
};

using namespace nv::index;
using namespace nv::index::xac;

class Volume_sample_program
{
    NV_IDX_VOLUME_SAMPLE_PROGRAM

    const Custom_params*  m_custom_params;

public:
    NV_IDX_DEVICE_INLINE_MEMBER
    void initialize()
    {
        // maps Custom Visual Element GUI parameters to this kernel.
        m_custom_params = state.bind_parameter_buffer<Custom_params>(0);
    }

    NV_IDX_DEVICE_INLINE_MEMBER
    int execute(
        const Sample_info_self&  sample_info,
              Sample_output&     sample_output)
    {
        // get current sample position
        const float3& sample_position = sample_info.sample_position_object_space;
        const auto& sample_context = sample_info.sample_context;

        // get reference to the sparse volume
        const auto& sparse_volume = state.self;

        // generate a volume sampler and lookup sample a the current position
        const uint field_index = 0u;
        const auto sampler = sparse_volume.generate_sampler<float,
                                                         Volume_filter_mode::TRILINEAR,
                                                         Volume_classification_mode::POST_INTERPOLATION>(
                                                         field_index,
                                                         sample_context);

        const float sample_value = sampler.fetch_sample(sample_position);

        // Map sample to color
        const Colormap colormap = sparse_volume.get_colormap();
        const float4 sample_color = colormap.lookup(sample_value);

        // store the output color
        sample_output.set_color(sample_color);

        return NV_IDX_PROG_OK;
    }
}; // class Volume_sample_program
