summaryrefslogblamecommitdiff
path: root/hw6/src/intersectionPoint.cpp
blob: 5b1d15ee74cac8692b9a5a848937d07a4349b7d1 (plain) (tree)





















































































































































































































































































































































                                                                                                                                                                                                
/******************************************************************/
/* This file is part of the homework assignments for CSCI-427/527 */
/* at The College of William & Mary and authored by Pieter Peers. */
/* No part of this file, whether altered or in original form, can */
/* be distributed or used outside the context of CSCI-427/527     */
/* without consent of either the College of William & Mary or     */
/* Pieter Peers.                                                  */
/******************************************************************/
#include <cassert>
#include "shader_base.h"
#include "intersectionPoint.h"

/////////////////
// Constructor //
/////////////////
intersectionPoint::intersectionPoint(void)
{
  _hit = false;
}


intersectionPoint::intersectionPoint(const ray& r, float rayParameter, const std::shared_ptr<const shader_base>& shader, const vec3d& normal, const vec3d& axis, const vec2d& textureCoordinate)
{
  // copy
  _ray = r;
  _rayParameter = rayParameter;
  _hit = true;
  _shader = shader;
  _normal = normalize(normal);
  _axis = normalize(axis);
  _textureCoordinate = textureCoordinate;

  // compute position
  _position = _ray(_rayParameter);
}


intersectionPoint::intersectionPoint(const intersectionPoint& ip)
{
  _hit = ip._hit;

  // copy remainder if hit
  if(_hit)
  {
    _ray = ip._ray;
    _rayParameter = ip._rayParameter;
    _shader = ip._shader;
    _normal = ip._normal;
    _position = ip._position;
    _axis = ip._axis;
    _textureCoordinate = ip._textureCoordinate;
  }
  else _shader = nullptr;
}

///////////////
// Operators //
///////////////
intersectionPoint& intersectionPoint::operator=(const intersectionPoint& ip)
{
  _assign(ip);
  return *this;
}


bool intersectionPoint::operator<(const intersectionPoint& ip) const
{
  // handle case where either one of the intersectionPoints is not a hit
  // => assume no-hit equals a hit at infinity
  if(!_hit) return false;
  if(!ip._hit) return true;

  // decide based on rayParameter
  return _rayParameter < ip._rayParameter;
}


bool intersectionPoint::operator>(const intersectionPoint& ip) const
{
  // handle case where either one of the intersectionPoints is not a hit
  // => assume no-hit equals a hit at infinity
  if(!_hit) return true;
  if(!ip._hit) return false;

  // decide based on rayParameter
  return _rayParameter > ip._rayParameter;
}


bool intersectionPoint::operator<(const lightSample& ls) const
{
  // handle case where this is not a hit
  if(!_hit) return false;

  // decide based on rayParameter
  return _rayParameter < ls.distance();
}


bool intersectionPoint::operator>(const lightSample& ls) const
{
  // handle case where this is not a hit
  if(!_hit) return true;

  // decide based on rayParameter
  return _rayParameter > ls.distance();
}

////////////////
// Inspectors //
////////////////
bool intersectionPoint::isHit(void) const
{
  return _hit;
}


shaderProperties intersectionPoint::getShaderProperties(void) const
{
  assert(hasShader());
  return _shader->properties(*this);
}


bool intersectionPoint::hasShader(void) const
{
  return (_shader != nullptr);
}


float intersectionPoint::distance(const intersectionPoint& ip) const
{
  // set distance to infinity of one of the two points is not a hit
  if(!_hit || !ip._hit) return +LARGE;

  // compute distance
  return _position.distance(ip._position);
}


const vec3d& intersectionPoint::position(void) const
{
  return _position;
}


const vec3d& intersectionPoint::direction(void) const
{
  return _ray.direction();
}


const vec2d& intersectionPoint::textureCoordinate(void) const
{
  return _textureCoordinate;
}


const vec3d& intersectionPoint::normal(void) const
{
  return _normal;
}


coordinateTransformation intersectionPoint::shadingFrame(void) const
{
  // transform => to global shading frame
  // inverseTransform => to local shading frame
  return coordinateTransformation(_normal, _axis);
}


