// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#ifndef __RTCORE_RAY_ISPH__
#define __RTCORE_RAY_ISPH__

#include "rtcore.isph"

/*! \ingroup embree_kernel_api_ispc */
/*! \{ */

/*! Ray structure for uniform (single) rays. */
#ifndef __RTCRay1__
#define __RTCRay1__
struct RTCRay1 
{
  /* ray data */
  float org[3];      //!< Ray origin
  float align0;      //!< unused member to force alignment of following members
  
  float dir[3];      //!< Ray direction
  float align1;      //!< unused member to force alignment of following members
  
  float tnear;       //!< Start of ray segment
  float tfar;        //!< End of ray segment (set to hit distance)
  float time;        //!< Time of this ray for motion blur
  unsigned int mask;        //!< Used to mask out objects during traversal
  
  /* hit data */
  float Ng[3];       //!< Unnormalized geometry normal
  float align2;
  
  float u;           //!< Barycentric u coordinate of hit
  float v;           //!< Barycentric v coordinate of hit

  unsigned int geomID;        //!< geometry ID
  unsigned int primID;        //!< primitive ID
  unsigned int instID;        //!< instance ID
  varying unsigned int align[0];  //!< aligns ray on stack to at least 16 bytes
};
#endif

/*! Ray structure for packets of 4 rays. */
#ifndef __RTCRay__
#define __RTCRay__
struct RTCRay
{
  /* ray data */
  float orgx;  //!< x coordinate of ray origin
  float orgy;  //!< y coordinate of ray origin
  float orgz;  //!< z coordinate of ray origin
  
  float dirx;  //!< x coordinate of ray direction
  float diry;  //!< y coordinate of ray direction
  float dirz;  //!< z coordinate of ray direction
  
  float tnear; //!< Start of ray segment 
  float tfar;  //!< End of ray segment   
  float time;  //!< Time of this ray for motion blur
  unsigned int mask;  //!< Used to mask out objects during traversal
  
  /* hit data */
  float Ngx;   //!< x coordinate of geometry normal
  float Ngy;   //!< y coordinate of geometry normal
  float Ngz;   //!< z coordinate of geometry normal
  
  float u;     //!< Barycentric u coordinate of hit
  float v;     //!< Barycentric v coordinate of hit
  
  unsigned int geomID;     //!< geometry ID
  unsigned int primID;     //!< primitive ID
  unsigned int instID;     //!< instance ID
};
#endif

/* Helper functions to access ray packets of runtime size N */
#ifndef __RTCRayN__
#define __RTCRayN__
struct RTCRayN {};
inline varying float& RTCRayN_org_x(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[0*N+0*N1+i]); }  //!< x coordinate of ray origin
inline varying float& RTCRayN_org_y(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[1*N+0*N1+i]); }  //!< y coordinate of ray origin
inline varying float& RTCRayN_org_z(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[2*N+0*N1+i]); }; //!< z coordinate of ray origin

inline varying float& RTCRayN_dir_x(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[3*N+1*N1+i]); }; //!< x coordinate of ray direction
inline varying float& RTCRayN_dir_y(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[4*N+1*N1+i]); }; //!< y coordinate of ray direction
inline varying float& RTCRayN_dir_z(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[5*N+1*N1+i]); }; //!< z coordinate of ray direction

inline varying float& RTCRayN_tnear(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[6*N+2*N1+i]); }; //!< Start of ray segment 
inline varying float& RTCRayN_tfar (RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[7*N+2*N1+i]); }; //!< End of ray segment (set to hit distance)

inline varying float& RTCRayN_time(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[8*N+2*N1+i]); };  //!< Time of this ray for motion blur 
inline varying unsigned int&   RTCRayN_mask(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying unsigned int* uniform) &((uniform unsigned int*)ptr)[9*N+2*N1+i]); };  //!< Used to mask out objects during traversal

inline varying float& RTCRayN_Ng_x(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[10*N+2*N1+i]); }; //!< x coordinate of geometry normal
inline varying float& RTCRayN_Ng_y(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[11*N+2*N1+i]); }; //!< y coordinate of geometry normal
inline varying float& RTCRayN_Ng_z(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[12*N+2*N1+i]); }; //!< z coordinate of geometry normal

