/******************************************************************************
 * Copyright 2023 NVIDIA Corporation. All rights reserved.
 *****************************************************************************/
/// \file
/// \brief Results exposed by the NVIDIA IndeX library when querying a scene's contents.

#ifndef NVIDIA_INDEX_ISCENE_QUERY_RESULTS_H
#define NVIDIA_INDEX_ISCENE_QUERY_RESULTS_H

#include <mi/base/interface_declare.h>
#include <mi/base/types.h>
#include <mi/base/uuid.h>
#include <mi/math/color.h>
#include <mi/math/matrix.h>
#include <mi/math/vector.h>
#include <mi/dice.h>

#include <nv/index/idata_sample.h>

namespace nv
{
namespace index
{

/// Describes a path through the scene description to identify a
/// specific instance of a scene element.
///
/// Since most types of scene elements may be referenced multiple
/// times in the scene, the element's tag is not sufficient to
/// address a specific instance. This interface defines a path
/// through the scene description to a chosen scene element
/// instance, traversing from the scene root through all other
/// ancestors to the actual instance.
///
/// \ingroup nv_scene_queries
///
class IScene_path :
    public mi::base::Interface_declare<0xce092e73,0x46c6,0x492f,0x87,0x9b,0x6e,0x14,0x23,0x07,0x33,0x26>
{
public:
    /// Returns the number of nodes in the path from the scene root
    /// to the chosen scene element instance.
    ///
    /// \return     The number of nodes in the path, including
    ///             the chosen element and the scene root.
    virtual mi::Uint32 get_length() const = 0;

    /// Returns a node in the path from the scene root to the
    /// chosen scene element instance.
    ///
    /// The first node of the path is the scene root, i.e. an \c
    /// IScene, followed by other ancestors, with the last node
    /// being the chosen scene element instance.
    ///
    /// The path can be used to distinguish multiple instances of
    /// the same scene element, i.e. when the same scene element is
    /// referenced by multiple scene groups. Since all instances use
    /// the same tag, it is necessary to look at the path to
    /// determine which instance was meant.
    ///
    /// \param[in] index    Selects the node in the path, must be in the
    ///                     range [0, get_length() - 1].
    /// \return             Tag of the selected node
    virtual mi::neuraylib::Tag_struct get_node(mi::Uint32 index) const = 0;
};

/// Interface class that returns the result of a pick operation.
/// The interface class represents a single scene query result generated by a mouse over
/// operation (a.k.a. 'pick' operation), i.e., by a ray starting from the scene's camera
/// position cast through the scene.
///
/// Each query result gives information about the scene element hit by the ray. This
/// information includes, for instance, the scene element's \c tag to clearly identify it
/// and the intersection point in the scene element's IJK space.
///
/// \ingroup nv_scene_queries
///
class IScene_pick_result :
    public mi::base::Interface_declare<0x0e201838,0xf0e5,0x41f7,0xa4,0xe0,0xfc,0x02,0x43,0xe6,0x06,0xce>
{
public:
    /// Represents the interface class of the intersection info result.
    /// Typically, an intersection result including its intersection information are
    /// highly dependent on the intersected shape class. For instance, intersecting
    /// (1) a line segments part of a set of line segments should return the index that
    /// that line segment in the line set, or intersecting (2) a triangular mesh should
    /// expose not only the index of the intersected triangle but also the adjacent vertices
    /// and possibly the according per-vertex attributes.
    /// The intersection result interfaces class \c IScene_pick_result provides just
    /// very basic intersection information such as the \c tag of the intersected shape,
    /// the intersection point in local space, and distance from the camera position in world space.
    /// Additional shape-specific intersection information are supposed to be provided
    /// derived (interface) classes. The UUID returned by \c get_intersection_info_class provides
    /// the application with the necessary interface class id required for proper casting the
    /// general intersection information interface class to the shape-specific intersection
    /// information interface class if additional shape-specific details for the intersection are
    /// required.
    ///
    /// \return     Unique UUID of the shape-specific intersection result interface class.
    ///             By default, the UUID refers to this default intersection info interface.
    ///
    virtual mi::base::Uuid get_intersection_info_class() const = 0;

    /// Returns the intersected scene element's tag.
    /// Each scene element is clearly defined by its unique tag. Thus, the tag
    /// returned by the query result unambiguously defines which scene element
    /// has been hit by the cast ray.
    /// \return     The tag of the hit scene element. The returned
    ///             tag shall be always valid.
    ///
    virtual mi::neuraylib::Tag_struct get_scene_element() const = 0;

    /// Returns the sub index that specifies which of the sub elements was hit, if any.
    /// Some scene elements such as point geometry consist of multiple sub elements (i.e. individual
    /// points).
    ///
    /// \deprecated Use the methods provided by specializations of
    ///             this class, e.g. \c IPoint_set_pick_result.
    ///
    /// \return     The index of the hit sub element, or -1 if the scene element has not sub elements.
    ///
    virtual mi::Sint32 get_scene_element_sub_index() const = 0;

    /// The hit point of the ray with the scene element may be
    /// associated with a regular volume sample value. For instance,
    /// a plane may visualize the voxel data values that the plane
    /// passes through. The ray-plane intersection then determines
    /// the regular voxel value of the dataset at the very position.
    /// Similarly, the data value of a heightfield surface that is
    /// textured based on the data values of an associated regular
    /// volume can also be determined.
    ///
    /// \return     Interface pointer to an \c IData_volume_sample instance representing,
    ///             for example, a regular volume sample value related to the ray-element
    ///             intersection. If the intersection is not related to any data value,
    ///             then the returned pointer is 0.
    ///
    virtual const IData_sample* get_data_sample() const = 0;

    /// The hit point of the ray with the scene element may be associated
    /// with a color value. For instance, a heightfield surface is typically rendered
    /// using a solid color that will be returned. In case of a slice scene element
    /// the ray-slice intersection determines a color value based on the
    /// voxel value and the colormap associated to the slice.
    ///
    /// \return     The color at the intersection point.
    ///
    virtual const mi::math::Color_struct& get_color() const = 0;

    /// Returns the intersection between the scene element and the ray.
    /// The intersection between the scene element and the ray cast from the
    /// camera through the scene is given as a 3D point in the IJK space
    /// of the scene element.
    ///
    /// \return     The intersection between the scene element and
    ///             the ray cast from the camera in IJK space.
    ///
    virtual const mi::math::Vector_struct<mi::Float32, 3>& get_intersection() const = 0;

    /// Returns the distance of the intersection from the camera position.
    /// The distance from the camera's eye position to the intersection between
    /// the scene element and the cast ray.
    ///
    /// \return     The distance of the intersection point to the
    ///             camera position in XYZ space.
    ///
    virtual mi::Float32 get_distance() const = 0;

    /// Returns the transformation matrix of the intersected scene
    /// element. This is the transformation that needs to be applied
    /// to the intersection point (as returned by \c
    /// get_intersection()) to transform from IJK to XYZ space.
    ///
    /// \note The name of this method is subject to change!
    ///
    /// \return     Transformation matrix.
    virtual const mi::math::Matrix_struct<mi::Float32, 4, 4>& get_transform() const = 0;

    /// Returns the scene path from the scene root to the
    /// intersected scene element.
    ///
    /// \note Use the \c mi::base::Handle template to store the returned interface pointer in order
    ///       to guarantee the correct destruction of the returned interface.
    ///
    /// \return     Scene path to intersected scene element.
    virtual const IScene_path* get_scene_path() const = 0;
};

/// Interface class that returns all results of a pick operation in front-to-back order.
/// The interface class enables accessing all scene query result generated by a mouse over
/// operation (cf. \c IScene_pick_result). The mouse over operation computes all intersections
/// of the cast ray with the scene elements and all query results are sorted in front to
/// depth order in accordance to the camera position.
///
/// \ingroup nv_scene_queries
///
class IScene_pick_results :
    public mi::base::Interface_declare<0xe39d04d8,0x1176,0x44c5,0xb0,0xc9,0xd3,0xff,0xf5,0x79,0x04,0xba>
{
public:
    /// Returns the number of intersections between the scene elements in the
    /// scene and the cast ray.
    ///
    /// \return     The number of query results. If the cast ray hasn't hit any
    ///             scene element in the scene then 0 is returned.
    virtual mi::Uint32 get_nb_results() const = 0;

    /// Returns a single pick result determined by the given index
    /// that corresponds to the depth ordering.
    ///
    /// \param[in] index    The index enables indexing the query results in
    ///                     depth sorted order. That is, the
    ///                     index 0 accesses the front most query result
    ///                     and the index [0, get_nb_results()-1] accesses
    ///                     the back most query result.
    /// \return             The query result associated with the index value.
    virtual IScene_pick_result* get_result(mi::Uint32 index) const = 0;

    /// Returns which viewport the pick results come from. The
    /// returned value is the index in the \c IViewport_list that
    /// was passed to \c IIndex_scene_query::pick().
    ///
    /// \return index into the list, will be 0 if only a single viewport is used.
    virtual mi::Size get_viewport_index() const = 0;
};

/// Defines a list of pick results. Each of these pick results
/// can store multiple intersections.
///
class IScene_pick_results_list :
        public mi::base::Interface_declare<0x7e0c9571,0xf362,0x4f78,0x88,0x2f,0x12,0x88,0x71,0xa7,0xa7,0x61>
{
public:
    /// Returns the number of pick results in this list.
    ///
    /// \return number of pick results
    virtual mi::Size size() const = 0;

    /// Returns the pick results at the given position in the list.
    ///
    /// \param[in] index Position in the list.
    /// \return selected Pick results, or 0 when \c index is invalid.
    virtual nv::index::IScene_pick_results* get(mi::Size index) const = 0;
};

/// Interface class that returns the result of a entry lookup operation.
/// The interface class represents a single scene query result generated by a mouse over
/// operation (a.k.a. 'pick' operation), i.e., by a ray starting from the scene's camera
/// position cast through the scene.
///
/// Each query result gives information about the scene element hit by the ray. This
/// information includes, for instance, the scene element's \c tag to clearly identify it
/// and the intersection point in the scene element's IJK space.
///
/// \ingroup nv_scene_queries
///
class IScene_lookup_result :
    public mi::base::Interface_declare<0x8832eb30,0x1c5e,0x4ab8,0x90,0x77,0xca,0x62,0x07,0xdb,0x3c,0x5c>
{
public:
    /// Represents the interface class of the entry lookup result.
    /// The entry lookup results usually dependent on the scene element class.
    /// For instance, the lookup of an entry of a triangle mesh returns a single
    /// triangle including its per-vertex information such as the vertices, normals,
    /// colors, etc.
    /// The lookup result interfaces class \c IScene_lookup_result provides
    /// just basic information.
    /// Any shape-specific information are supposed to be provided
    /// derived (interface) classes. The UUID returned by \c get_intersection_info_class provides
    /// the application with the necessary interface class id required for proper casting the
    /// general intersection information interface class to the shape-specific intersection
    /// information interface class if additional shape-specific details for the intersection are
    /// required.
    ///
    /// \return     Returns the UUID of the shape-specific lookup result interface class.
    ///             By default, the UUID refers to this default lookup interface.
    ///
    virtual mi::base::Uuid get_intersection_info_class() const = 0;
};

}} // namespace index / nv

#endif // NVIDIA_INDEX_ISCENE_QUERY_RESULTS_H
