Subversion Repositories gelsvn

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#ifndef __RAY_H__
#define __RAY_H__

#include "CGLA/Vec3f.h"
#include "Geometry/TriMesh.h"

namespace BRender 
{
  const double d_eps = 0.000001;
  const float f_eps = 0.01f;

  struct Ray 
  {
    // Constructor
    Ray() 
      : origin(0), direction(0), hit_pos(0), hit_normal(0), 
        has_hit(false), dist(CGLA::BIG), ior(1), u(0), v(0), 
        hit_object(0)
    { }

    CGLA::Vec3f origin;
    CGLA::Vec3f direction;
    CGLA::Vec3f hit_pos;
    CGLA::Vec3f hit_normal;

    bool has_hit; // Did the ray hit an object

    double dist;  // Distance from origin to current intersection
    float ior;    // Current index of refraction for media
    float u, v;   // uv-coordinates on current surface
    float ran;

    int trace_depth;  // Current recursion number
    int hit_face_id;
    int id;

    Geometry::TriMesh* hit_object;

    void reset()
    {
      dist = CGLA::BIG; 
      hit_object = 0;
      u=0;
      v=0;
      has_hit=false;      
    }

    void reflect(const CGLA::Vec3f &normal)
    {
      assert(dot(direction, normal) < 0);
      direction = normal*2.0f*dot(-direction,normal) + direction;      
    }

    void refract(const CGLA::Vec3f& normal, float new_ior)
    {
      float ref_ratio = ior/new_ior;
      float cos_N_I = dot(normal, direction);
      CGLA::Vec3f norm(normal);

      if(cos_N_I > 0)
      {
        norm = -norm;
        cos_N_I = dot(norm, direction);
      }

      float selector = 1 + (ref_ratio*ref_ratio)*(cos_N_I*cos_N_I - 1);

      if(selector > 0) 
      {
        direction = norm*(ref_ratio*(-cos_N_I) - sqrt(selector)) 
                    + direction*ref_ratio;
        ior = new_ior;
      } 
      else 
        // Total internal reflection.
        reflect(normal);
    }
  };
  
}
#endif