private bool IsCircleColliding( CircleParticle p ) { p.GetCardXProjection(); double depthX = TestIntervals( p.BMin, p.BMax, minX, maxX ); if ( depthX == 0 ) return false; p.GetCardYProjection(); double depthY = TestIntervals( p.BMin, p.BMax, minY, maxY ); if ( depthY == 0 ) return false; // determine if the circle's center is in a vertex voronoi region bool isInVertexX = Math.Abs( depthX ) < p.Radius; bool isInVertexY = Math.Abs( depthY ) < p.Radius; if ( isInVertexX && isInVertexY ) { // get the closest vertex double vx = center.X + Sign( p.Curr.X - center.X ) * ( rectWidth / 2 ); double vy = center.Y + Sign( p.Curr.Y - center.Y ) * ( rectHeight / 2 ); // get the distance from the vertex to circle center double dx = p.Curr.X - vx; double dy = p.Curr.Y - vy; double mag = Math.Sqrt( dx * dx + dy * dy ); double pen = p.Radius - mag; // if there is a collision in one of the vertex regions if ( pen > 0 ) { dx /= mag; dy /= mag; p.MTD.Set( dx * pen, dy * pen ); normal.Set( dx, dy ); return true; } return false; } else { // collision on one of the 4 edges p.SetXYMTD( depthX, depthY ); normal.Set( p.MTD.X / Math.Abs( depthX ), p.MTD.Y / Math.Abs( depthY ) ); return true; } }
public void ResolveCircleCollision( CircleParticle p, Engine engine ) { if ( IsCircleColliding( p ) ) { OnContact(); p.OnContact(); p.ResolveCollision( normal, engine ); } }
private bool IsCircleColliding( CircleParticle p ) { // find the closest point on the surface to the CircleParticle p.ClosestPoint = FindClosestPoint( p.Curr ); // get the normal of the circle relative to the location of the closest point Vector circleNormal = p.ClosestPoint.MinusNew( p.Curr ); circleNormal.Normalize(); // if the center of the circle has broken the line keep the normal from 'flipping' // to the opposite direction. for small circles, this prevents break-throughs if ( Inequality( p.Curr ) ) { double absCX = Math.Abs( circleNormal.X ); circleNormal.X = ( faceNormal.X < 0 ) ? absCX : -absCX; circleNormal.Y = Math.Abs( circleNormal.Y ); } // get contact point on edge of circle Vector contactPoint = p.Curr.PlusNew( circleNormal.Mult( p.Radius ) ); if ( SegmentInequality( contactPoint ) ) { if ( contactPoint.Distance( p.ClosestPoint ) > collisionDepth ) return false; double dx = contactPoint.X - p.ClosestPoint.X; double dy = contactPoint.Y - p.ClosestPoint.Y; p.MTD.Set( -dx, -dy ); return true; } return false; }
public virtual void ResolveCircleCollision( CircleParticle p, Engine engine, ref CollisionState state ) { }
protected void Create(double x, double y) { // create the bicycle double leftX = x - 18; double rightX = x + 18; double widthX = rightX - leftX; double midX = leftX + (widthX / 2); double topY = y + 0; // wheels wheelA = new Wheel(leftX, topY, 12); Add(wheelA, "wheelA"); wheelB = new Wheel(rightX, topY, 12); Add(wheelB, "wheelB"); // body PhysicsObject[] objs; SpringBox rectA = new SpringBox(midX, topY, widthX, 15, out objs); foreach (PhysicsObject o in objs) { Add(o); } // wheel struts SpringConstraint conn1 = new SpringConstraint(wheelA, rectA.P3); Add(conn1); SpringConstraint conn2 = new SpringConstraint(wheelB, rectA.P2); Add(conn2); SpringConstraint conn1a = new SpringConstraint(wheelA, rectA.P0); Add(conn1a); SpringConstraint conn2a = new SpringConstraint(wheelB, rectA.P1); Add(conn2a); // triangle top of car personHead = new CircleParticle(midX, topY - 30, 5); Add(personHead); personHead.Contact += delegate(object sender, EventArgs e) { Kill(); }; sHeadToWheelA = new SpringConstraint(personHead, wheelA); Add(sHeadToWheelA); sHeadToWheelB = new SpringConstraint(personHead, wheelB); Add(sHeadToWheelB); // angular constraint for triangle top sBikeAngular = new AngularConstraint(wheelA, personHead, wheelB); Add(sBikeAngular); angDefault = sBikeAngular.TargetTheta; personBody = new CircleParticle(midX - 5, topY - 20, 5); personLegs = new CircleParticle(midX, topY - 5, 5); aPose = new AngularConstraint(personHead, personBody, personLegs); sHeadToBody = new SpringConstraint(personHead, personBody); sHeadToBody.RestLength = 12; Add(sHeadToBody); sBodyToLegs = new SpringConstraint(personBody, personLegs); sBodyToLegs.RestLength = 12; Add(sBodyToLegs); Add(personBody); Add(personLegs); sLegsToWheelB = new SpringConstraint(personLegs, wheelB); sLegsToWheelB.RestLength = 20; Add(sLegsToWheelB); sLegsToWheelA = new SpringConstraint(personLegs, wheelA); sLegsToWheelA.RestLength = 20; Add(sLegsToWheelA); }
private bool IsCircleColliding( CircleParticle p ) { p.GetCardXProjection(); double depthX = TestIntervals( p.BMin, p.BMax, minX, maxX ); if ( depthX == 0 ) return false; p.GetCardYProjection(); double depthY = TestIntervals( p.BMin, p.BMax, minY, maxY ); if ( depthY == 0 ) return false; double dx = center.X - p.Curr.X; double dy = center.Y - p.Curr.Y; double len = Math.Sqrt( dx * dx + dy * dy ); double pen = ( p.Radius + radius ) - len; if ( pen > 0 ) { dx /= len; dy /= len; p.MTD.Set( -dx * pen, -dy * pen ); normal.Set( -dx, -dy ); return true; } return false; }
public override void ResolveCircleCollision( CircleParticle p, Engine engine, ref CollisionState state ) { if ( Collision.IsEllipseCollision( curr, Size, 0, p.curr, p.Size, 0, out state ) ) { Vector normal = state.Depth.Clone().Normalize(); Vector vel1 = curr.MinusNew( prev ); Vector vel2 = p.curr.MinusNew( p.prev ); p.prev = p.curr.PlusNew( state.Depth ); prev = curr.MinusNew( state.Depth ); } }