Skip to content

Instantly share code, notes, and snippets.

@ThePhD
Created February 25, 2014 02:14
Show Gist options
  • Save ThePhD/6747153fbf639ed5ee02 to your computer and use it in GitHub Desktop.
Save ThePhD/6747153fbf639ed5ee02 to your computer and use it in GitHub Desktop.
#pragma once
#include <Furrovine++/THit3.h>
#include <Furrovine++/optional.h>
#include <Furrovine++/Ray3.h>
#include <Furrovine++/Vector3.h>
#include <Furrovine++/TNormal3.h>
#include <Furrovine++/RTriangle3.h>
#include <Furrovine++/RPlane.h>
#include <Furrovine++/RSphere.h>
#include <Furrovine++/RDisk3.h>
namespace Furrovine {
template <typename T>
optional<THit3<T>> intersect( const TRay3<T>& ray, const RPlane<T>& target ) {
T distance;
T denom = dot( target.normal, ray.direction );
if ( denom <= static_cast<T>( 1e-6 ) )
return nullopt;
Vec3 onplane = ( target.normal * target.distance );
Vec3 origindirection = onplane - ray.origin;
distance = dot( origindirection, target.normal ) / denom;
if ( distance < 0 )
return nullopt;
THit3<T> hit;
hit.distance0 = distance;
hit.contact = ray.at( hit.distance0 );
hit.normal = target.normal;
return hit;
}
template <typename T>
optional<THit3<T>> intersect( const TRay3<T>& ray, const RSphere<T>& target ) {
RVector3<T> L = target.origin - ray.origin;
T tca = L.dot( ray.direction );
if ( tca < 0 )
return nullopt;
T radiussquared = target.radius * target.radius;
T d2 = L.dot( L ) - tca * tca;
if ( d2 > radiussquared )
return nullopt;
T thc = static_cast<T>( std::sqrt( radiussquared - d2 ) );
THit3<T> hit;
hit.distance0 = tca - thc;
hit.distance1 = tca + thc;
hit.contact = ray.at( hit.distance0 );
hit.normal = target.origin - hit.contact;
hit.normal.normalize( );
return hit;
}
template <typename T>
optional<THit3<T>> intersect( const TRay3<T>& ray, const RTriangle3<T>& target ) {
RVector3<T> edge1( target.b ), edge2( target.c );
edge1 -= target.a;
edge2 -= target.b;
RVector3<T> crossproduct( cross( ray.direction, edge2 ) );
T dotproduct = edge1.dot( crossproduct );
if ( dotproduct == static_cast<T>( 0 ) )
return nullopt;
THit3<T> hit;
RVector3<T> vdist( ray.origin - target.a );
hit.uvw.x = vdist.dot( crossproduct ) / dotproduct;
if ( hit.uvw.x < static_cast<T>( 0 ) || hit.uvw.x > static_cast<T>( 1 ) )
return nullopt;
RVector3<T> vrdist( vdist.cross( edge1 ) );
hit.uvw.y = dot( ray.direction, vrdist ) / dotproduct;
if ( hit.uvw.y < static_cast<T>( 0 ) || hit.uvw.x + hit.uvw.y > static_cast<T>( 1 ) )
return nullopt;
hit.distance0 = edge2.dot( vrdist ) / dotproduct;
hit.normal = target.normal( );
hit.contact = ray.at( hit.distance0 );
return hit;
}
template <typename T>
optional<THit3<T>> intersect( const TRay3<T>& ray, const RDisk3<T>& target ) {
T d = 0;
auto planehit = intersect( ray, target.plane );
if ( planehit ) {
RVector3<T> p = ray.origin + ray.direction * d;
RVector3<T> v = p - target.origin;
T d2 = v.dot( v );
if ( d2 <= target.radius * target.radius )
return planehit;
}
return nullopt;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment