// grtray.h
// by Glenn G. Chappell
// April 2004
// Part of GRT package

// Defines class GrtRay

#ifndef FILE_GRTRAY_H_INCLUDED
#define FILE_GRTRAY_H_INCLUDED

#include "grttypes.h"
#include "vecpos.h"
using tf::vec;
using tf::pos;


// ************************************************************************
// GrtRay declaration
// ************************************************************************

// class GrtRay
// Ray with position and direction
// Includes optional utility functions for doing reflection & refraction
class GrtRay
{

// ***** GrtRay: ctors, dctor, op= *****
public:
   GrtRay(const pos & thestartp=pos(), const vec & thedirecv = vec())
      :startp_(thestartp), direcv_(thedirecv.normalized())
   {}

   // Auto-generated copy ctor, dctor, copy op= are fine

// ***** GrtRay: data access *****
public:
   pos start() const
   { return startp_; }

   void setstart(const pos & thestartp)
   { startp_ = thestartp; }

   vec dir() const
   { return direcv_; }

   void setdir(const vec & thedirecv)
   { direcv_ = thedirecv.normalized(); }

// ***** GrtRay: utility operations
public:
   GrtRay reflect(const GrtHit & thehit) const
      // Reflect this ray at a hit point.
      // Returns reflected ray.
   {
      const pos newstartp = thehit.where;
      const vec newdirecv = direcv_ - 2.*direcv_.component(thehit.norm);
      return GrtRay(newstartp, newdirecv);
   }

   GrtRay refract(const GrtHit & thehit, double index) const
      // Refract this ray at a hit point. Assumes normal vector at hit is unit.
      // index is index of refraction of object. Assume this is positive.
      // Returns refracted ray.
   {
      const pos newstartp = thehit.where;

      double trueindex;  // Index of refraction of medium we are entering
                         //  w.r.t. medium we are leaving.
      if (direcv_.dot(thehit.norm) < 0.)  // Entering object
      {
         trueindex = index;
      }
      else                                 // Leaving object
      {
         trueindex = 1./index;
      }

      // Compute components of ray direction parallel & perpendicular
      //  to object normal
      const vec parcomponent = direcv_.component(thehit.norm);
      const vec perpcomponent = direcv_ - parcomponent;
      const vec newdirecv = trueindex * perpcomponent + parcomponent;
     
      return GrtRay(newstartp, newdirecv);
   }
   
// ***** GrtRay: Data members *****
private:
   pos startp_;  // Starting point of ray
   vec direcv_;  // Direction of ray; always a unit vector

};  // End class GrtRay

#endif // #ifndef FILE_GRTRAY_H_INCLUDED
