kick
|
00001 // 00002 // ray.cpp 00003 // KickCPP 00004 // 00005 // Created by Morten Nobel-Jørgensen on 18/12/13. 00006 // Copyright (c) 2013 Morten Nobel-Joergensen. All rights reserved. 00007 // 00008 00009 #include "kick/math/ray.h" 00010 00011 using namespace glm; 00012 00013 namespace kick { 00014 Ray::Ray() 00015 : mOrigin{vec3(0,0,0)}, mDirection{vec3(0,0,-1)} 00016 { 00017 00018 } 00019 00020 Ray::Ray(vec3 origin, vec3 direction) 00021 : mOrigin{origin}, mDirection{glm::normalize(direction)} 00022 { 00023 } 00024 00025 bool Ray::closestPoints(Ray otherRay, glm::vec3& outPoint1, glm::vec3& outPoint2) const { 00026 vec3 otherRayOrigin = otherRay.mOrigin; 00027 vec3 otherRayDirection = otherRay.mDirection; 00028 float epsilon = 1.401298E-45f; 00029 bool isParallel = fabs(dot(mDirection, otherRayDirection)) >= 1 - epsilon; 00030 if (isParallel){ 00031 outPoint1 = vec3{0}; 00032 outPoint2 = vec3{0}; 00033 return false; 00034 } 00035 00036 // loosely based on http://www.youtube.com/watch?v=HC5YikQxwZA 00037 // t is distance traveled at ray and s distance traveled at otherRay 00038 // PQ is vector between rays 00039 vec3 PQT = -mDirection; 00040 vec3 PQS = otherRayDirection; 00041 vec3 PQVal = -mOrigin + otherRayOrigin; 00042 00043 float PQu1S = dot(PQS, mDirection); 00044 float PQu1T = dot(PQT, mDirection); 00045 float PQu1Val = dot(PQVal, mDirection) * -1; 00046 00047 float PQu2S = dot(PQS, otherRayDirection); 00048 float PQu2T = dot(PQT, otherRayDirection); 00049 float PQu2Val = dot(PQVal, otherRayDirection) * -1; 00050 00051 // maybe not the most efficient way to solve the system of linear equations 00052 mat2x2 mat; 00053 mat[0][0] = PQu1S; 00054 mat[1][0] = PQu1T; 00055 mat[0][1] = PQu2S; 00056 mat[1][1] = PQu2T; 00057 00058 mat = inverse(mat); 00059 vec2 res = mat * vec2(PQu1Val, PQu2Val); 00060 00061 outPoint1 = mOrigin + mDirection * res[1]; 00062 outPoint2 = otherRayOrigin + otherRayDirection * res[0]; 00063 00064 return true; 00065 } 00066 00067 void Ray::setDirection(glm::vec3 const &direction) { 00068 Ray::mDirection = glm::normalize(direction); 00069 } 00070 00071 glm::vec3 const &Ray::direction() const { 00072 return mDirection; 00073 } 00074 00075 void Ray::setOrigin(glm::vec3 const &origin) { 00076 Ray::mOrigin = origin; 00077 } 00078 00079 glm::vec3 const &Ray::origin() const { 00080 return mOrigin; 00081 } 00082 00083 glm::vec3 Ray::point(float offset) const { 00084 return mOrigin + mDirection * offset; 00085 } 00086 00087 bool Ray::intersectTriangle(glm::vec3 v0, glm::vec3 v1, glm::vec3 v2, glm::vec3 &intersectionPoint, bool clampBackIntersections) const { 00088 // based on RTR 3ed page 750 00089 vec3 e1 = v1 - v0; 00090 vec3 e2 = v2 - v0; 00091 vec3 q = cross(mDirection, e2); 00092 float a = dot(e1, q); 00093 float eps = 1e-10; 00094 if (a > -eps && a < eps) return false; 00095 float f = 1 / a; 00096 vec3 s = mOrigin - v0; 00097 float u = f * dot(s, q); 00098 if (u < 0.0) return false; 00099 vec3 r = cross(s, e1); 00100 float v = f * dot(mDirection, r); 00101 if (v < 0.0 || u + v > 1.0) return false; 00102 float t = f * dot(e2, r); 00103 if (clampBackIntersections && t < 0){ 00104 return false; 00105 } 00106 intersectionPoint = point(t); 00107 00108 return true; 00109 } 00110 00111 glm::vec3 Ray::closestPoint(glm::vec3 point) const { 00112 return mOrigin + dot(point - mOrigin, mDirection) / dot(mDirection,mDirection) * mDirection; 00113 } 00114 }