-
-
Save ThePhD/6747153fbf639ed5ee02 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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