static public bool OBBOBB(ObjectBoundingBoxCollision2D rectA, ObjectBoundingBoxCollision2D rectB) { //grab 4 axis of both shapes // grab all vertices of both shapes, then put them onto each axis of both shapes // Vector2 rightA = new Vector2(Mathf.Cos(rectA.zRot), -Mathf.Sin(rectA.zRot)); Vector2 upA = new Vector2(Mathf.Sin(rectA.zRot), Mathf.Cos(rectA.zRot)); Vector2 rightB = new Vector2(Mathf.Cos(rectB.zRot), -Mathf.Sin(rectB.zRot)); Vector2 upB = new Vector2(Mathf.Sin(rectB.zRot), Mathf.Cos(rectB.zRot)); if (OBBTest(rightA, rectA, rectB)) { if (OBBTest(upA, rectA, rectB)) { if (OBBTest(rightB, rectB, rectA)) { if (OBBTest(upB, rectB, rectB)) { return(true); } } } } return(false); }
public CollisionInfo(CircleCollision2D colA, ObjectBoundingBoxCollision2D colB, Vector2 normal, float penetration) { RigidBodyA = colA.GetComponent <Particle2D>(); RigidBodyB = colB.GetComponent <Particle2D>(); RelativeVelocity = RigidBodyB.velocity - RigidBodyA.velocity; contacts[0].normal = normal; contacts[0].penetration = penetration; contacts[0].restitution = Mathf.Min(RigidBodyA.restitution, RigidBodyB.restitution); }
static public bool CircleOBB(CircleCollision2D circle, ObjectBoundingBoxCollision2D rect) { //transform circle into obb space transform.InverseTransformPoint(cirecle.postion); //then do circle AABB Vector2 halfExtend = (rect.posMax - rect.posMin) / 2; Vector2 circleInOBB = rect.transform.InverseTransformPoint(circle.center); Vector2 circleBox = new Vector2(Mathf.Max(-halfExtend.x, Mathf.Min(circleInOBB.x, halfExtend.x)), Mathf.Max(-halfExtend.y, Mathf.Min(circleInOBB.y, halfExtend.y))); Vector2 distance = circleInOBB - circleBox; float distanceSQ = Vector2.Dot(distance, distance); Debug.DrawLine(circleBox, circle.center); if (distanceSQ <= (circle.radius * circle.radius)) { return(true); } return(false); }
static private bool OBBTest(Vector2 norm, ObjectBoundingBoxCollision2D proj, ObjectBoundingBoxCollision2D main) { //top left is min.x, max y //bottom right is max.x, min.y Vector2 Max1; Vector2 Min1; Vector2 Max2; Vector2 Min2; Vector2 p1 = Vector2.Dot(proj.topRight, norm) * norm; Vector2 p2 = Vector2.Dot(proj.botLeft, norm) * norm; Vector2 p3 = Vector2.Dot(new Vector2(proj.topRight.x, proj.botLeft.y), norm) * norm; Vector2 p4 = Vector2.Dot(proj.botLeft, norm) * norm; if (p1.x <= p3.x && p1.y <= p3.y) { p1 = p3; } if (p2.x >= p4.x && p2.y >= p4.y) { p2 = p4; } Max1 = p1; Min1 = p2; Max2 = Vector2.Dot(main.topRight, norm) * norm; Min2 = Vector2.Dot(main.botLeft, norm) * norm; if (Max1.x >= Min2.x && Max1.y >= Min2.y && Max2.x >= Min1.x && Max2.y >= Min1.y) { return(true); } return(false); }
static public bool AABBOBB(AxisAllignedBoundingBoxCollision2D colA, ObjectBoundingBoxCollision2D colB) { //AxisAllignedBoundingBoxCollision2D //transform min and max into obb space, then do AABB AABB if (colA.posMax.x >= colB.posMin.x && colB.posMax.x >= colA.posMin.x) { if (colA.posMax.y >= colB.posMin.y && colB.posMax.y >= colA.posMin.y) { //return true; Vector2 abbMinTrans = colB.transform.InverseTransformPoint(colA.posMin); Vector2 abbMaxTrans = colB.transform.InverseTransformPoint(colA.posMax); if (abbMaxTrans.x >= colB.posMin.x && colB.posMax.x >= abbMinTrans.x) { if (abbMaxTrans.y >= colB.posMin.y && colB.posMax.y >= abbMinTrans.y) { return(true); } } } } return(false); }
static public CollisionInfo CircleOBB(CircleCollision2D circle, ObjectBoundingBoxCollision2D rect) { //transform circle into obb space transform.InverseTransformPoint(cirecle.postion); //then do circle AABB Vector2 halfExtend = (rect.posMax - rect.posMin) / 2; Vector2 circleInOBB = rect.transform.InverseTransformPoint(circle.center); Vector2 circleBox = new Vector2(Mathf.Max(-halfExtend.x, Mathf.Min(circleInOBB.x, halfExtend.x)), Mathf.Max(-halfExtend.y, Mathf.Min(circleInOBB.y, halfExtend.y))); Vector2 distanceVec = circleInOBB - circleBox; float distanceSQ = Vector2.Dot(distanceVec, distanceVec); //Debug.DrawLine(circleBox, circle.center); if (distanceSQ <= (circle.radius * circle.radius)) { //return true; float distance = Mathf.Sqrt(distanceSQ); return(new CollisionInfo(circle, rect, rect.transform.TransformVector(-distanceVec).normalized, circle.radius - distance)); } return(null); }
static public CollisionInfo OBBOBB(ObjectBoundingBoxCollision2D rectA, ObjectBoundingBoxCollision2D rectB) { List <Vector2> allAxis = new List <Vector2>(); allAxis.AddRange(rectA.normAxis); allAxis.AddRange(rectB.normAxis); foreach (var axis in allAxis) { float OBB1Min = float.MaxValue; float OBB1Max = float.MinValue; foreach (var vert in rectA.verticeCheck) { float dotValue = (vert.x * axis.x + vert.y * axis.y); if (dotValue < OBB1Min) { OBB1Min = dotValue; } if (dotValue > OBB1Max) { OBB1Max = dotValue; } } float OBB2Min = float.MaxValue; float OBB2Max = float.MinValue; foreach (var vert in rectB.verticeCheck) { float dotValue = (vert.x * axis.x + vert.y * axis.y); if (dotValue < OBB2Min) { OBB2Min = dotValue; } if (dotValue > OBB2Max) { OBB2Max = dotValue; } } if (!(OBB1Max < OBB2Min && OBB2Max < OBB1Min)) { Vector2 AtoB = rectB.center - rectA.center; float x_overlap = rectA.halfExtends.x + rectB.halfExtends.x - Mathf.Abs(AtoB.x); if (x_overlap > 0.0f) { float y_overlap = rectA.halfExtends.y + rectB.halfExtends.y - Mathf.Abs(AtoB.y); if (y_overlap > 0.0f) { if (x_overlap < y_overlap) { return(new CollisionInfo(rectA, rectB, AtoB.x < 0.0f ? -Vector2.right : Vector2.right, x_overlap)); } else { return(new CollisionInfo(rectA, rectB, AtoB.y < 0.0f ? -Vector2.up : Vector2.up, y_overlap)); } } } } } return(null); }
static public CollisionInfo AABBOBB(AxisAllignedBoundingBoxCollision2D colA, ObjectBoundingBoxCollision2D colB) { //AxisAllignedBoundingBoxCollision2D //transform min and max into obb space, then do AABB AABB //if (colA.posMax.x >= colB.posMin.x && colB.posMax.x >= colA.posMin.x) //{ // if (colA.posMax.y >= colB.posMin.y && colB.posMax.y >= colA.posMin.y) // { // //return true; // Vector2 abbMinTrans = colB.transform.InverseTransformPoint(colA.posMin); // Vector2 abbMaxTrans = colB.transform.InverseTransformPoint(colA.posMax); // if (abbMaxTrans.x >= colB.posMin.x && colB.posMax.x >= abbMinTrans.x) // { // if (abbMaxTrans.y >= colB.posMin.y && colB.posMax.y >= abbMinTrans.y) // { // return true; // } // } // } //} //return false; List <Vector2> allAxis = new List <Vector2>(); allAxis.AddRange(colA.normAxis); allAxis.AddRange(colB.normAxis); foreach (var axis in allAxis) { float AABBMin = float.MaxValue; float AABBMax = float.MinValue; foreach (var vert in colA.verticeCheck) { float dotValue = (vert.x * axis.x + vert.y * axis.y); if (dotValue < AABBMin) { AABBMin = dotValue; } if (dotValue > AABBMax) { AABBMax = dotValue; } } float OBBMin = float.MaxValue; float OBBMax = float.MinValue; foreach (var vert in colB.verticeCheck) { float dotValue = (vert.x * axis.x + vert.y * axis.y); if (dotValue < OBBMin) { OBBMin = dotValue; } if (dotValue > OBBMax) { OBBMax = dotValue; } } if (!(AABBMax < OBBMin && OBBMax < AABBMin)) { Vector2 AtoB = colB.center - colA.center; float x_overlap = colA.halfExtends.x + colB.halfExtends.x - Mathf.Abs(AtoB.x); if (x_overlap > 0.0f) { float y_overlap = colA.halfExtends.y + colB.halfExtends.y - Mathf.Abs(AtoB.y); if (y_overlap > 0.0f) { if (x_overlap < y_overlap) { return(new CollisionInfo(colA, colB, AtoB.x < 0.0f ? -Vector2.right : Vector2.right, x_overlap)); } else { return(new CollisionInfo(colA, colB, AtoB.y < 0.0f ? -Vector2.up : Vector2.up, y_overlap)); } } } } } return(null); }