inline varying float& RTCRayN_u   (RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[13*N+3*N1+i]); }; //!< Barycentric u coordinate of hit
inline varying float& RTCRayN_v   (RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying float* uniform) &((uniform float*)ptr)[14*N+3*N1+i]); }; //!< Barycentric v coordinate of hit

inline varying unsigned int& RTCRayN_geomID(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying unsigned int*   uniform) &((uniform unsigned int*  )ptr)[15*N+3*N1+i]); }; //!< geometry ID
inline varying unsigned int& RTCRayN_primID(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying unsigned int*   uniform) &((uniform unsigned int*  )ptr)[16*N+3*N1+i]); }; //!< primitive ID
inline varying unsigned int& RTCRayN_instID(RTCRayN* uniform ptr, uniform size_t N, uniform size_t i) { uniform size_t N1 = (uniform size_t)(N == 1); return *((varying unsigned int*   uniform) &((uniform unsigned int*  )ptr)[17*N+3*N1+i]); }; //!< instance ID
#endif

/*! \brief Ray structure template for packets of N rays in pointer SOA layout. */
#ifndef __RTCRayNp__
#define __RTCRayNp__
struct RTCRayNp
{
  /* ray data */
  uniform float* uniform orgx;  //!< x coordinate of ray origin
  uniform float* uniform orgy;  //!< y coordinate of ray origin
  uniform float* uniform orgz;  //!< z coordinate of ray origin

  uniform float* uniform dirx;  //!< x coordinate of ray direction
  uniform float* uniform diry;  //!< y coordinate of ray direction
  uniform float* uniform dirz;  //!< z coordinate of ray direction

  uniform float* uniform tnear; //!< Start of ray segment (optional)
  uniform float* uniform tfar;  //!< End of ray segment (set to hit distance)
 
  uniform float* uniform time;  //!< Time of this ray for motion blur (optional)
  uniform unsigned int* uniform mask;  //!< Used to mask out objects during traversal (optional)

  /* hit data */
  uniform float* uniform Ngx;   //!< x coordinate of geometry normal (optional)
  uniform float* uniform Ngy;   //!< y coordinate of geometry normal (optional)
  uniform float* uniform Ngz;   //!< z coordinate of geometry normal (optional)

  uniform float* uniform u;     //!< Barycentric u coordinate of hit
  uniform float* uniform v;     //!< Barycentric v coordinate of hit
 
  uniform unsigned int* uniform geomID;  //!< geometry ID
  uniform unsigned int* uniform primID;  //!< primitive ID
  uniform unsigned int* uniform instID;  //!< instance ID (optional)
};
#endif

/* Helper functions to access hit packets of size N */
#ifndef __RTCHitN__
#define __RTCHitN__
struct RTCHitN {};
inline varying float& RTCHitN_Ng_x(const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying float* uniform) &((float* uniform)ptr)[0*N+i]); }; //!< x coordinate of geometry normal
inline varying float& RTCHitN_Ng_y(const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying float* uniform) &((float* uniform)ptr)[1*N+i]); }; //!< y coordinate of geometry normal
inline varying float& RTCHitN_Ng_z(const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying float* uniform) &((float* uniform)ptr)[2*N+i]); }; //!< z coordinate of geometry normal

inline varying unsigned int& RTCHitN_instID(const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying unsigned int*   uniform) &((unsigned int* uniform  )ptr)[3*N+i]); }; //!< instance ID
inline varying unsigned int& RTCHitN_geomID(const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying unsigned int*   uniform) &((unsigned int* uniform  )ptr)[4*N+i]); }; //!< geometry ID
inline varying unsigned int& RTCHitN_primID(const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying unsigned int*   uniform) &((unsigned int* uniform  )ptr)[5*N+i]); }; //!< primitive ID

inline varying float& RTCHitN_u   (const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying float* uniform) &((float* uniform)ptr)[6*N+i]); }; //!< Barycentric u coordinate of hit
inline varying float& RTCHitN_v   (const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying float* uniform) &((float* uniform)ptr)[7*N+i]); }; //!< Barycentric v coordinate of hit
inline varying float& RTCHitN_t   (const RTCHitN* uniform ptr, uniform size_t N, uniform size_t i) { return *((varying float* uniform) &((float* uniform)ptr)[8*N+i]); }; //!< hit distance
#endif

/*! @} */

#endif
