Newer
Older
Import / projects / Gameloft / bne_lib / code / Utils / Plane.cpp
/**
 *  @class Plane
 *
 *  @Date: Created by Ray Zhang on 28/07/14.
 *
 *  @Description
 *  Define a plane, defined by a point and the normal from the point.
 */
#include "Plane.h"

const float NORMALISATION_TOLERANCE = 0.0001f; // I would have expected to use RKEPSILON here, but perhaps I'm missing something.

Plane::Plane(const RKVector& point, const RKVector& normal)
: m_point(point)
, m_normal(normal)
{
  RKASSERT(fabs(normal.LengthSquared() - 1) <= NORMALISATION_TOLERANCE, "Plane normal has not been normalised");
}

Plane::Plane(const RKVector& p1, const RKVector& p2, const RKVector& p3)
: m_point(p1)
{
  m_normal = (p2 - p1).Cross(p3 - p1);
  m_normal.Normalize();
}

bool Plane::Intersection(const RKVector& lineBegin, const RKVector& lineDirectionNormalised, RKVector* outIntersection) const
{
  RKASSERT(fabs(lineDirectionNormalised.LengthSquared() - 1) <= NORMALISATION_TOLERANCE, "Ray direction has not been normalised");
  RKASSERT(outIntersection, "No outIntersection reference provided");

  bool res = false;
  float direction_normal_dot_product = lineDirectionNormalised.Dot(m_normal);
  if (fabs(direction_normal_dot_product) > NORMALISATION_TOLERANCE) {
    RKVector  line_to_plane = m_point - lineBegin;
    float distance_along_ray = line_to_plane.Dot(m_normal) / direction_normal_dot_product;
    *outIntersection = lineBegin + distance_along_ray * lineDirectionNormalised;
    res = true;
  }
  outIntersection->w = 1.f;
  return res;
}

bool Plane::Intersection(const Ray& ray, RKVector* outIntersection) const {
  return Intersection(ray.GetOrigin(), ray.GetDirection(), outIntersection);
}

Plane::Side Plane::GetSide(const RKVector& test_position) const {
  RKVector point_to_plane = m_point - test_position;
  float dot_prod = point_to_plane.Dot(m_normal);

  if (dot_prod < RKPI_ON_TWO)
    return SIDE_FRONT;
  else if (dot_prod > RKPI_ON_TWO)
    return SIDE_BACK;

  return SIDE_NONE;
}