geometry.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /*
  2. * MIT License
  3. *
  4. * Copyright (c) [year] [fullname]
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. #ifndef GUL_GEOMETRY_H
  25. #define GUL_GEOMETRY_H
  26. #include <glm/glm.hpp>
  27. #include <glm/gtx/closest_point.hpp>
  28. namespace gul
  29. {
  30. template<typename T>
  31. class point_t
  32. {
  33. public:
  34. typedef T value_type;
  35. typedef glm::tvec3<value_type, glm::highp> glm_type;
  36. point_t()
  37. {
  38. }
  39. point_t(value_type _x) : point_t(_x,_x,_x){}
  40. explicit point_t(value_type _x, value_type _y, value_type _z) : x(_x), y(_y), z(_z)
  41. {
  42. }
  43. explicit point_t( glm_type const & p) : point_t( p.x,p.y,p.z)
  44. {
  45. }
  46. value_type & operator[](int i)
  47. {
  48. return (&x)[i];
  49. }
  50. value_type const & operator[](int i) const
  51. {
  52. return (&x)[i];
  53. }
  54. glm_type asVec() const
  55. {
  56. return glm_type(x,y,z);
  57. }
  58. value_type x=value_type(0);
  59. value_type y=value_type(0);
  60. value_type z=value_type(0);
  61. };
  62. /**
  63. * @brief displacement
  64. * @param p
  65. * @param L
  66. * @return
  67. *
  68. * Returns the vector which starts on p1 and ends on p2
  69. */
  70. template<typename T>
  71. inline glm::tvec3<T, glm::highp> displacement(point_t<T> const & p1, point_t<T> const & p2)
  72. {
  73. return glm::tvec3<T, glm::highp>( p2.x-p1.x , p2.y-p1.y, p2.z-p1.z);
  74. }
  75. template<typename T>
  76. inline point_t<T> operator+(point_t<T> const & p1, glm::tvec3<T, glm::highp> const & v)
  77. {
  78. return point_t<T>( p1.x+v.x , p1.y+v.y, p1.z+v.z);
  79. }
  80. template<typename T>
  81. inline glm::tvec3<T, glm::highp> operator-(point_t<T> const & p1, point_t<T> const & p2)
  82. {
  83. return displacement(p1,p2);
  84. }
  85. /**
  86. * @brief The line_t class
  87. *
  88. * A line is defined by a point and a vector direction.
  89. */
  90. template<typename T>
  91. class line_t
  92. {
  93. public:
  94. typedef T value_type;
  95. typedef glm::tvec3<value_type, glm::highp> vec_type;
  96. typedef point_t<value_type> point_type;
  97. line_t()
  98. {
  99. }
  100. /**
  101. * @brief line_t
  102. * @param _p0
  103. * @param _p1
  104. *
  105. * Construct a line from two points.
  106. */
  107. line_t( point_type const & _p0, point_type const & _p1) : p(_p0), v( displacement(_p1,_p0) )
  108. {
  109. }
  110. line_t( point_type const & _p0, vec_type const & v1) : p(_p0), v(v1)
  111. {
  112. }
  113. /**
  114. * @brief closestPoint
  115. * @param x
  116. * @return
  117. *
  118. * Returns the point on the line that is closest to x
  119. */
  120. point_type closestPoint(point_type const & x) const
  121. {
  122. return point_type( glm::closestPointOnLine( x.asVec(), p.asVec(), p.asVec()+v) );
  123. auto r = p - x;
  124. //auto r = vec3( L.p.x - p.x , L.p.y -p.y , L.p.z - p.z);
  125. auto n = glm::normalize(v);
  126. return x + (r - glm::dot(r,n)*n);
  127. }
  128. point_type p = point_type{0,0,0};
  129. vec_type v = vec_type{1,0,0};
  130. };
  131. template<typename T>
  132. T length( line_t<T> const & L)
  133. {
  134. return glm::length( L.v );
  135. }
  136. /**
  137. * @brief intersectingLine
  138. * @param L0
  139. * @param L1
  140. * @return
  141. *
  142. * Finds the line/ray that starts on L0 and ends on L1
  143. */
  144. template<typename T>
  145. line_t<T> intersectingLine( line_t<T> const & L0, line_t<T> const & L1 )
  146. {
  147. auto & d1 = L0.v;
  148. auto & d2 = L1.v;
  149. auto & p1 = L0.p;
  150. auto & p2 = L1.p;
  151. auto n = glm::cross( d1, d2);
  152. auto n1 = glm::cross(d1, n);
  153. auto n2 = glm::cross(d2, n);
  154. auto t = -glm::dot(p2-p1, n2 ) / glm::dot(d1,n2);
  155. auto s = -glm::dot(p1-p2, n1 ) / glm::dot(d2,n1);
  156. return line_t<T>( p1+t*d1, p2+s*d2);
  157. }
  158. /**
  159. * @brief distance
  160. * @param L0
  161. * @param L1
  162. * @return
  163. *
  164. * Returns the distance between two lines
  165. */
  166. template<typename T>
  167. T distance( line_t<T> const & L0, line_t<T> const & L1 )
  168. {
  169. auto n = glm::cross(L0.v, L1.v);
  170. return glm::dot( L1.p - L0.p, n) / glm::length(n);
  171. }
  172. /**
  173. * @brief distance
  174. * @param L
  175. * @param p
  176. * @return
  177. *
  178. * Calculates the distance between a line and a point.
  179. */
  180. template<typename T>
  181. inline T distance(line_t<T> const & L, point_t<T> const & p)
  182. {
  183. return glm::length( glm::cross( L.v, vec3(L.p.x - p.x, L.p.y-p.y,L.p.z-p.z)) ) / glm::length(L.v);
  184. }
  185. /**
  186. * @brief displacement
  187. * @param p
  188. * @param L
  189. * @return
  190. *
  191. * Returns a vector which when added to the point, p, will bring the point to line, L
  192. */
  193. template<typename T>
  194. inline glm::tvec3<T, glm::highp> displacement(point_t<T> const & p, line_t<T> const & L)
  195. {
  196. auto r = vec3( L.p.x - p.x , L.p.y -p.y , L.p.z - p.z);
  197. auto n = glm::normalize(L.v);
  198. return r - glm::dot(r,n)*n;
  199. }
  200. /**
  201. * @brief displacement
  202. * @param L
  203. * @param p
  204. * @return
  205. *
  206. * Return the vector which is perpendicular to the Line L and points to the direction of p
  207. */
  208. template<typename T>
  209. inline glm::tvec3<T, glm::highp> displacement(line_t<T> const & L, point_t<T> const & p)
  210. {
  211. return -displacement(p,L);
  212. }
  213. template<typename T>
  214. class plane_t
  215. {
  216. public:
  217. typedef T value_type;
  218. typedef glm::tvec3<value_type, glm::highp> vec_type;
  219. typedef point_t<value_type> point_type;
  220. plane_t()
  221. {
  222. }
  223. /**
  224. * @brief plane_t
  225. * @param _p0
  226. * @param _n
  227. *
  228. * Construct a plane from a point and a normal
  229. */
  230. plane_t( point_type const & _p0, vec_type const & _n) : n( glm::normalize(_n)), d( -glm::dot(n, vec3(_p0.x,_p0.y,_p0.z)))
  231. {
  232. }
  233. /**
  234. * @brief plane_t
  235. * @param a
  236. * @param b
  237. * @param c
  238. *
  239. * Construct a plane from 3 points.
  240. */
  241. plane_t( point_type const & a,
  242. point_type const & b,
  243. point_type const & c) : plane_t( a, glm::cross( displacement(b,a), displacement(c,a)) )
  244. {
  245. }
  246. /**
  247. * @brief closestPoint
  248. * @param p
  249. * @return
  250. *
  251. * Returns the point on the plane that is closest to x
  252. */
  253. point_type closestPoint(point_type const & x) const
  254. {
  255. //auto const & n = p.n;
  256. //auto const & d = p.d;
  257. return x + (( d + glm::dot(n, vec3(x.x,x.y,x.z) ) )/glm::dot(n,n)) * n;
  258. }
  259. vec_type n = vec_type{0,1,0};
  260. value_type d = 0;
  261. };
  262. /**
  263. * @brief displacement
  264. * @param p
  265. * @param P
  266. * @return
  267. *
  268. * Returns a vector when added to point x, will bring the point to plane P
  269. */
  270. template<typename T>
  271. inline glm::tvec3<T, glm::highp> displacement(point_t<T> const & x, plane_t<T> const & P)
  272. {
  273. auto const & n = P.n;
  274. auto const & d = P.d;
  275. return (( d + glm::dot(n, vec3(x.x,x.y,x.z) ) )/glm::dot(n,n)) * n;
  276. }
  277. template<typename T>
  278. inline glm::tvec3<T, glm::highp> displacement(plane_t<T> const & P, point_t<T> const & x)
  279. {
  280. return -displacement(x,P);
  281. }
  282. /**
  283. * @brief distance
  284. * @param x
  285. * @param P
  286. * @return
  287. *
  288. * Returns the distance between the point x and the plane P
  289. */
  290. template<typename T>
  291. inline T distance(point_t<T> const & x, plane_t<T> const & P)
  292. {
  293. auto const & n = P.n;
  294. auto const & d = P.d;
  295. return -(( d + glm::dot(n, vec3(x.x,x.y,x.z) ) )/glm::dot(n,n));
  296. }
  297. template<typename T>
  298. inline T distance(plane_t<T> const & P, point_t<T> const & x)
  299. {
  300. return distance(x,P);
  301. }
  302. /**
  303. * @brief intersection
  304. * @param P
  305. * @param L
  306. * @return
  307. *
  308. * Returns the intersection point of plane P and line L
  309. */
  310. template<typename T>
  311. inline point_t<T> intersection(plane_t<T> const & P, line_t<T> const & L)
  312. {
  313. auto t = (-P.d - glm::dot( P.n, L.p.asVec())) / glm::dot(P.n,L.v);
  314. return point_t<T>( L.p.asVec() + t*L.v );
  315. }
  316. using point = point_t<float>;
  317. using plane = plane_t<float>;
  318. using line = line_t<float>;
  319. using point3 = point_t<float>;
  320. using plane3 = plane_t<float>;
  321. using line3 = line_t<float>;
  322. template<typename T>
  323. class box_t
  324. {
  325. public:
  326. typedef T value_type;
  327. typedef glm::tvec3<value_type, glm::highp> vec_type;
  328. typedef point_t<value_type> point_type;
  329. box_t() : box_t( vec_type(0.5,0.5,0.5) )
  330. {
  331. }
  332. explicit box_t( vec_type const & _halfExtents) : half_extents(_halfExtents)
  333. {
  334. }
  335. /**
  336. * @brief plane_t
  337. * @param _p0
  338. * @param _n
  339. *
  340. * Construct a plane from a point and a normal
  341. */
  342. box_t( point_type const & _centre, vec_type const & _halfExtents) : centre(_centre), half_extents(_halfExtents)
  343. {
  344. }
  345. float operator()( vec_type const &p ) const
  346. {
  347. auto & b = half_extents;
  348. auto q = glm::abs(p) - b;
  349. return glm::length(glm::max(q,glm::vec3(0.0))) + glm::min(glm::max(q.x,glm::max(q.y,q.z)),0.0f);
  350. }
  351. point_type centre;
  352. vec_type half_extents;
  353. };
  354. /**
  355. * @brief distance
  356. * @param L
  357. * @param p
  358. * @return
  359. *
  360. * Calculates the distance between a line and a point.
  361. */
  362. template<typename T>
  363. inline T distance(box_t<T> const & L, point_t<T> const & p)
  364. {
  365. auto q = glm::abs(glm::vec3(p.x-L.centre.x,p.y-L.centre.y,p.z-L.centre.z) ) - L.half_extents;
  366. return glm::length( glm::max(q, static_cast<T>(0.0) )) + glm::min( glm::max( q.x, glm::max(q.y,q.z)), static_cast<T>(0.0) );
  367. }
  368. template<typename T>
  369. inline bool intersects(box_t<T> const & b, line_t<T> const & r)
  370. {
  371. T tmin = -INFINITY, tmax = INFINITY;
  372. auto b_min = b.centre.asVec() - b.half_extents;
  373. auto b_max = b.centre.asVec() + b.half_extents;
  374. if ( std::fabs(r.v.x) > static_cast<T>(0.001) )
  375. {
  376. auto tx1 = (b_min.x - r.p.x)/r.v.x;
  377. auto tx2 = (b_max.x - r.p.x)/r.v.x;
  378. tmin = glm::max(tmin, glm::min(tx1, tx2));
  379. tmax = glm::min(tmax, glm::max(tx1, tx2));
  380. }
  381. if ( std::fabs(r.v.y) > static_cast<T>(0.001) )
  382. {
  383. auto ty1 = (b_min.y - r.p.y)/r.v.y;
  384. auto ty2 = (b_max.y - r.p.y)/r.v.y;
  385. tmin = glm::max(tmin, glm::min(ty1, ty2));
  386. tmax = glm::min(tmax, glm::max(ty1, ty2));
  387. }
  388. if ( std::fabs(r.v.z) > static_cast<T>(0.001) )
  389. {
  390. auto ty1 = (b_min.z - r.p.z)/r.v.z;
  391. auto ty2 = (b_max.z - r.p.z)/r.v.z;
  392. tmin = glm::max(tmin, glm::min(ty1, ty2));
  393. tmax = glm::min(tmax, glm::max(ty1, ty2));
  394. }
  395. return tmax >= tmin;
  396. }
  397. template<typename T>
  398. class sphere_t
  399. {
  400. public:
  401. typedef T value_type;
  402. typedef glm::tvec3<value_type, glm::highp> vec_type;
  403. typedef point_t<value_type> point_type;
  404. sphere_t() : sphere_t( value_type(1) )
  405. {
  406. }
  407. explicit sphere_t( value_type _radius) : radius(_radius)
  408. {
  409. }
  410. /**
  411. * @brief plane_t
  412. * @param _p0
  413. * @param _n
  414. *
  415. * Construct a plane from a point and a normal
  416. */
  417. sphere_t( point_type const & _centre, value_type _radius) : centre(_centre), radius(_radius)
  418. {
  419. }
  420. point_type centre;
  421. value_type radius;
  422. };
  423. template<typename T>
  424. inline bool intersects(sphere_t<T> const & b, line_t<T> const & r)
  425. {
  426. return distance( r, point_t<T>(b.centre) ) <= b.radius;
  427. }
  428. }
  429. #endif