//0: 0 intersection //1: 1 intersections //-1: infinite intersections int ray_rect(vec3 ray[], vec3 rect[], vec3 out) { int ret; vec3 v; vec3 plane[2]; float vx,vy,xx,yy; float* c = rect[0]; float* r = rect[1]; float* f = rect[2]; float* u = rect[3]; plane[0][0] = c[0]; plane[0][1] = c[1]; plane[0][2] = c[2]; plane[1][0] = u[0]; plane[1][1] = u[1]; plane[1][2] = u[2]; ret = ray_plane(ray, plane, out); if(ret <= 0)return ret; v[0] = out[0] - c[0]; v[1] = out[1] - c[1]; v[2] = out[2] - c[2]; vx= v[0]*r[0] + v[1]*r[1] + v[2]*r[2]; vy= v[0]*f[0] + v[1]*f[1] + v[2]*f[2]; xx= r[0]*r[0] + r[1]*r[1] + r[2]*r[2]; yy= f[0]*f[0] + f[1]*f[1] + f[2]*f[2]; if((vx>-xx)&&(vx<xx)&&(vy>-yy)&&(vy<yy))return 1; return 0; }
// assumes a parallelogram BOOL ray_quadrangle(const LLVector3 &ray_point, const LLVector3 &ray_direction, const LLVector3 &point_0, const LLVector3 &point_1, const LLVector3 &point_2, LLVector3 &intersection, LLVector3 &intersection_normal) { LLVector3 side_01 = point_1 - point_0; LLVector3 side_12 = point_2 - point_1; intersection_normal = side_01 % side_12; intersection_normal.normVec(); if (ray_plane(ray_point, ray_direction, point_0, intersection_normal, intersection)) { LLVector3 point_3 = point_0 + (side_12); LLVector3 side_23 = point_3 - point_2; LLVector3 side_30 = point_0 - point_3; if (intersection_normal * (side_01 % (intersection - point_0)) >= 0.0f && intersection_normal * (side_12 % (intersection - point_1)) >= 0.0f && intersection_normal * (side_23 % (intersection - point_2)) >= 0.0f && intersection_normal * (side_30 % (intersection - point_3)) >= 0.0f) { return TRUE; } } return FALSE; }
BOOL ray_circle(const LLVector3 &ray_point, const LLVector3 &ray_direction, const LLVector3 &circle_center, const LLVector3 plane_normal, F32 circle_radius, LLVector3 &intersection) { if (ray_plane(ray_point, ray_direction, circle_center, plane_normal, intersection)) { if (circle_radius >= (intersection - circle_center).magVec()) { return TRUE; } } return FALSE; }
/*! \brief A parabola-plane intersection test which ignores negative time intersections. \param T The origin of the ray relative to a point on the plane. \param D The direction/velocity of the ray. \param A The acceleration of the ray. \param N The normal of the plane. \param d The thickness of the plane. \return The time until the intersection, or HUGE_VAL if no intersection. */ inline double parabola_plane(const math::Vector& T, const math::Vector& D, const math::Vector& A, math::Vector N, const double d) { //Check if this is actually a ray-plane test double adot = A | N; if (adot == 0) return ray_plane(T, D, N, d); //Create the rest of the variables double rdot = T | N; //Ensure that the normal is pointing towards the particle //position (so that (rdot < d) is a test if the particle is //overlapped) if (rdot < 0) { adot = -adot; rdot = -rdot; N = -N; } double vdot = D | N; //Check for overlapped and approaching dynamics if ((rdot <= d) && (vdot < 0)) return 0; double arg = vdot * vdot - 2 * (rdot - d) * adot; double minimum = - vdot / adot; if (adot < 0) { //Particle will always hit the wall //If there are no real roots, the particle is arcing inside //the wall and there is a collision at the minimum if (arg < 0) return minimum; std::pair<double, double> roots = magnet::math::quadraticEquation(0.5 * adot, vdot, rdot - d); return std::max(roots.first, roots.second); } else { //Particle can curve away from the wall //Check if the particle misses the wall completely or we're //passed the minimum if ((arg < 0) || (minimum < 0)) return HUGE_VAL; std::pair<double, double> roots = magnet::math::quadraticEquation(0.5 * adot, vdot, rdot - d); return std::min(roots.first, roots.second); } }