check if a sphere intersects a face
| 1594 | |
| 1595 | // check if a sphere intersects a face |
| 1596 | int check_sphere_to_face(vector *colp, vector *intp, float *col_dist, vector *wall_norm, const vector *p0, |
| 1597 | const vector *p1, vector *face_normal, int nv, float rad, vector **vertex_ptr_list) { |
| 1598 | uint32_t edgemask; |
| 1599 | |
| 1600 | ASSERT(nv > 0 && nv <= 32); // otherwise, we overflow the edgemask -- if we hit this we need to make edgemask a long |
| 1601 | // long and adjust the other functions accordingly |
| 1602 | |
| 1603 | // now do 2d check to see if point is inside the face (if so, we are done) |
| 1604 | edgemask = check_point_to_face(colp, face_normal, nv, vertex_ptr_list); |
| 1605 | |
| 1606 | // If we are inside edgemask is 0, we hit the face. |
| 1607 | if (edgemask == 0) { |
| 1608 | // mprintf(0, "CSTF Hit Face\n"); |
| 1609 | *col_dist = vm_VectorDistance(p0, intp); |
| 1610 | *wall_norm = *face_normal; |
| 1611 | return IT_FACE; |
| 1612 | } else { |
| 1613 | // Although the plane collision point is not in the face, we might hit an edge. |
| 1614 | // If the checkpoint collides with the edge of a face, it could |
| 1615 | // go a little farther before hitting anything |
| 1616 | |
| 1617 | vector *v0, *v1; |
| 1618 | int edgenum; |
| 1619 | |
| 1620 | // If we have no radius we could only hit the face and not an edge or point |
| 1621 | if (rad == 0.0) |
| 1622 | return IT_NONE; |
| 1623 | |
| 1624 | int f_hit = 0; |
| 1625 | vector c_end = *p1; |
| 1626 | |
| 1627 | // get verts for edge we're behind |
| 1628 | for (edgenum = 0; edgenum < nv; edgenum++) { |
| 1629 | if (edgemask & 1) { |
| 1630 | v0 = vertex_ptr_list[edgenum]; |
| 1631 | v1 = vertex_ptr_list[(edgenum + 1) % nv]; |
| 1632 | |
| 1633 | if (check_vector_to_cylinder(colp, intp, col_dist, wall_norm, p0, &c_end, rad, v0, v1)) { |
| 1634 | c_end = *intp; |
| 1635 | f_hit = 1; |
| 1636 | } |
| 1637 | } |
| 1638 | |
| 1639 | edgemask = edgemask >> 1; |
| 1640 | } |
| 1641 | |
| 1642 | return f_hit; |
| 1643 | } /* checkvec = *p0 - *v0; |
| 1644 | edgevec = *v1 - *v0; |
| 1645 | edgelen = vm_NormalizeVector(&edgevec); |
| 1646 | |
| 1647 | cur_dist = edgevec * checkvec; |
| 1648 | |
| 1649 | closest_point = *v0 + cur_dist * edgevec; |
| 1650 | |
| 1651 | // See if the sphere intersects the edge of the face |
| 1652 | if(!check_vector_to_sphere_1(intp, col_dist, p0, p1, &closest_point, rad, 1)) return IT_NONE; |
| 1653 | checkvec = *intp - *v0; |
no test coverage detected