Add Planes

This commit is contained in:
Eryn Wells 2013-09-22 09:58:40 -07:00
parent 5d14a63c37
commit 2ea0589b44
2 changed files with 185 additions and 0 deletions

154
src/object_plane.cc Normal file
View file

@ -0,0 +1,154 @@
/* object_plane.h
*
* Planes are Shapes defined by a point and two direction vectors.
*
* Eryn Wells <eryn@erynwells.me>
*/
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include "basics.h"
#include "object.h"
#include "object_plane.h"
/*
* Plane::Plane --
*
* Default constructor. Create a Plane with a point at the origin and normal vector in the Y direction.
*/
Plane::Plane()
: Plane(Vector3::Y)
{ }
/*
* Plane::Plane --
*
* Constructor. Create a Plane with a point at the origin, and a given normal.
*/
Plane::Plane(Vector3 n)
: Plane(Vector3::Zero, n)
{ }
/*
* Plane::Plane --
*
* Constructor. Create a Plane with the given origin and normal vectors.
*/
Plane::Plane(Vector3 o, Vector3 n)
: Shape(o),
normal(n.normalize())
{ }
/*
* Plane::does_intersect --
*
* Compute the intersection of a ray with this Plane. All intersection t values are returned in the **t argument. The
* number of values returned therein is indicated by the return value. Memory is allocated at *t. It is the caller's
* responsibility to free it when it is no longer needed. If 0 is returned, no memory needs to be freed.
*/
int
Plane::does_intersect(const Ray &ray, float **t)
const
{
/*
* The algebraic form of a plane is the following:
*
* (p - p0) . n = 0
*
* where p is a point in the plane, p0 is another point in the plane (the origin point in our case), and n is the
* normal vector. (Periods [.] indicate dot products.) We can plug in the parametric equation for a Ray and solve
* for t to get the intersection point.
*
* ((ro + t*rd) - p0) . n = 0
*
* Simplifying, distributing, and solving for t:
*
* t = ((p0 - ro) . n) / (ld . n)
*
* Note that if the denominator is 0, the ray runs parallel to the plane and there are no intersections. If both the
* numerator and denominator are 0, the ray is in the plane and intersects everywhere.
*
* See: http://en.wikipedia.org/wiki/Line-plane_intersection
*/
Vector3 o = get_origin();
int nints = 1;
float numer = (o - ray.origin).dot(normal);
float denom = ray.direction.dot(normal);
if (denom == 0.0) {
nints = 0;
if (numer == 0.0) {
// Ray is in plane.
nints = 1;
}
}
// No intersections.
if (nints == 0) {
return nints;
}
float t0 = numer / denom;
// If the t value is negative, it's "behind" the origin of the ray, which we don't care about.
if (t0 < 0.0) {
return 0;
}
// Allocate memory, at most one float.
if (t != NULL) {
*t = new float(t0);
}
return nints;
}
/*
* Plane::point_is_on_surface --
*
* Determine if a point lies on the surface of this Sphere.
*/
bool
Plane::point_is_on_surface(const Vector3 &p)
const
{
/*
* Plug point p into the equation for a plane:
*
* a(x - ox) + b(y - oy) + c(z - oz) = 0
*
* where (a, b, c) are the coordinates of the normal vector, and (ox, oy, oz) are the coordinates of the origin
* vector.
*
* I found this page most helpful:
* http://www.math.oregonstate.edu/home/programs/undergrad/CalculusQuestStudyGuides/vcalc/lineplane/lineplane.html
*/
Vector3 o = get_origin();
float x = normal.x * (p.x - o.x);
float y = normal.y * (p.y - o.y);
float z = normal.z * (p.z - o.z);
return (x + y + z) == 0.0;
}
/*
* Plane::compute_normal --
*
* Compute the normal for this Plane at the given point. If the point does not lie on the surface of the plane, a zero
* vector is returned.
*/
Vector3
Plane::compute_normal(const Vector3 &p)
const
{
// This one's easy since planes are defined by their normals. :)
return normal;
}

31
src/object_plane.h Normal file
View file

@ -0,0 +1,31 @@
/* object_plane.h
*
* Planes are Shapes defined by a point and two direction vectors.
*
* Eryn Wells <eryn@erynwells.me>
*/
#ifndef __OBJECT_PLANE_H__
#define __OBJECT_PLANE_H__
#include "basics.h"
#include "object.h"
class Plane
: public Shape
{
public:
Plane();
Plane(Vector3 normal);
Plane(Vector3 o, Vector3 normal);
int does_intersect(const Ray &ray, float **t) const;
bool point_is_on_surface(const Vector3 &p) const;
Vector3 compute_normal(const Vector3 &p) const;
private:
Vector3 normal;
};
#endif