public TwinCollisionChild(Collider self, Collider other, DotToLineCollisionResult source) { this.self = self; this.other = other; this.contactPoint = source.collisionPoint; this.selfDepenetration = source.dotDepenetration; this.otherDepenetration = source.lineDepenetration; this.selfOtherNormal = source.lineNormal; this.t = source.t; this.selfMovement = source.dotMovement; this.otherMovement = source.lineMovement; this.selfRequirement = source.dotRequirement; this.otherRequirement = source.lineRequirement; this.thinSelf = source.thinDot; this.thinOther = source.thinLine; this.similarDepenetration = source.similarDepenetration; this.selfOriginalMovement = source.dotOriginalMovement; this.otherOriginalMovement = source.lineOriginalMovement; selfDepenetration0 = selfDepenetration; otherDepenetration0 = otherDepenetration; similarDepenetration0 = similarDepenetration; selfMovement0 = selfMovement; otherMovement0 = otherMovement; selfRequirement0 = selfRequirement; otherRequirement0 = otherRequirement; }
public bool CheckGraze(PolygonCollider other, out TwinCollisionChild result) { bool ret0 = false; result = null; Vector2 mov = movement; Vector2 oMov = other.movement; Vector2[] myPoints = worldPoints; Vector2[] otherPoints = other.worldPoints; int mpl = myPoints.Length; int mpl1 = mpl - 1; int opl = otherPoints.Length; int opl1 = opl - 1; Vector2 prevContactPoint = Vector2.zero; DotToLineCollisionResult r = new DotToLineCollisionResult(); for (int i = 0; i < mpl; ++i) { Vector2 p = myPoints [i]; for (int j = 0; j < opl; ++j) { int j1 = Util.RotaryClamp(j - 1, 0, opl1); Vector2 p1 = otherPoints [j1]; Vector2 p2 = otherPoints [j]; DotToLineCollisionResult rIJ; if (Physics.MovingDotToMovingLineGraze( p, movement, p1, p2, other.movement, out rIJ) && (!ret0 || prevContactPoint != rIJ.collisionPoint)) { if (!ret0 || rIJ.t < r.t || ( rIJ.t == r.t && rIJ.dotMovement.sqrMagnitude < r.dotMovement.sqrMagnitude /*&& ( * !r.CheckDotRequirement2(mov+rIJ.dotDepenetration - rIJ.thinDot) || !r.CheckLineRequirement2(oMov+rIJ.lineDepenetration - rIJ.thinLine) ||)*/ ) ) { bool collidedIJ = false; if (rIJ.r == 0) { if (Vector2.Dot( Util.Normal(myPoints[Util.RotaryClamp(i - 1, 0, mpl1)], p), rIJ.lineNormal ) == -1) { collidedIJ = true; } } else if (rIJ.r == 1) { if (Vector2.Dot( Util.Normal(p, myPoints[Util.RotaryClamp(i + 1, 0, mpl1)]), rIJ.lineNormal ) == -1) { collidedIJ = true; } } else { collidedIJ = true; } if (collidedIJ) { ret0 = true; r = rIJ; //result = new TwinCollisionChild (this, other, rIJ); } } } } } if (ret0) { result = new TwinCollisionChild(this, other, r); } if (ret0 && gameObject.name == "GreenBox" && (result.selfDepenetration.x == 0.3125f || result.selfDepenetration.x == 0.3124999f)) { bool x = true; } if (ret0 && result.other.gameObject.name == "GreenBox" && (result.otherDepenetration.x == 0.3125f || result.otherDepenetration.x == 0.3124999f)) { bool x = true; } return(ret0); }
public static bool MovingDotToMovingLineCollision( Vector2 dot, Vector2 dotMovement, Vector2 lineP1, Vector2 lineP2, Vector2 lineMovement, out DotToLineCollisionResult result) { result = new DotToLineCollisionResult(); result.dotOriginalMovement = dotMovement; result.lineOriginalMovement = lineMovement; Vector2 lineNormal = Util.Normal(lineP1, lineP2); result.lineNormal = lineNormal; result.t = 1; //Vector2 d = lineP2 - lineP1; if (dotMovement == Vector2.zero && lineMovement == Vector2.zero) { UnityEngine.Debug.Log("ZERO MOVEMENT"); return(false); } Vector2 diff0 = (dotMovement - lineMovement); float movDot = Vector2.Dot(lineNormal, diff0.normalized); if (movDot > 0) { /*if (dotMovement.x != 0 && lineNormal.x != 0) { * bool signDot = dotMovement.x > 0; * bool signLine = lineMovement.x > 0; * if (signDot == signLine) { * UnityEngine.Debug.Log ("DOT ESCAPE"); * } * }*/ return(false); } if (movDot == 0) { Vector2 u = lineP2 - lineP1; Vector2 v = dot - lineP1; Vector2 w = v + diff0; Vector2 proj = Util.Project(w, u); if (Vector2.Dot(v, u) < 0) { return(false); } else { float r = proj.magnitude / u.magnitude; Vector2 rej = w - proj; if (r > 1) { return(false); } else if (rej.sqrMagnitude > 3 * Util.sqrThin) { return(false); } else { result.r = r; result.t = 1; result.dotDepenetration = Vector2.zero; result.collisionPoint = dot + dotMovement; result.lineDepenetration = Vector2.zero; result.dotMovement = dotMovement; result.dotRequirement = dotMovement; result.dotOriginalMovement = dotMovement; result.lineNormal = Util.Normal(u); result.similarDepenetration = Vector2.zero; result.thinDot = Vector2.zero; result.thinLine = Vector2.zero; result.lineOriginalMovement = lineMovement; result.lineRequirement = lineMovement; result.lineMovement = lineMovement; return(true); } } } DotToLineIntersectionResult _r; if (!MovingDotToMovingLineIntersection(dot, dotMovement, lineP1, lineP2, lineMovement, out _r)) { return(MovingDotToMovingLineGraze(dot, dotMovement, lineP1, lineP2, lineMovement, out result)); return(false); } bool needThinning = true; if (false) { float t = _r.t; Vector2 u = lineP2 - lineP1; Vector2 endPoint = _r.intersectionPoint; Vector2 postLineP1 = lineP1 + lineMovement + result.lineDepenetration; Vector2 diff = endPoint - postLineP1; float crossPost = Util.Cross(diff, u); if (crossPost != 0) { //UnityEngine.Debug.Log ("CROSS IS NOT ZERO"); float crossPre = Util.Cross(dot - lineP1, u); bool signPost = crossPost > 0; bool signPre = crossPre > 0; needThinning = true; if (signPre != signPost) { UnityEngine.Debug.Log("SIGN IS DIFFERENT"); if (t <= 0) { UnityEngine.Debug.Log("T NEGATIVE"); needThinning = true; t = 0; } else { int i = 0; do { if (t >= _r.t) { t *= (1 - Util.thin); } if (t >= _r.t) { t -= Util.sqrThin; } if (t >= _r.t) { t -= Util.halfThin; } if (t >= _r.t) { t -= Util.thin; } if (t < 0) { UnityEngine.Debug.Log("T NEGATIVE"); needThinning = true; t = 0; break; } _r.t = t; float t1 = t - 1; _r.dotDepenetration = dotMovement * t1; _r.lineDepenetration = lineMovement * t1; _r.intersectionPoint = dot + dotMovement + _r.dotDepenetration; endPoint = _r.intersectionPoint; postLineP1 = lineP1 + lineMovement + _r.lineDepenetration; diff = endPoint - postLineP1; crossPost = Util.Cross(diff, u); crossPre = Util.Cross(dot - lineP1, u); signPost = crossPost > 0; signPre = crossPre > 0; if (signPost == signPre) { needThinning = false; break; } else { UnityEngine.Debug.Log("FAILED"); } ++i; } while(needThinning && i < 5 && t > 0); } } } } //needThinning = false; Vector2 _dotMovement = dotMovement + _r.dotDepenetration; Vector2 _lineMovement = lineMovement + _r.lineDepenetration; Vector2 _dotRequirement = _dotMovement; Vector2 _lineRequirement = _lineMovement; _r.dotDepenetration = Util.Project(_r.dotDepenetration, lineNormal); _r.lineDepenetration = Util.Project(_r.lineDepenetration, lineNormal); if (dotMovement == Vector2.zero && lineMovement == Vector2.zero && _r.dotDepenetration == Vector2.zero && _r.lineDepenetration == Vector2.zero) { UnityEngine.Debug.Log("ZERO MOVEMENT AND DEPENETRATION"); return(false); } //Vector2 similarDepenetration = Vector2.zero; Vector2 similarDepenetration = SimilarDepenetration(_r.dotDepenetration, _r.lineDepenetration, lineNormal); if (similarDepenetration != Vector2.zero) { _r.dotDepenetration -= similarDepenetration; _r.lineDepenetration -= similarDepenetration; _dotMovement -= similarDepenetration; _lineMovement -= similarDepenetration; } Vector2 thinDot = Vector2.zero, thinLine = Vector2.zero; if (needThinning) { Thin(_dotMovement, _r.dotDepenetration, _lineMovement, _r.lineDepenetration, lineNormal, out thinDot, out thinLine); _r.dotDepenetration += thinDot; _r.lineDepenetration += thinLine; _dotMovement += thinDot; _lineMovement += thinLine; } result.similarDepenetration = similarDepenetration; result.lineNormal = lineNormal; result.t = _r.t; result.r = _r.r; result.dotDepenetration = _r.dotDepenetration; result.lineDepenetration = _r.lineDepenetration; result.collisionPoint = _r.intersectionPoint; result.dotMovement = _dotMovement; result.lineMovement = _lineMovement; result.dotRequirement = _dotRequirement; // - _r.dotDepenetration; result.lineRequirement = _lineRequirement; // - _r.lineDepenetration; result.thinDot = thinDot; result.thinLine = thinLine; return(true); }
public static bool MovingDotToMovingLineGraze( Vector2 dot, Vector2 dotMovement, Vector2 lineP1, Vector2 lineP2, Vector2 lineMovement, out DotToLineCollisionResult result) { result = new DotToLineCollisionResult(); result.dotOriginalMovement = dotMovement; result.lineOriginalMovement = lineMovement; Vector2 lineNormal = Util.Normal(lineP1, lineP2); result.lineNormal = lineNormal; result.t = 1; Vector2 diff0 = (dotMovement - lineMovement); float movDot = Vector2.Dot(lineNormal, diff0.normalized); if (movDot < 0) { return(false); } Vector2 u = lineP2 - lineP1; Vector2 v = dot - lineP1; Vector2 w = v + diff0; Vector2 proj = Util.Project(v, u); Vector2 rej = w - proj; if (rej.sqrMagnitude < 3 * Util.sqrThin) { if (Vector2.Dot(v, u) < 0) { return(false); } else { float r0 = proj.sqrMagnitude / u.sqrMagnitude; float r = Util.Project(w, u).magnitude / u.magnitude; if (r0 > 1) { return(false); } else { if (r > 1) { r = 1; } result.r = r; result.t = 1; result.dotDepenetration = Vector2.zero; result.collisionPoint = dot + dotMovement; result.lineDepenetration = Vector2.zero; result.dotMovement = dotMovement; result.dotRequirement = dotMovement; result.dotOriginalMovement = dotMovement; result.lineNormal = Util.Normal(u); result.similarDepenetration = Vector2.zero; result.thinDot = Vector2.zero; result.thinLine = Vector2.zero; result.lineOriginalMovement = lineMovement; result.lineRequirement = lineMovement; result.lineMovement = lineMovement; return(true); } } } return(false); }