mathutil.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include "qrad.h"
  2. #define NUM_LERP_POINTS 4 //used by PointInWall (defines magic number)
  3. //===============================================
  4. // PointInEdge - base for all boundary checks
  5. //===============================================
  6. inline bool PointInEdge(const vec_t* const point, const vec_t* const p1, const vec_t* const p2, const vec_t* const normal)
  7. {
  8. vec3_t edge, temp, temp2; //don't make static because we need multithread support
  9. VectorSubtract(p1,p2,edge);
  10. VectorSubtract(p1,point,temp);
  11. CrossProduct(edge,temp,temp2);
  12. //old code normalizes here, which is useless when detecting sign change below
  13. return (DotProduct(temp2,normal) >= 0);
  14. }
  15. //===============================================
  16. // PointInWall - check a lerpWall_t boundary
  17. //===============================================
  18. inline bool PointInWall(const lerpWall_t* const wall, const vec_t* const point)
  19. {
  20. for(int counter = 0; counter < NUM_LERP_POINTS; counter++)
  21. {
  22. if(!PointInEdge(point,wall->vertex[counter],wall->vertex[(counter+1)%4],wall->plane.normal))
  23. { return false; }
  24. }
  25. return true;
  26. }
  27. //===============================================
  28. // PointInWall - check a Winding boundary
  29. //===============================================
  30. inline bool PointInWinding(const Winding* const W, const dplane_t* const plane, const vec_t* const point)
  31. {
  32. //reverse direction of points because plane input is 180 degrees from desired normal
  33. for(size_t counter = 0; counter < W->m_NumPoints-1; counter++)
  34. {
  35. if(!PointInEdge(point,W->m_Points[counter+1],W->m_Points[counter],plane->normal))
  36. { return false; }
  37. }
  38. return PointInEdge(point,W->m_Points[0],W->m_Points[W->m_NumPoints-1],plane->normal);
  39. }
  40. //==================================================
  41. // PointInTri - check a boundary defined by 3 points
  42. //==================================================
  43. inline bool PointInTri(const vec_t* const point, const dplane_t* const plane, const vec_t* const p1, const vec_t* const p2, const vec_t* const p3)
  44. {
  45. return (PointInEdge(point,p1,p2,plane->normal) && PointInEdge(point,p2,p3,plane->normal) && PointInEdge(point,p3,p1,plane->normal));
  46. }
  47. //==================================================
  48. // LineSegmentIntersectsBounds - does the line pass through the box?
  49. //==================================================
  50. inline bool LineSegmentIntersectsBounds(const vec_t* const p1, const vec_t* const p2, const vec3_t& mins, const vec3_t& maxs)
  51. {
  52. vec_t tNear = -999999999;
  53. vec_t tFar = 999999999;
  54. vec_t t0,t1,tmp;
  55. vec3_t d;
  56. VectorSubtract(p2,p1,d);
  57. for(int index = 0; index < 3; ++index)
  58. {
  59. if(fabs(d[index]) < EQUAL_EPSILON)
  60. {
  61. if(p1[index] < (mins[index] - EQUAL_EPSILON) || p1[index] > (maxs[index] + EQUAL_EPSILON))
  62. {
  63. return false;
  64. }
  65. continue;
  66. }
  67. t0 = (mins[index] - p1[index]) / d[index];
  68. t1 = (maxs[index] - p1[index]) / d[index];
  69. if(t0 > t1)
  70. {
  71. tmp = t1;
  72. t1 = t0;
  73. t0 = tmp;
  74. }
  75. if(t0 > tNear)
  76. {
  77. tNear = t0;
  78. }
  79. if(t1 < tFar)
  80. {
  81. tFar = t1;
  82. }
  83. if(tNear > tFar || tFar < 0)
  84. {
  85. return false;
  86. }
  87. }
  88. return true;
  89. }
  90. //==================================================
  91. // LineSegmentIntersectsFace - does the face block the segment?
  92. //==================================================
  93. inline bool LineSegmentIntersectsFace(const vec_t* const p1, const vec_t* const p2, vec3_t& point_out, const int index)
  94. {
  95. if(LineSegmentIntersectsBounds(p1,p2,g_opaque_face_list[index].mins,g_opaque_face_list[index].maxs))
  96. {
  97. if(LineSegmentIntersectsPlane(g_opaque_face_list[index].plane,p1,p2,point_out))
  98. {
  99. if(PointInWinding(g_opaque_face_list[index].winding,&g_opaque_face_list[index].plane,point_out))
  100. {
  101. return true;
  102. }
  103. }
  104. }
  105. return false;
  106. }
  107. //==================================================
  108. // LineSegmentIntersectsPlane - returns intersection
  109. // point in point parameter if it exists
  110. //==================================================
  111. inline bool LineSegmentIntersectsPlane(const dplane_t& plane, const vec_t* const p1, const vec_t* const p2, vec3_t& point)
  112. {
  113. vec3_t line;
  114. VectorSubtract(p2,p1,line);
  115. vec_t dist1 = DotProduct(plane.normal,line); //p1 to p2
  116. if(dist1 == 0.0) //parallel
  117. { return false; }
  118. vec3_t origin;
  119. VectorScale(plane.normal,plane.dist,origin);
  120. VectorSubtract(origin,p1,origin);
  121. vec_t loc = DotProduct(plane.normal,origin)/dist1; //p1 to plane
  122. if(loc < 0 || loc > 1) //if we're over 100% or
  123. { return false; } //under 0% of original length
  124. VectorMA(p1,loc,line,point);
  125. return true;
  126. }
  127. //==================================================
  128. // PlaneFromPoints
  129. //==================================================
  130. inline void PlaneFromPoints(const vec_t* const p1, const vec_t* const p2, const vec_t* const p3, dplane_t* plane)
  131. {
  132. vec3_t temp, temp2;
  133. VectorSubtract(p3,p2,temp);
  134. VectorSubtract(p1,p2,temp2);
  135. CrossProduct(temp,temp2,plane->normal);
  136. VectorNormalize(plane->normal);
  137. plane->dist = DotProduct(plane->normal,p1);
  138. }
  139. //==================================================
  140. // SnapToPlane
  141. //==================================================
  142. inline void SnapToPlane(const dplane_t* const plane, vec_t* const point, const vec_t offset)
  143. {
  144. vec_t scale = (plane->dist + offset);
  145. scale -= DotProduct(plane->normal,point);
  146. VectorMA(point,scale,plane->normal,point);
  147. }
  148. // =====================================================================================
  149. // TestSegmentAgainstOpaqueList
  150. // Returns facenum of the opaque face if the segment intersects an item in the opaque list
  151. // =====================================================================================
  152. #ifdef HLRAD_HULLU
  153. int TestSegmentAgainstOpaqueList(const vec_t* p1, const vec_t* p2, vec3_t &scaleout)
  154. #else
  155. int TestSegmentAgainstOpaqueList(const vec_t* p1, const vec_t* p2)
  156. #endif
  157. {
  158. unsigned x;
  159. vec3_t point;
  160. const dplane_t* plane;
  161. const Winding* winding;
  162. int returnVal = -1;
  163. int facenum;
  164. //vec_t* endpoint;
  165. bool blocked = false;
  166. //*endpoint = *p2;
  167. #ifdef HLRAD_HULLU
  168. VectorFill(scaleout,1.0);
  169. #endif
  170. for (x = 0; x < g_opaque_face_count; x++)
  171. {
  172. plane = &g_opaque_face_list[x].plane;
  173. winding = g_opaque_face_list[x].winding;
  174. facenum = g_opaque_face_list[x].facenum;
  175. // if(LineSegmentIntersectsFace(p1,endpoint,point,x))
  176. if(LineSegmentIntersectsFace(p1,p2,point,x))
  177. {
  178. #ifdef HLRAD_HULLU
  179. if(g_opaque_face_list[x].transparency)
  180. {
  181. VectorMultiply(scaleout, g_opaque_face_list[x].transparency_scale, scaleout);
  182. //don't change endpoint here -- only if face completely blocks light
  183. }
  184. else
  185. {
  186. //can't break here because we might be blocked more than one time,
  187. //continue searching for earliest blocking face
  188. //*endpoint = *point;
  189. returnVal = facenum;
  190. blocked = true;
  191. }
  192. #else
  193. *endpoint = *point;
  194. returnVal = facenum;
  195. blocked = true;
  196. #endif
  197. }
  198. }
  199. if(blocked)
  200. {
  201. return returnVal; //return face that intersects the segment closest to p1
  202. }
  203. #ifdef HLRAD_HULLU
  204. if(VectorCompare(scaleout,vec3_origin))
  205. {
  206. VectorClear(scaleout);
  207. }
  208. #endif
  209. return -1; //not completely blocked
  210. }