//////////////
// Mutators //
//////////////
void intersectionPoint::transform(const transformation3d& t)
{
  // sanity check
  if(!_hit) return;

  /// transform
  _ray.transform(t);
  _position = t.transformPoint(_position);
  _normal = t.transformNormal(_normal);
  _axis = t.transformNormal(_axis);

  // recompute the ray parameter (to account for potential scaling)
  _rayParameter = _ray(_position);
}


void intersectionPoint::inverseTransform(const transformation3d& t)
{
  // sanity check
  if(!_hit) return;

  // inverse transform
  _ray.inverseTransform(t);
  _position = t.inverseTransformPoint(_position);
  _normal = t.inverseTransformNormal(_normal);
  _axis = t.inverseTransformNormal(_axis);

  // recompute the ray parameter (to account for potential scaling)
  _rayParameter = _ray(_position);
}


void intersectionPoint::transformShadingFrame(const transformation3d& sft)
{
  // sanity check
  if(!_hit) return;

  // Note: shading frame transformation are defined
  //       with respect to the local shading frame (i.e., N=Z, axis=X)
  transformation3d t = shadingFrame();

  // transform
  _normal = t.transformNormal( sft.transformNormal(vec3d(0.0f, 0.0f, 1.0f)) );
  _axis = t.transformNormal( sft.transformNormal(vec3d(1.0f, 0.0f, 0.0f)) );

  // Done.
}


void intersectionPoint::inverseTransformShadingFrame(const transformation3d& sft)
{
  // sanity check
  if(!_hit) return;

  // Note: shading frame transformation are defined
  //       with respect to the local shading frame (i.e., N=Z, axis=X)
  // Note: this transformation will not undo the effects of
  //       transformShadingFrame since the local shading frame
  //       is altered by the transformation (and thus the frame
  //       with respect to which the inverseTransformation is 
  //       applied)
  transformation3d t = shadingFrame();

  // transform
  _normal = t.transformNormal( sft.inverseTransformNormal(vec3d(0.0f, 0.0f, 1.0f)) );
  _axis = t.transformNormal( sft.inverseTransformNormal(vec3d(1.0f, 0.0f, 0.0f)) );

  // Done.
}


void intersectionPoint::setShader(const std::shared_ptr<const class shader_base>& shader)
{
  _shader = shader;
}


/////////////
// Methods //
/////////////
color intersectionPoint::shade(const vec3d& out) const
{
  assert(hasShader());
  if(!_hit) return color(0.0f);
  return _shader->shade(*this, out);
}

color intersectionPoint::shade(const lightSample& ls) const
{
  assert(hasShader());
  if(!_hit) return color(0.0f);
  return _shader->shade(*this, ls.directionToLight()) * ls.emittance();
}


float intersectionPoint::reflectivity(void) const
{
  assert(hasShader());

  // get reflectivity
  float albedo = _shader->reflectivity(*this);
  
  // cannot reflect more than 100%
  assert(albedo <= 1.0f);

  // Done.
  return albedo;
}


color intersectionPoint::reflectance(const vec3d& out) const
{
  assert(hasShader());
  return _shader->reflectance(*this, out);
}


brdfSample intersectionPoint::sample(float r1, float r2) const
{
  assert(hasShader());
  return _shader->sample(*this, r1, r2);
}


color intersectionPoint::emittance(void) const
{
  assert(hasShader());
  return _shader->emittance(*this);
}


/////////////////////
// Private Methods //
/////////////////////
void intersectionPoint::_assign(const intersectionPoint& ip)
{
  // sanity check
  if(&ip == this) return;

  // copy if hit
  _hit = ip._hit;
  if(_hit)
  {
    _ray = ip._ray;
    _rayParameter = ip._rayParameter;
    _position = ip._position;
    _normal = ip._normal;
    _axis = ip._axis;
    _textureCoordinate = ip._textureCoordinate;
    _shader = ip._shader;
  }
  else _shader = nullptr;
}


void intersectionPoint::_swap(intersectionPoint& ip)
{
  swap(_ray, ip._ray);
  std::swap(_hit, ip._hit);
  std::swap(_rayParameter, ip._rayParameter);
  swap(_position, ip._position);
  swap(_normal, ip._normal);
  swap(_axis, ip._axis);
  swap(_textureCoordinate, ip._textureCoordinate);
  std::swap(_shader, ip._shader);
}