| 260 | } |
| 261 | |
| 262 | static inline bool intersectcylinder(const vec &from, const vec &to, const vec &start, const vec &end, float radius, float &dist) |
| 263 | { |
| 264 | vec d(end), m(from), n(to); |
| 265 | d.sub(start); |
| 266 | m.sub(start); |
| 267 | n.sub(from); |
| 268 | float md = m.dot(d), |
| 269 | nd = n.dot(d), |
| 270 | dd = d.squaredlen(); |
| 271 | if(md < 0 && md + nd < 0) return false; |
| 272 | if(md > dd && md + nd > dd) return false; |
| 273 | float nn = n.squaredlen(), |
| 274 | mn = m.dot(n), |
| 275 | a = dd*nn - nd*nd, |
| 276 | k = m.squaredlen() - radius*radius, |
| 277 | c = dd*k - md*md; |
| 278 | if(fabs(a) < 0.005f) |
| 279 | { |
| 280 | if(c > 0) return false; |
| 281 | if(md < 0) dist = -mn / nn; |
| 282 | else if(md > dd) dist = (nd - mn) / nn; |
| 283 | else dist = 0; |
| 284 | return true; |
| 285 | } |
| 286 | else if(c > 0) |
| 287 | { |
| 288 | float b = dd*mn - nd*md, |
| 289 | discrim = b*b - a*c; |
| 290 | if(discrim < 0) return false; |
| 291 | dist = (-b - sqrtf(discrim)) / a; |
| 292 | } |
| 293 | else dist = 0; |
| 294 | float offset = md + dist*nd; |
| 295 | if(offset < 0) |
| 296 | { |
| 297 | if(nd <= 0) return false; |
| 298 | dist = -md / nd; |
| 299 | if(k + dist*(2*mn + dist*nn) > 0) return false; |
| 300 | } |
| 301 | else if(offset > dd) |
| 302 | { |
| 303 | if(nd >= 0) return false; |
| 304 | dist = (dd - md) / nd; |
| 305 | if(k + dd - 2*md + dist*(2*(mn-nd) + dist*nn) > 0) return false; |
| 306 | } |
| 307 | return dist >= 0 && dist <= 1; |
| 308 | } |
| 309 | |
| 310 | |
| 311 | int intersect(playerent *d, const vec &from, const vec &to, vec *end) |
no test coverage detected