Intersection3.cpp
上传用户:chinafayin
上传日期:2022-04-05
资源大小:153k
文件大小:8k
源码类别:

并行计算

开发平台:

Visual C++

  1. /*
  2.     Linear Algebra / Math library
  3.     Copyright (C) 2003-2009, Marek Olsak (maraeo@gmail.com), All Rights Reserved.
  4.     Copyright (C) 2003-2005, Tomas Pastorek (tomas@tomaspastorek.cz), All Rights Reserved.
  5.     This program is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU General Public License
  7.     as published by the Free Software Foundation; either version 2
  8.     of the License, or (at your option) any later version.
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.     You should have received a copy of the GNU General Public License
  14.     along with this program; if not, write to the Free Software
  15.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  16. */
  17. #include "../All.h"
  18. // AABB = axis-aligned bounding box
  19. namespace Rune
  20. {
  21.     /**
  22.         Spocita kolizi AABB a bodu
  23.     **************************************************************************************************/
  24.     template<typename T>
  25.     RUNEMATH_API bool Intersect(const AxisAlignedBox3<T> &b, const Vec3<T> &p)
  26.     {
  27.         return p >= b.min && p <= b.max;
  28.     }
  29.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<float> &b, const Vec3<float> &p);
  30.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<double> &b, const Vec3<double> &p);
  31.     /**
  32.         Spocita kolizi dvou AABB
  33.     **************************************************************************************************/
  34.     template<typename T>
  35.     RUNEMATH_API bool Intersect(const AxisAlignedBox3<T> &b1, const AxisAlignedBox3<T> &b2)
  36.     {
  37.         if (b1.max.x < b2.min.x || b1.min.x > b2.max.x) return false;
  38.         if (b1.max.y < b2.min.y || b1.min.y > b2.max.y) return false;
  39.         if (b1.max.z < b2.min.z || b1.min.z > b2.max.z) return false;
  40.         return true;
  41.     }
  42.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<float> &b1, const AxisAlignedBox3<float> &b2);
  43.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<double> &b1, const AxisAlignedBox3<double> &b2);
  44.     /**
  45.         Spocita kolizi AABB a koule
  46.     **************************************************************************************************/
  47.     template<typename T>
  48.     RUNEMATH_API bool Intersect(const AxisAlignedBox3<T> &b, const Sphere3<T> &s)
  49.     {
  50.         T dist = 0;
  51.         if (s.pos.x < b.min.x)      dist += Math<T>::Sqr(s.pos.x - b.min.x);
  52.         else if (s.pos.x > b.max.x) dist += Math<T>::Sqr(s.pos.x - b.max.x);
  53.         if (s.pos.y < b.min.y)      dist += Math<T>::Sqr(s.pos.y - b.min.y);
  54.         else if (s.pos.y > b.max.y) dist += Math<T>::Sqr(s.pos.y - b.max.y);
  55.         if (s.pos.z < b.min.z)      dist += Math<T>::Sqr(s.pos.z - b.min.z);
  56.         else if (s.pos.z > b.max.z) dist += Math<T>::Sqr(s.pos.z - b.max.z);
  57.         return dist <= s.radius*s.radius;
  58.     }
  59.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<float> &b, const Sphere3<float> &s);
  60.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<double> &b, const Sphere3<double> &s);
  61.     /**
  62.         Spocita kolizi AABB a koule
  63.     **************************************************************************************************/
  64.     template<typename T>
  65.     RUNEMATH_API bool Intersect(const AxisAlignedBox3<T> &b, Interior bi, const Sphere3<T> &s, Interior si)
  66.     {
  67.         switch (si)
  68.         {
  69.         case SOLID:
  70.             switch (bi)
  71.             {
  72.             case SOLID:
  73.                 return Intersect(b, s);
  74.             case HOLLOW:
  75.                 {
  76.                     T dist = 0;
  77.                     bool face = false;
  78.                     if (s.pos.x < b.min.x)      { dist += Math<T>::Sqr(s.pos.x - b.min.x); face = true; }
  79.                     else if (s.pos.x > b.max.x) { dist += Math<T>::Sqr(s.pos.x - b.max.x); face = true; }
  80.                     else if (s.pos.x - b.min.x <= s.radius) face = true;
  81.                     else if (b.max.x - s.pos.x <= s.radius) face = true;
  82.                     if (s.pos.y < b.min.y)      { dist += Math<T>::Sqr(s.pos.y - b.min.y); face = true; }
  83.                     else if (s.pos.y > b.max.y) { dist += Math<T>::Sqr(s.pos.y - b.max.y); face = true; }
  84.                     else if (s.pos.y - b.min.y <= s.radius) face = true;
  85.                     else if (b.max.y - s.pos.y <= s.radius) face = true;
  86.                     if (s.pos.z < b.min.z)      { dist += Math<T>::Sqr(s.pos.z - b.min.z); face = true; }
  87.                     else if (s.pos.z > b.max.z) { dist += Math<T>::Sqr(s.pos.z - b.max.z); face = true; }
  88.                     else if (s.pos.z - b.min.z <= s.radius) face = true;
  89.                     else if (b.max.z - s.pos.z <= s.radius) face = true;
  90.                     return face && dist <= s.radius*s.radius;
  91.                 }
  92.             }
  93.         case HOLLOW:
  94.             {
  95.                 T minX = Math<T>::Sqr(s.pos.x - b.min.x);
  96.                 T maxX = Math<T>::Sqr(s.pos.x - b.max.x);
  97.                 T minY = Math<T>::Sqr(s.pos.y - b.min.y);
  98.                 T maxY = Math<T>::Sqr(s.pos.y - b.max.y);
  99.                 T minZ = Math<T>::Sqr(s.pos.z - b.min.z);
  100.                 T maxZ = Math<T>::Sqr(s.pos.z - b.max.z);
  101.                 bool outsideX = s.pos.x < b.min.x || s.pos.x > b.max.x;
  102.                 bool outsideY = s.pos.y < b.min.y || s.pos.y > b.max.y;
  103.                 bool outsideZ = s.pos.z < b.min.z || s.pos.z > b.max.z;
  104.                 T x = Math<T>::Min(minX, maxX);
  105.                 T y = Math<T>::Min(minY, maxY);
  106.                 T z = Math<T>::Min(minZ, maxZ);
  107.                 T distMin = 0;
  108.                 if (outsideX) distMin += x;
  109.                 if (outsideY) distMin += y;
  110.                 if (outsideZ) distMin += z;
  111.                 T rSq = s.radius*s.radius;
  112.                 if (distMin > rSq)
  113.                     return false;
  114.                 T distMax = Math<T>::Max(minX, maxX) +
  115.                             Math<T>::Max(minY, maxY) +
  116.                             Math<T>::Max(minZ, maxZ);
  117.                 switch (bi)
  118.                 {
  119.                 case SOLID:
  120.                     return rSq <= distMax;
  121.                 case HOLLOW:
  122.                     return rSq <= distMax && (outsideX || outsideY || outsideZ || x <= rSq || y <= rSq || z <= rSq);
  123.                 }
  124.             }
  125.         }
  126.         return false;
  127.     }
  128.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<float> &b, Interior bi, const Sphere3<float> &s, Interior si);
  129.     template RUNEMATH_API bool Intersect(const AxisAlignedBox3<double> &b, Interior bi, const Sphere3<double> &s, Interior si);
  130.     /**
  131.         Spocita kolizi dvou kouli
  132.     **************************************************************************************************/
  133.     template<typename T>
  134.     RUNEMATH_API bool Intersect(const Sphere3<T> s1, const Sphere3<T> &s2)
  135.     {
  136.         T d = Math<T>::Sqr(s1.pos.x-s2.pos.x) + Math<T>::Sqr(s1.pos.y-s2.pos.y) + Math<T>::Sqr(s1.pos.z-s2.pos.z);
  137.         return d <= Math<T>::Sqr(s1.radius+s2.radius);
  138.     }
  139.     template RUNEMATH_API bool Intersect(const Sphere3<float> s1, const Sphere3<float> &s2);
  140.     template RUNEMATH_API bool Intersect(const Sphere3<double> s1, const Sphere3<double> &s2);
  141.     /**
  142.         Spocita kolizi dvou kouli, vraci navic bod dotyku kouli
  143.     **************************************************************************************************/
  144.     template<typename T>
  145.     RUNEMATH_API bool Intersect(const Sphere3<T> &s1, const Sphere3<T> &s2, Vec3<T> &point)
  146.     {
  147.         if (Intersect(s1, s2))
  148.         {
  149.             Vec3<T> dir = s1.pos - s2.pos;
  150.             dir.Normalize();
  151.             point = s2.pos + dir * s2.radius;
  152.             return true;
  153.         }
  154.         return false;
  155.     }
  156.     template RUNEMATH_API bool Intersect(const Sphere3<float> &s1, const Sphere3<float> &s2, Vec3<float> &point);
  157.     template RUNEMATH_API bool Intersect(const Sphere3<double> &s1, const Sphere3<double> &s2, Vec3<double> &point);
  158.     /**
  159.         Spocita kolizi koule a bodu
  160.     **************************************************************************************************/
  161.     template<typename T>
  162.     RUNEMATH_API bool Intersect(const Sphere3<T> &s, const Vec3<T> &point)
  163.     {
  164.         return Vec3<T>::DistanceSqr(s.pos, point) < s.radius * s.radius;
  165.     }
  166.     template RUNEMATH_API bool Intersect(const Sphere3<float> &s, const Vec3<float> &point);
  167.     template RUNEMATH_API bool Intersect(const Sphere3<double> &s, const Vec3<double> &point);
  168. }