kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out) { kmVec2 intersect; kmVec2 final_intersect; kmVec2 normal; kmScalar distance = 10000.0f; kmBool intersected = KM_FALSE; if(kmRay2IntersectLineSegment(ray, p1, p2, &intersect)) { intersected = KM_TRUE; kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); if(this_distance < distance) { final_intersect.x = intersect.x; final_intersect.y = intersect.y; distance = this_distance; calculate_line_normal(*p1, *p2, &normal); } } if(kmRay2IntersectLineSegment(ray, p2, p3, &intersect)) { intersected = KM_TRUE; kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); if(this_distance < distance) { final_intersect.x = intersect.x; final_intersect.y = intersect.y; distance = this_distance; calculate_line_normal(*p2, *p3, &normal); } } if(kmRay2IntersectLineSegment(ray, p3, p1, &intersect)) { intersected = KM_TRUE; kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); if(this_distance < distance) { final_intersect.x = intersect.x; final_intersect.y = intersect.y; distance = this_distance; calculate_line_normal(*p3, *p1, &normal); } } if(intersected) { intersection->x = final_intersect.x; intersection->y = final_intersect.y; if(normal_out) { normal_out->x = normal.x; normal_out->y = normal.y; } } return intersected; }
kmBool kmRay2IntersectBox(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, const kmVec2* p4, kmVec2* intersection, kmVec2* normal_out) { kmBool intersected = KM_FALSE; kmVec2 intersect, final_intersect, normal; kmScalar distance = 10000.0f; const kmVec2* points[4]; points[0] = p1; points[1] = p2; points[2] = p3; points[3] = p4; unsigned int i = 0; for(; i < 4; ++i) { const kmVec2* this_point = points[i]; const kmVec2* next_point = (i == 3) ? points[0] : points[i+1]; const kmVec2* other_point = (i == 3 || i == 0) ? points[1] : points[0]; if(kmRay2IntersectLineSegment(ray, this_point, next_point, &intersect)) { kmVec2 tmp; kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start)); kmVec2 this_normal; calculate_line_normal(*this_point, *next_point, *other_point, &this_normal); if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) { kmVec2Assign(&final_intersect, &intersect); distance = this_distance; intersected = KM_TRUE; kmVec2Assign(&normal, &this_normal); } } } if(intersected) { intersection->x = final_intersect.x; intersection->y = final_intersect.y; if(normal_out) { normal_out->x = normal.x; normal_out->y = normal.y; } } return intersected; }