public override bool TestCollisionVsCircle(CircleCollisionHull2D other) { //collides if distance between centers is <= sum of radii //or if you like opptimizations //if (distance between center)^2 <= (sum of radii)^2 // 1. get two centers Vector2 circleCenter1 = transform.position; Vector2 circleCenter2 = other.transform.position; // 2. take diference Vector2 distance = circleCenter2 - circleCenter1; // 3. distance squared = dot(diff, diff) float distSqr = Vector2.Dot(distance, distance); // 4. add the radii float radiiSum = other.radius + radius; // 5. square sum radiiSum *= radiiSum; // 6. do test. johnny test. it passes if distSq <= sumSq if (distSqr < radiiSum) { Debug.Log("CIRCLE -> CIRCLE"); return(true); } return(false); }
// FOR SUCCESSFUL COLLISION, CHANGE COLOR public override bool TestCollisionVSCircle(CircleCollisionHull2D other, ref Collision c) { // find the min and max components of the obb float minX = Mathf.Min(topLeftAxis.x, Mathf.Min(topRightAxis.x, Mathf.Min(botLeftAxis.x, botRightAxis.x))); float maxX = Mathf.Max(topLeftAxis.x, Mathf.Max(topRightAxis.x, Mathf.Max(botLeftAxis.x, botRightAxis.x))); float minY = Mathf.Min(topLeftAxis.y, Mathf.Min(topRightAxis.y, Mathf.Min(botLeftAxis.y, botRightAxis.y))); float maxY = Mathf.Max(topLeftAxis.y, Mathf.Max(topRightAxis.y, Mathf.Max(botLeftAxis.y, botRightAxis.y))); // calculate closest point by clamping circle center on each dimension // Find the vector2 distance between box & circle Vector2 diff = (Vector2)transform.position - (Vector2)other.transform.position; // Normalize that vector // multiply the vector by the radius to get the closest point on the circumference diff = diff.normalized * other.radius + (Vector2)other.transform.position; Debug.Log(minX + ", " + maxX); Debug.Log(minY + ", " + maxY); Debug.Log(diff); // check for the collision return(IsIntersectingCircle(minX, maxX, minY, maxY, diff.x, diff.y)); }
public override bool TestCollisionVsCircle(CircleCollisionHull2D other) { //same as above but first... //multiply circle center by box inverse matrix // 1. get circle center Vector4 circleCenter = new Vector4(other.transform.position.x, other.transform.position.y, 0.0f, 1.0f); // 2. get box x bounds float xMaxBound = transform.localScale.x * 0.5f; float xMinBound = -transform.localScale.x * 0.5f; // 3. get box y bounds float yMaxBound = transform.localScale.y * 0.5f; float yMinBound = -transform.localScale.y * 0.5f; // 4. multiply circle center world position by box world to local matrix circleCenter = transform.InverseTransformPoint(circleCenter); // 5. clamp circle center on box x bound float circleOnX = circleCenter.x; // 6. clamp circle center on box y bound float circleOnY = circleCenter.y; if (circleCenter.x > xMaxBound) { circleOnX = xMaxBound; } else if (circleCenter.x < xMinBound) { circleOnX = xMinBound; } if (circleCenter.y > yMaxBound) { circleOnY = yMaxBound; } else if (circleCenter.y < yMinBound) { circleOnY = yMinBound; } // 7. use clamped point as closest point of box Vector2 closestPoint = new Vector2(circleOnX, circleOnY); Vector2 distance = closestPoint - new Vector2(circleCenter.x, circleCenter.y); float distSqr = Vector2.Dot(distance, distance); // 8. check if closest point of box is within the circle if (distSqr < other.radius * other.radius) { Debug.Log("OBB -> CIRCLE"); return(true); } // 9. do test (if in circle, true, else false) return(false); }
public override bool TestCollisionVsCircle(CircleCollisionHull2D other, ref Collision c) { c.a = this; c.b = other; // c.status // check if sqr distance between the center is less that the square of the radii updatePosition(); other.updatePosition(); // could use dot product float sqrDistance = (position - other.position).SqrMagnitude(); float sqrRadii = radius + other.radius; sqrRadii *= sqrRadii; bool isColiding = sqrDistance <= sqrRadii; if (!isColiding) { return(isColiding); } //contact point // http://paulbourke.net/geometry/circlesphere/ Vector2 difference = other.position - position; //from position to other.position float distance = difference.magnitude; float radii = radius + other.radius; // distance = radii // Vector2 contact = position + difference; // Get point halfway between two centers. Vector2 contact = position + difference * (radius / (radius + other.radius)); // Vector2 normal = (position - contact).normalized; // vector from contact to center float overlap = radii - distance; // not sure we need this. // edge cases - circles overlap completely, or one inside the other. c.contactCount = 1; c.contacts = new CollisionHull2D.Collision.Contact[c.contactCount]; c.contacts[0].point = contact; c.contacts[0].normal = normal; c.contacts[0].restitution = restitution; // TODO: Is this coefficient or actual number? // closing velocity // https://gamedev.stackexchange.com/questions/118162/how-to-calculate-the-closing-speed-of-two-objects //Vector2 diff = other.position - position; //Vector2 velDiff = other.particle2D.getVelocity() - particle2D.getVelocity(); //float closingSpeed = Vector2.Dot(velDiff, diff) / diff.magnitude; //Relative velocity from book Vector2 relativeVelocity = particle2D.getVelocity() - other.getParticle2D().getVelocity(); float separatingVel = Vector2.Dot(relativeVelocity, normal); // relativeVelocity * normal // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector // this would simulate hitting a hard object w/ no velocity loss. // Vector2 velReflectedOverN = particle2D.getVelocity() - 2 * Vector2.Dot(particle2D.getVelocity(), normal) * normal; // c.closingVelocity = closingSpeed*velReflectedOverN.normalized; c.closingVelocity = -separatingVel * normal; //was -seperatingVel c.status = isColiding; return(isColiding); }
public override bool TestCollisionVsCircle(CircleCollisionHull2D other) { //SEE CIRCLE // find closest point to circle on box // done by clamping center of circle to be within box dimensions // if closest point is within circle, pass! (do circle vs point test) // 1. get circle center Vector2 circleCenter = other.transform.position; float xMaxBound = transform.position.x + transform.localScale.x * 0.5f; float xMinBound = transform.position.x - transform.localScale.x * 0.5f; // 3. get box y bounds float yMaxBound = transform.position.y + transform.localScale.y * 0.5f; float yMinBound = transform.position.y - transform.localScale.y * 0.5f; // 4. clamp circle center on box x bound // 5. clamp circle center on box y bound float circleOnX = circleCenter.x; float circleOnY = circleCenter.y; if (circleCenter.x > xMaxBound) { circleOnX = xMaxBound; } else if (circleCenter.x < xMinBound) { circleOnX = xMinBound; } if (circleCenter.y > yMaxBound) { circleOnY = yMaxBound; } else if (circleCenter.y < yMinBound) { circleOnY = yMinBound; } // 6. use clamped point as closest point of box Vector2 closestPoint = new Vector2(circleOnX, circleOnY); Vector2 distance = closestPoint - circleCenter; float distSqr = Vector2.Dot(distance, distance); // 7. check if closest point of box is within the circle // 8. do test (if in circle, true, else false) if (distSqr < other.radius * other.radius) { Debug.Log("BOX -> CIRCLE"); return(true); } return(false); }
// FOR SUCCESSFUL COLLISION, CHANGE COLOR public override bool TestCollisionVSCircle(CircleCollisionHull2D other, ref Collision c) { //ROB // Passes if distance between centers <= sum of radii // optimized collision passes if (distance between centers) squared <= (sum of radii) squared // 1. Get the two centers Vector2 otherCenter = other.thisCenter; // 2. difference between centers Vector2 distanceVec = otherCenter - thisCenter; //float distance = (otherCenter.x - thisCenter.x) * (otherCenter.x - thisCenter.x) // + (otherCenter.y - thisCenter.y) * (otherCenter.y - thisCenter.y); //distance *= distance; // 3. distance squared = dot(diff, diff) float distance = Vector2.Dot(distanceVec, distanceVec); // 4. Sum of radii float totalRadii = radius + other.radius; // 5. square sum totalRadii *= totalRadii; // 6. Do the test: distSqr <= sumSqr if (distance <= totalRadii) { c.a = gameObject.GetComponent <CircleCollisionHull2D>(); c.b = other; c.status = true; if (distance <= totalRadii) { float theta = Mathf.Atan2(distanceVec.y, distanceVec.x); // find the point in the center of the overlap between the two circles c.contactCount = 1; float distanceToContactPoint = ((distance * distance - other.radius * other.radius + radius * radius) / (2 * distance)); c.contact[0].penetration = radius - distanceToContactPoint; c.contact[0].point.x = thisCenter.x + Mathf.Cos(theta) * distanceToContactPoint; // if broken, put in abs inside of sqrt c.contact[0].point.y = thisCenter.y + Mathf.Sin(theta) * distanceToContactPoint; c.contact[0].normal = thisCenter - c.contact[0].point; c.contact[0].normal.Normalize(); Debug.DrawLine(thisCenter, thisCenter + c.contact[0].normal); c.contact[0].restitutionCoefficient = restitution; } return(true); } return(false); }
public bool TestCollisionVsCircle(CircleCollisionHull2D other) { // check if sqr distance between the center is less that the square of the radii updatePosition(); other.updatePosition(); // could use dot product float sqrDistance = (position - other.position).SqrMagnitude(); float sqrRadii = radius + other.radius; sqrRadii *= sqrRadii; bool isColiding = sqrDistance <= sqrRadii; return(isColiding); }
// FOR SUCCESSFUL COLLISION, CHANGE COLOR public override bool TestCollisionVSCircle(CircleCollisionHull2D other, ref Collision c) { // cam did this part float circleX = other.thisCenter.x; float circleY = other.thisCenter.y; float circleRadius = other.radius; float rectX = position.x; float rectY = position.y; float DeltaX = circleX - Mathf.Max(rectX, Mathf.Min(circleX, rectX + width * 0.5f)); float DeltaY = circleY - Mathf.Max(rectY, Mathf.Min(circleY, rectY + height * 0.5f)); return((DeltaX * DeltaX + DeltaY * DeltaY) < (circleRadius * circleRadius)); }
// Start is called before the first frame update public override bool TestCollisionVsCircle(CircleCollisionHull2D other, ref Collision c) { updatePosition(); other.updatePosition(); // find the closest point to the circle on the box. // - Clamp the center of the circle to be in dimensions of box, gets closest point? Vector2 closest_point; Vector2 blCorner = botLeftCorner + position; Vector2 trCorner = topRightCorner + position; closest_point.x = Mathf.Clamp(other.position.x, blCorner.x, trCorner.x); closest_point.y = Mathf.Clamp(other.position.y, blCorner.y, trCorner.y); // if closest point is within circle, pass. (point vs circle test). square for efficiency bool isColiding = (other.position - closest_point).SqrMagnitude() < other.radius * other.radius; return(isColiding); }
// Start is called before the first frame update void Start() { collider = gameObject.AddComponent <CircleCollisionHull2D>(); collider.radius = radius; collider.FakeStart(); }
public abstract bool TestCollisionVSCircle(CircleCollisionHull2D other, ref Collision c);
public abstract bool TestCollisionVsCircle(CircleCollisionHull2D other);
public virtual bool TestCollisionVsCircle(CircleCollisionHull2D other, ref Collision c) { return(false); }
public override bool TestCollisionVsCircle(CircleCollisionHull2D other, ref Collision c) { // See circle updatePosition(); other.updatePosition(); // same as above, but first // multiply circle center by invs world matrix of box to move to box space // neither of the these work. // Vector2 transformedPosition = transform.localToWorldMatrix.inverse * other.position; //Matrix4x4 trs = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one); // Vector2 transformedPosition = (trs* new Vector4(other.position.x, other.position.y, 0, 0)); // Vector2 transformedPosition = other.position; // Vector2 closest_point; // Vector2 blc = Vector2.zero, trc = Vector2.zero; // bot left and top right of OBB // getDimensions(ref blc, ref trc); // //With above code works except for position and rotation. // //blc += position; // //trc += position; // // This fixes position but not rotation. //// blc = botLeftTranslated(); // // trc = topRightTranslated(); // // These aren't the right corners? // closest_point.x = Mathf.Clamp(transformedPosition.x, blc.x, trc.x); // closest_point.y = Mathf.Clamp(transformedPosition.y, blc.y, trc.y); // // if closest point is within circle, pass. (point vs circle test). square for efficiency // bool isColiding = (transformedPosition - closest_point).SqrMagnitude() < other.radius * other.radius; ; // return isColiding; // =========== Attempt 2 ============= // // project circle center and this points onto axii // if circle point is within radius of point on both axii then true, else false. // can use clamp here too // Project circle and corners onto up axis Vector2 circleProj = project(other.position, transform.up); Vector2 corner1 = topRightTranslated(); Vector2 corner2 = botRightTranslated(); // should be able to ignore other two corners along axis because they'll be the same. Vector2 c1proj = project(corner1, transform.up); Vector2 c2proj = project(corner2, transform.up); // clamp circle proj to get closest point Vector2 closestPoint; closestPoint.x = Mathf.Clamp(circleProj.x, Mathf.Min(c1proj.x, c2proj.x), Mathf.Max(c1proj.x, c2proj.x)); closestPoint.y = Mathf.Clamp(circleProj.y, Mathf.Min(c1proj.y, c2proj.y), Mathf.Max(c1proj.y, c2proj.y)); // compare closest point to projected point. bool isCollidingOnUp = (circleProj - closestPoint).SqrMagnitude() < other.radius * other.radius; // repeat for right axis circleProj = project(other.position, transform.right); corner1 = topLeftTranslated(); corner2 = topRightTranslated(); c1proj = project(corner1, transform.right); c2proj = project(corner2, transform.right); closestPoint.x = Mathf.Clamp(circleProj.x, Mathf.Min(c1proj.x, c2proj.x), Mathf.Max(c1proj.x, c2proj.x)); closestPoint.y = Mathf.Clamp(circleProj.y, Mathf.Min(c1proj.y, c2proj.y), Mathf.Max(c1proj.y, c2proj.y)); bool isCollidingOnRight = (circleProj - closestPoint).SqrMagnitude() < other.radius * other.radius; return(isCollidingOnRight && isCollidingOnUp); }