//Checks if the provided lines intersect //Derived from https://blogs.sas.com/content/iml/2018/07/09/intersection-line-segments.html private static bool Intersects(VecLine a, VecLine b) { //Convert the lines to 4 points MFG.Vector3 p1 = a.p; MFG.Vector3 p2 = a.p + a.v; MFG.Vector3 q1 = b.p; MFG.Vector3 q2 = b.p + b.v; //Form a matrix from the vector differences between the points MFG.Matrix3 A = new MFG.Matrix3((p2 - p1).x, (p2 - p1).y, 0, (q1 - q2).x, (q1 - q2).y, 0, 0, 0, 1); //Form a vector from the differences between the start points MFG.Vector3 B = q1 - p1; //Then //A*t = b //t = A^-1 * b //Get the inverted matrix as required by the previous maths MFG.Matrix3 inverted = A.GetInverted(); if (inverted != null) //If it is invertible, they don't share a slope. The lines will intersect. { MFG.Vector3 solution = inverted * B; //Solve the equation return((solution.x >= 0 && solution.x <= 1) && (solution.y >= 0 && solution.y <= 1)); //If the solution falls in the unit square, valid collision, else not. } else //Otherwise, if they share a slope, { //Check for overlaps if (IsBetween(p1, p2, q1)) //Is q1 between p1 and p2? { return(true); //They collide! } if (IsBetween(p1, p2, q2)) //Is q2 between p1 and p2? { return(true); //They collide! } if (IsBetween(q1, q2, p1)) //Is p11 between q1 and q2? { return(true); //They collide! } return(false); //If there were no overlaps, they don't collide! } }
/* * Narrow phase collision detection considers each line of the bounding box of object A vs each line in the bounding box of object B. * If slopes match+not collinear, it escapes as false. * It then checks for collisions by representing each line as a parametric linear equation point+t*vector, then checks for where their (x,y) match. * If the lines collide such that both parametric variables are between 0 and 1, there is a collision between the line segments. */ private static bool Collides(BoundingBox a, BoundingBox b) { var origin = new MFG.Vector3(0, 0, 1); int aLen = a.vertices.Length; int bLen = b.vertices.Length; for (int i = 0; i < aLen; i++) //For each vertex comprising the bounding box of the first object { var lineA = new VecLine(a.vertices[i], a.vertices[(i + 1) % aLen]); //Create a line to the next vertex for (int j = 0; j < bLen; j++) //For each vertex comprising the bounding box of the first object { var lineB = new VecLine(b.vertices[j], b.vertices[(j + 1) % bLen]); //Create a line to the next vertex if (Intersects(lineA, lineB)) //Do the line segments intersect? { return(true); //Yes! So the boxes collide! } } } return(false); //No, none do, so the boxes don't collide. }