boxcol.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "boxcol.h"
  2. #include "..\common_h\render.h"
  3. #define LOCAL_EPSILON 0.000001f
  4. SlowBoxCollider::SlowBoxCollider ()
  5. {
  6. BoxMin = Vector(0.0f);
  7. BoxMax = Vector(0.0f);
  8. transform = Matrix ();
  9. }
  10. SlowBoxCollider::~SlowBoxCollider ()
  11. {
  12. }
  13. void SlowBoxCollider::Init (const Vector& BoxMin, const Vector& BoxMax, const Matrix& transform)
  14. {
  15. this->BoxMin = BoxMin;
  16. this->BoxMax = BoxMax;
  17. this->transform = transform;
  18. }
  19. bool SlowBoxCollider::dsRayTriOverlapUseDistance (const Vector &v0, const Vector &v1, const Vector &v2, float &tri_dist, const Vector& v_from, const Vector& v_to)
  20. {
  21. //-------- make math ray------------
  22. Vector direction;
  23. Vector origin;
  24. float max_dist;
  25. Vector r = (v_to - v_from );
  26. max_dist = sqrtf (r.x * r.x + r.y * r.y + r.z * r.z);
  27. origin = v_from;
  28. direction = !r;
  29. //-------- make math ray------------
  30. // Find vectors for two edges sharing vert0
  31. Vector edge1 = v1 - v0;
  32. Vector edge2 = v2 - v0;
  33. //------ Учитываем, что луч может быть ограничен по длинне
  34. Vector plane = edge2 ^ edge1;
  35. plane = !plane;
  36. double plane_dist = -(v0 | plane);
  37. double Denom = plane | direction;
  38. if(Denom>-LOCAL_EPSILON && Denom<LOCAL_EPSILON) return false;
  39. double ttrid = -((plane_dist + (plane | origin )) / Denom);
  40. tri_dist = (float)ttrid;
  41. //if (tri_dist < 0 || tri_dist > max_dist) return false;
  42. //---------------------
  43. // Begin calculating determinant - also used to calculate U parameter
  44. Vector pvec = direction^edge2;
  45. // If determinant is near zero, ray lies in plane of triangle
  46. double det = edge1|pvec;
  47. // the non-culling branch
  48. if(det>-LOCAL_EPSILON && det<LOCAL_EPSILON) return false;
  49. double inv_det = 1.0f / det;
  50. // Calculate distance from vert0 to ray origin
  51. Vector tvec = origin - v0;
  52. // Calculate U parameter and test bounds
  53. double mU = (tvec|pvec) * inv_det;
  54. if (mU < 0.0 || mU > 1.0) return false;
  55. // prepare to test V parameter
  56. Vector qvec = tvec^edge1;
  57. // Calculate V parameter and test bounds
  58. double mV = (direction|qvec) * inv_det;
  59. if (mV < 0.0 || (mU+mV) > 1.0) return false;
  60. // Calculate distance
  61. /*
  62. float mDistance = (edge2|qvec) * inv_det;
  63. */
  64. //tri_dist = (edge2|qvec) * inv_det;
  65. //if (tri_dist < 0 || tri_dist > distance) return false;
  66. return true;
  67. }
  68. float SlowBoxCollider::RayTrace (const Vector& from, const Vector& to)
  69. {
  70. IntersectionPoint = Vector (0.0f);
  71. Vector v[8];
  72. v[0] = Vector (BoxMax.x, BoxMax.y, BoxMax.z);
  73. v[1] = Vector (BoxMax.x, BoxMax.y, BoxMin.z);
  74. v[2] = Vector (BoxMin.x, BoxMax.y, BoxMax.z);
  75. v[3] = Vector (BoxMin.x, BoxMax.y, BoxMin.z);
  76. v[4] = Vector (BoxMax.x, BoxMin.y, BoxMax.z);
  77. v[5] = Vector (BoxMax.x, BoxMin.y, BoxMin.z);
  78. v[6] = Vector (BoxMin.x, BoxMin.y, BoxMax.z);
  79. v[7] = Vector (BoxMin.x, BoxMin.y, BoxMin.z);
  80. IndexTriangle Cube[12];
  81. Cube[0].a = 1; Cube[0].b = 4; Cube[0].c = 3;
  82. Cube[1].a = 1; Cube[1].b = 2; Cube[1].c = 4;
  83. Cube[2].a = 5; Cube[2].b = 2; Cube[2].c = 1;
  84. Cube[3].a = 5; Cube[3].b = 6; Cube[3].c = 2;
  85. Cube[4].a = 7; Cube[4].b = 5; Cube[4].c = 8;
  86. Cube[5].a = 5; Cube[5].b = 6; Cube[5].c = 8;
  87. Cube[6].a = 7; Cube[6].b = 1; Cube[6].c = 3;
  88. Cube[7].a = 7; Cube[7].b = 5; Cube[7].c = 1;
  89. Cube[8].a = 8; Cube[8].b = 4; Cube[8].c = 2;
  90. Cube[9].a = 8; Cube[9].b = 2; Cube[9].c = 6;
  91. Cube[10].a = 7; Cube[10].b = 3; Cube[10].c = 4;
  92. Cube[11].a = 7; Cube[11].b = 4; Cube[11].c = 8;
  93. for (int i = 0; i < 8; i++)
  94. {
  95. v[i] = v[i] * transform;
  96. }
  97. for (i = 0; i < 12; i++)
  98. {
  99. Cube[i].a = Cube[i].a - 1;
  100. Cube[i].b = Cube[i].b - 1;
  101. Cube[i].c = Cube[i].c - 1;
  102. }
  103. float MinDistance = -1.0f;
  104. float TriDist = 0.0f;
  105. IRender* pRS = (IRender*)api->GetService("DX9Render");
  106. for (int n = 0; n < 12; n++)
  107. {
  108. //pRS->DrawBufferedLine(v[Cube[n].a], 0xFFFF0000, v[Cube[n].b], 0xFFFF0000);
  109. //pRS->DrawBufferedLine(v[Cube[n].b], 0xFFFF0000, v[Cube[n].c], 0xFFFF0000);
  110. //pRS->DrawBufferedLine(v[Cube[n].c], 0xFFFF0000, v[Cube[n].a], 0xFFFF0000);
  111. bool res = dsRayTriOverlapUseDistance (v[Cube[n].a], v[Cube[n].b], v[Cube[n].c], TriDist, from, to);
  112. Vector direction;
  113. Vector origin;
  114. float max_dist;
  115. Vector r = (to - from );
  116. max_dist = sqrtf (r.x * r.x + r.y * r.y + r.z * r.z);
  117. origin = from;
  118. direction = !r;
  119. if (res)
  120. {
  121. if (MinDistance < 0)
  122. {
  123. MinDistance = TriDist;
  124. IntersectionPoint = origin + (direction * MinDistance);
  125. } else
  126. {
  127. if (TriDist < MinDistance)
  128. {
  129. MinDistance = TriDist;
  130. IntersectionPoint = origin + (direction * MinDistance);
  131. }
  132. }
  133. }
  134. }
  135. return MinDistance;
  136. }