// Copyright 2009-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "common/Ray.ih"
#include "math/AffineSpace.ih"
#include "math/box.ih"
// openvkl
#include "openvkl/value_selector.isph"
#include "openvkl/openvkl.isph"

struct TransferFunction;

//! \brief Variables and methods common to all subtypes of the Volume
//!  class, an abstraction for the concrete object which performs the
//!  volume sampling (this struct must be the first field of a struct
//!  representing a "derived" class to allow casting to that class).
//!
struct Volume
{
  /*! pointer to the c++-equivalent class of this entity */
  void *cppEquivalent;

  int32 volumeID;

  VKLVolume vklVolume;
  VKLSampler vklSampler;

  //! Find the next isosurface hit point in the volume for ray casting based
  //! renderers.
  void (*intersectIsosurface)(const void *uniform _self,
      uniform float *uniform isovalues,
      uniform int numIsovalues,
      uniform size_t geomID,
      // ray.u contains ray-space intersection error, i.e. the epsilon
      varying Ray &ray);

  /*! Bounding box for the volume in world coordinates.
      This is an internal derived parameter and not meant to be
      redefined externally.
  */
  box3f boundingBox;
};

void Volume_Constructor(Volume *uniform volume, void *uniform cppEquivalent);

// Helper functions ///////////////////////////////////////////////////////////

inline float Volume_getSample(const Volume *uniform volume, const vec3f &P)
{
  return vklComputeSampleV(volume->vklSampler, &((const vkl_vec3f &)P));
}

inline vec3f Volume_getGradient(const Volume *uniform volume, const vec3f &P)
{
  vkl_vec3f result =
      vklComputeGradientV(volume->vklSampler, &((const vkl_vec3f &)P));

  return *((varying vec3f *)&result);
}
