// box intersect face and return intersection distance, point and normal public override bool BoxIntersect(CollisionBox ray_box, Vector3 ray_origin, Vector3 ray_direction, Vector3[] vert_pos, out float intersect_distance, out Vector3 intersect_position, out Vector3 intersect_normal) { intersect_distance = float.MaxValue; intersect_position = ray_origin; intersect_normal = Vector3.Zero; bool intersected = false; Vector3 p1, p2, p3, p4; uint i, j; CollisionBox world_box = new CollisionBox(ray_box.min + ray_origin, ray_box.max + ray_origin); Vector3[] box_verts = world_box.GetVertices(); Vector3[] box_edges = world_box.GetEdges(); // intersect box edges to face edges for (i = 0; i < 12; i++) { // cull edges with normal more than 135 degree from moving direction if (Vector3.Dot(CollisionBox.edge_normals[i], ray_direction) < -0.70710678) continue; p1 = box_edges[i * 2]; p2 = box_edges[i * 2 + 1]; p4 = vert_pos[vertices[0]]; for (j = 0; j < vertices.Length; j++) { p3 = p4; p4 = vert_pos[vertices[(j + 1) % vertices.Length]]; float distance; Vector3 position; if (CollisionFace.EdgeIntersect(p1, p2, ray_direction, p3, p4, out distance, out position)) { if (distance < intersect_distance) { intersect_distance = distance; intersect_position = position; intersect_normal = Vector3.Normalize(Vector3.Cross(p2-p1,p3-p4)); if (Vector3.Dot(ray_direction, intersect_normal) > 0) intersect_normal = Vector3.Negate(intersect_normal); intersected = true; } } } } // intersect from face vertices to box for (i = 0; i < 3; i++) { float tnear, tfar; p1 = vert_pos[vertices[i]]; int box_face_id = world_box.RayIntersect(p1, -ray_direction, out tnear, out tfar); if (box_face_id > -1) { if (tnear < intersect_distance) { intersect_distance = tnear; intersect_position = p1; intersect_normal = -CollisionBox.face_normals[box_face_id]; intersected = true; } } } // intersect from box vertices to face polygon Vector3 v1 = vert_pos[vertices[0]]; Vector3 v2 = vert_pos[vertices[1]]; Vector3 v3 = vert_pos[vertices[2]]; for (i = 0; i < 8; i++) { // cull vertices with normal more than 135 degree from moving direction if (Vector3.Dot(CollisionBox.vertex_normals[i], ray_direction) < -0.70710678) continue; Vector3 uvt; if (CollisionFace.RayTriangleIntersect(box_verts[i], ray_direction, v1, v2, v3, out uvt.Z, out uvt.X, out uvt.Y)) { if (uvt.Z < intersect_distance) { intersect_distance = uvt.Z; intersect_position = (1.0f - uvt.X - uvt.Y) * v1 + uvt.X * v2 + uvt.Y * v3; intersect_normal = Vector3.Normalize(Vector3.Cross(v3 - v1, v2 - v1)); intersected = true; } } } return intersected; }
// box intersect face and return intersection distance, point and normal public override bool BoxIntersect( CollisionBox rayBox, Vector3 rayOrigin, Vector3 rayDirection, Vector3[] vertices, out float intersectDistance, out Vector3 intersectPosition, out Vector3 intersectNormal) { intersectDistance = float.MaxValue; intersectPosition = rayOrigin; intersectNormal = Vector3.Zero; bool intersected = false; Vector3 p1, p2, p3, p4; uint i, j; CollisionBox worldBox = new CollisionBox(rayBox.min + rayOrigin, rayBox.max + rayOrigin); Vector3[] boxVerts = worldBox.GetVertices(); Vector3[] boxEdges = worldBox.GetEdges(); float distance; Vector3 position; // intersect box edges to face edges for (i = 0; i < 12; i++) { // cull edges with normal more than 135 degree from moving direction float dot = Vector3.Dot(CollisionBox.edgeNormals[i], rayDirection); if (dot < -0.70710678) { continue; } p1 = boxEdges[i * 2]; p2 = boxEdges[i * 2 + 1]; p4 = vertices[indices[0]]; for (j = 0; j < indices.Length; j++) { p3 = p4; p4 = vertices[indices[(j + 1) % indices.Length]]; if (CollisionFace.EdgeIntersect(p1, p2, rayDirection, p3, p4, out distance, out position)) { if (distance < intersectDistance) { intersectDistance = distance; intersectPosition = position; intersectNormal = Vector3.Cross(p2 - p1, p3 - p4); intersectNormal = Vector3.Normalize(intersectNormal); if (Vector3.Dot(rayDirection, intersectNormal) > 0) { intersectNormal = Vector3.Negate(intersectNormal); } intersected = true; } } } } // intersect from face vertices to box for (i = 0; i < 3; i++) { float tnear, tfar; p1 = vertices[indices[i]]; int box_face_id = worldBox.RayIntersect(p1, -rayDirection, out tnear, out tfar); if (box_face_id > -1) { if (tnear < intersectDistance) { intersectDistance = tnear; intersectPosition = p1; intersectNormal = -CollisionBox.faceNormals[box_face_id]; intersected = true; } } } // intersect from box vertices to face polygon Vector3 v1 = vertices[indices[0]]; Vector3 v2 = vertices[indices[1]]; Vector3 v3 = vertices[indices[2]]; Vector3 uvt; for (i = 0; i < 8; i++) { // cull vertices with normal more than 135 degree from moving direction float dot = Vector3.Dot(CollisionBox.vertexNormals[i], rayDirection); if (dot < -0.70710678) { continue; } if (CollisionFace.RayTriangleIntersect(boxVerts[i], rayDirection, v1, v2, v3, out uvt.Z, out uvt.X, out uvt.Y)) { if (uvt.Z < intersectDistance) { intersectDistance = uvt.Z; intersectPosition = (1.0f - uvt.X - uvt.Y) * v1 + uvt.X * v2 + uvt.Y * v3; intersectNormal = Vector3.Cross(v3 - v1, v2 - v1); intersectNormal = Vector3.Normalize(intersectNormal); intersected = true; } } } return(intersected); }