BsTorus.cpp 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. #include "BsTorus.h"
  2. #include "BsRay.h"
  3. #include "BsMath.h"
  4. namespace BansheeEngine
  5. {
  6. Torus::Torus(float outerRadius, float innerRadius)
  7. :outerRadius(outerRadius), innerRadius(innerRadius)
  8. { }
  9. std::pair<bool, float> Torus::intersects(const Ray& ray) const
  10. {
  11. const Vector3& org = ray.getOrigin();
  12. const Vector3& dir = ray.getDirection();
  13. float a = org.dot(dir);
  14. float b = org.dot(org);
  15. float outerSqrd = outerRadius*outerRadius;
  16. float innerSqrd = innerRadius*innerRadius;
  17. float K = a - innerSqrd - outerSqrd;
  18. float E = 1.0f;
  19. float D = 4 * b;
  20. float C = 2 * (2 * b*b + K + 2 * outerSqrd*dir.z*dir.z);
  21. float B = 4 * (K*b + 2 * outerSqrd*org.z*dir.z);
  22. float A = K*K + 4 * outerSqrd*(org.z*org.z - innerSqrd);
  23. float roots[4];
  24. UINT32 numRoots = Math::solveQuartic(A, B, C, D, E, roots);
  25. if (numRoots > 0)
  26. {
  27. float nearestT = std::numeric_limits<float>::max();
  28. for (UINT32 i = 0; i < numRoots; i++)
  29. {
  30. float t = roots[i];
  31. float x = org.x + t*dir.x;
  32. float y = org.x + t*dir.y;
  33. float l = outerRadius*(Math::PI / 2 - Math::atan2(y, x).valueRadians());
  34. if (l >= 0 && t < nearestT)
  35. nearestT = t;
  36. }
  37. return std::make_pair(true, nearestT);
  38. }
  39. return std::make_pair(false, 0.0f);
  40. }
  41. }