/** * Check if agent intersect with shape * * Agent will automatically detect which shape is used to calculate collision **/ public virtual CollisionResult IntersectWithShape(ConvexShape shape) { switch (shape.ShapeId) { case ConvexShapeID.Rectangle: ConvexRect rectShape = shape as ConvexRect; if (rectShape == null) { #if DEBUG Debug.LogError("Unable to down cast ConvexShape to ConvexRect"); #endif } return(ContactWithRectangle(rectShape)); case ConvexShapeID.Circle: ConvexCircle circleShape = shape as ConvexCircle; if (circleShape == null) { #if DEBUG Debug.LogError("Unable to down cast ConvexShape to ConvexCircle"); #endif } return(ContactWIthCircle(circleShape)); case ConvexShapeID.Unknow: #if DEBUG Debug.LogError("Unknow convex shape"); #endif break; } return(CollisionResult.None); }
protected override CollisionResult ContactWithRectangle(ConvexRect otherRect) { //All corners from rectangle Vector2[] corners = otherRect.AllCorners; bool collision = true; /** * Find closest corner to circle center then make a line between that corner and circle center into projection axis * Projecting all corner to that axis then find min and max corner * Check if circle is overlap with rectangle * * This solve problem when circle contact each corner vertex **/ //find closest corner and compare distance int closestCornerIndex = 0; int currentCornerIndex = 1; while (currentCornerIndex < corners.Length) { if ((_center - corners [closestCornerIndex]).sqrMagnitude > (_center - corners [currentCornerIndex]).sqrMagnitude) { closestCornerIndex = currentCornerIndex; } currentCornerIndex++; } //projection axis from closest corner to circle center Vector2 p = _center - corners [closestCornerIndex]; //base on axis find min and max corner float rMin = 0.0f; float rMax = 0.0f; for (int i = 0; i < corners.Length; i++) { rMax = Mathf.Max(rMax, Vector2.Dot(p.normalized, corners [i])); rMin = Mathf.Min(rMin, Vector2.Dot(p.normalized, corners [i])); } //find circle center projection float cP = Vector2.Dot(p.normalized, _center); //check if circle is overlap rectangle if (rMax < (cP - _radius) || rMin > (cP + _radius)) { collision = false; } else { collision = true; } /** * Find 4 corner's normal and make it as prjection axis * Go throught each normal(corner) * Find min and max projection of rectangle's corner base on that axis * Project circle center on that axis * Check if circle overlap rectangle * * This solve problem while circle contact edge of rectangle * * We also check if circle inside rectangle **/ //Ignore edge check if circle not contact with 4 corners(vertices) if (collision == true) { bool inside = true; Vector2[] normals = otherRect.Normals; float r1Dot1, r1Dot2, r1Dot3, r1Dot4, r1PMin, r1PMax; for (int i = 0; i < normals.Length; i++) { //4 corners projection r1Dot1 = Vector2.Dot(normals [i], corners [0]); r1Dot2 = Vector2.Dot(normals [i], corners [1]); r1Dot3 = Vector2.Dot(normals [i], corners [2]); r1Dot4 = Vector2.Dot(normals [i], corners [3]); //corner min and max on this normal(projection axis) r1PMin = Mathf.Min(r1Dot1, Mathf.Min(r1Dot2, Mathf.Min(r1Dot3, r1Dot4))); r1PMax = Mathf.Max(r1Dot1, Mathf.Max(r1Dot2, Mathf.Max(r1Dot3, r1Dot4))); //circle center projection on this normal(projection axis) float circleP = Vector2.Dot(normals [i], _center); //check if circle overlap rectangle if ((circleP - _radius) > r1PMax || (circleP + _radius) < r1PMin) { collision = false; break; } //Circle intersect with rectangle then check if circle inside rectangle //If insde we &(AND) value with true other wise false if ((circleP - _radius) > r1PMin && (circleP + _radius) > r1PMin) { inside &= true; } else { inside &= false; } } //if circle collide rectangle if (collision) { //If inside rectangle if (inside) { return(CollisionResult.Fit); } else { return(CollisionResult.Overlap); } } } return(CollisionResult.None); }
protected override CollisionResult ContactWithRectangle(ConvexRect otherRect) { bool collision = true; //this rectangle's normal of 4 corner and use it as projection axis Vector2[] rect1Normals = this.Normals; Vector2[] rect1AllCorners = this.AllCorners; Vector2[] rect2AllCorners = otherRect.AllCorners; //For each normals in this rectangle for (int i = 0; i < rect1Normals.Length; i++) { //Projecting all corners from rect1 to rect1's normal float r1Dot1 = Vector2.Dot(rect1Normals [i], rect1AllCorners [0]); float r1Dot2 = Vector2.Dot(rect1Normals [i], rect1AllCorners [1]); float r1Dot3 = Vector2.Dot(rect1Normals [i], rect1AllCorners [2]); float r1Dot4 = Vector2.Dot(rect1Normals [i], rect1AllCorners [3]); //Find rect1 max and min projection float r1PMin = Mathf.Min(r1Dot1, Mathf.Min(r1Dot2, Mathf.Min(r1Dot3, r1Dot4))); float r1PMax = Mathf.Max(r1Dot1, Mathf.Max(r1Dot2, Mathf.Max(r1Dot3, r1Dot4))); //Projecting all corners from rect2 to rect1's normal float r2Dot1 = Vector2.Dot(rect1Normals [i], rect2AllCorners [0]); float r2Dot2 = Vector2.Dot(rect1Normals [i], rect2AllCorners [1]); float r2Dot3 = Vector2.Dot(rect1Normals [i], rect2AllCorners [2]); float r2Dot4 = Vector2.Dot(rect1Normals [i], rect2AllCorners [3]); //Find rect2 max and min projection float r2PMin = Mathf.Min(r2Dot1, Mathf.Min(r2Dot2, Mathf.Min(r2Dot3, r2Dot4))); float r2PMax = Mathf.Max(r2Dot1, Mathf.Max(r2Dot2, Mathf.Max(r2Dot3, r2Dot4))); //Two rectangles not collide each other if there is a gap //and we do not check further if (r2PMin > r1PMax || r2PMax < r1PMin) { collision = false; break; } } //Check if this rectangle is inside another rectangle if (collision == true) { bool inside = true; //4 corners of this rectangle foreach (Vector2 corner in AllCorners) { //if other rectangle not contain this corner if (!otherRect.ContainPoint2D(corner)) { inside = false; break; } } if (inside == true) { return(CollisionResult.Fit); } return(CollisionResult.Overlap); } //There is no collision between two rectangles; return(CollisionResult.None); }
//public abstract ConvexShape GetShape (); /** * Subclass must override **/ protected abstract CollisionResult ContactWithRectangle(ConvexRect otherRect);
protected override CollisionResult ContactWithRectangle(ConvexRect otherRect) { return(otherRect.IntersectWithShape(this)); }
protected override CollisionResult ContactWithRectangle(ConvexRect otherRect) { bool collision = true; bool inside = true; //this rectangle's normal of 4 corner and use it as projection axis Vector2[] rect1Normals = this.Normals; Vector2[] rect1AllCorners = this.AllCorners; Vector2[] rect2AllCorners = otherRect.AllCorners; //For each normals in this rectangle IEnumerator ie = rect1Normals.GetEnumerator(); while (ie.MoveNext()) { //Projecting all corners from rect1 to rect1's normal float r1Dot1 = Vector2.Dot((Vector2)ie.Current, rect1AllCorners [0]); float r1Dot2 = Vector2.Dot((Vector2)ie.Current, rect1AllCorners [1]); float r1Dot3 = Vector2.Dot((Vector2)ie.Current, rect1AllCorners [2]); float r1Dot4 = Vector2.Dot((Vector2)ie.Current, rect1AllCorners [3]); //Find rect1 max and min projection float r1PMin = Mathf.Min(r1Dot1, Mathf.Min(r1Dot2, Mathf.Min(r1Dot3, r1Dot4))); float r1PMax = Mathf.Max(r1Dot1, Mathf.Max(r1Dot2, Mathf.Max(r1Dot3, r1Dot4))); //Projecting all corners from rect2 to rect1's normal float r2Dot1 = Vector2.Dot((Vector2)ie.Current, rect2AllCorners [0]); float r2Dot2 = Vector2.Dot((Vector2)ie.Current, rect2AllCorners [1]); float r2Dot3 = Vector2.Dot((Vector2)ie.Current, rect2AllCorners [2]); float r2Dot4 = Vector2.Dot((Vector2)ie.Current, rect2AllCorners [3]); //Find rect2 max and min projection float r2PMin = Mathf.Min(r2Dot1, Mathf.Min(r2Dot2, Mathf.Min(r2Dot3, r2Dot4))); float r2PMax = Mathf.Max(r2Dot1, Mathf.Max(r2Dot2, Mathf.Max(r2Dot3, r2Dot4))); //Two rectangles not collide each other if there is a gap //and we do not check further if (r2PMin > r1PMax || r2PMax < r1PMin) { collision = false; inside = false; break; } if (r1PMin < r2PMin || r1PMax > r2PMax) { inside = false; } } if (collision == true) { if (inside == true) { return(CollisionResult.Fit); } return(CollisionResult.Overlap); } //There is no collision between two rectangles; return(CollisionResult.None); }