Last active
May 11, 2023 06:43
-
-
Save Robadob/d6d479f39bf7a1944e87c6b1780a813d to your computer and use it in GitHub Desktop.
3D Geometry Functions
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
#ifndef __3DGeometry_h__ | |
#define __3DGeometry_h__ | |
#include <glm/glm.hpp> | |
/** | |
* Returns the closest point on a given infinite line to a given point | |
**/ | |
glm:vec3 closestPointOnLine(const glm::vec3 &line1, const glm::vec3 &line2, const glm::vec3 &point) | |
{//https://forum.unity3d.com/threads/how-do-i-find-the-closest-point-on-a-line.340058/#post-2198950 | |
glm::vec3 dir = normalize(line2-line1); | |
glm::vec3 v = point-line1; | |
float d = dot(v, dir); | |
return line1 + dir*d; | |
} | |
/** | |
* Returns the closest point on a given line segment to a given point | |
**/ | |
glm::vec3 closestPointOnLineSegment(const glm::vec3 &line1, const glm::vec3 &line2, const glm::vec3 &point) | |
{//https://forum.unity3d.com/threads/how-do-i-find-the-closest-point-on-a-line.340058/#post-2199249 | |
glm::vec3 line = line2 - line1; | |
float len = length(line); | |
line = normalize(line); | |
glm::vec3 v = point - line1; | |
float d = dot(v, line); | |
d = glm::clamp<float>(d, 0, len); | |
return line1 + line*d; | |
} | |
/** | |
* Returns the distance to the closest point on a given line segment to a given point | |
**/ | |
float distPointLine(const glm::vec3 &line1, const glm::vec3 &line2, const glm::vec3 &point) | |
{//http://www.randygaul.net/2014/07/23/distance-point-to-line-segment/ | |
glm::vec3 n = line2 - line1; | |
glm::vec3 pa = line1 - point; | |
float c = dot(n, pa); | |
if (c > 0.0f)//Nearest point goes past A | |
return dot(pa,pa); | |
glm::vec3 bp = point - line2; | |
if (dot(n, bp) > 0.0f)//Nearest point goes past B | |
return dot(bp,bp); | |
glm::vec3 e = pa - n * (c / dot(n, n)); | |
return dot(e, e); | |
} | |
//I think this is known as determinant, confirms whether 3 point are wound in a clockwise order | |
bool isCW(const glm::vec2 &p0, const glm::vec2 &p1, const glm::vec2 &p2) | |
{//Taken from SO | |
return (p1.x*p2.y - p1.y*p2.x - p0.x*p2.y + p0.y*p2.x + p0.x*p1.y - p0.y*p1.x)< 0; | |
} | |
//Projects the 3d poly into the 2d plane of Normal(0,1,0) and ensures point is in bounds | |
bool insideConvexPoly3D2D(const glm::vec3 *beforeFirstPoint, const glm::vec3 *afterLastPoint, const glm::vec3 &testPoint) | |
{//Based on http://erich.realtimerendering.com/ptinpoly/ | |
glm::vec2 testPoint2D = glm::vec2(testPoint.x, testPoint.z); | |
glm::vec2 pt1; | |
glm::vec2 pt2 = glm::vec2((*(afterLastPoint - 1)).x, (*(afterLastPoint - 1)).z); | |
float yMin = FLT_MAX; | |
float yMax = -FLT_MAX; | |
for (const glm::vec3 *i = beforeFirstPoint; i < afterLastPoint; ++i) | |
{ | |
pt1 = pt2; | |
pt2 = glm::vec2((*i).x, (*i).z); | |
if (!isCW(pt1, pt2, testPoint2D)) | |
{ | |
return false; | |
} | |
yMin = glm::min(yMin, (*i).y); | |
yMax = glm::max(yMax, (*i).y); | |
} | |
if (testPoint.y >= yMin&&testPoint.y <= yMax) | |
return true; | |
return false; | |
} | |
/** | |
* Intersects an infinite ray with an infinite plane | |
* Returns false where the infinite ray is parallel to the plane | |
**/ | |
bool linePlaneIntersection(const glm::vec3 &rayStart, const glm::vec3 &rayEnd, | |
const glm::vec3 &planeNormal, const glm::vec3 &pointOnPlane, glm::vec3& contact) | |
{//https://stackoverflow.com/a/35396994/1646387 | |
// get d value | |
float d = dot(planeNormal, pointOnPlane); | |
glm::vec3 rayNormal = normalize(rayEnd - rayStart); | |
if (dot(planeNormal, rayNormal) == 0) { | |
return false; // No intersection, the line is parallel to the plane | |
} | |
// Compute the X value for the directed line ray intersecting the plane | |
float x = (d - dot(planeNormal, rayStart)) / dot(planeNormal, rayNormal); | |
// output contact point | |
contact = rayStart + rayNormal*x; //Make sure your ray vector is normalized | |
return true; | |
} | |
#endif //__3DGeometry_h__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment