public override float ComputeSweepRadius(Vec2 pivot) { float ds1 = Vec2.DistanceSquared(_v1, pivot); float ds2 = Vec2.DistanceSquared(_v2, pivot); return(Common.Math.Sqrt(Common.Math.Max(ds1, ds2))); }
public void Update(double dt) { Time += (float)dt; Position = StartingPosition + Velocity * Time; if (Vec2.DistanceSquared(Position, StartingPosition) > Range * Range) { Active = false; } }
internal void Initialize(ContactConstraint cc) { Box2DXDebug.Assert(cc.PointCount > 0); switch (cc.Type) { case ManifoldType.Circles: { Vec2 pointA = cc.BodyA.GetWorldPoint(cc.LocalPoint); Vec2 pointB = cc.BodyB.GetWorldPoint(cc.Points[0].LocalPoint); if (Vec2.DistanceSquared(pointA, pointB) > Settings.FLT_EPSILON_SQUARED) { Normal = pointB - pointA; Normal.Normalize(); } else { Normal.Set(1.0f, 0.0f); } Points[0] = 0.5f * (pointA + pointB); Separations[0] = Vec2.Dot(pointB - pointA, Normal) - cc.Radius; } break; case ManifoldType.FaceA: { Normal = cc.BodyA.GetWorldVector(cc.LocalPlaneNormal); Vec2 planePoint = cc.BodyA.GetWorldPoint(cc.LocalPoint); for (int i = 0; i < cc.PointCount; ++i) { Vec2 clipPoint = cc.BodyB.GetWorldPoint(cc.Points[i].LocalPoint); Separations[i] = Vec2.Dot(clipPoint - planePoint, Normal) - cc.Radius; Points[i] = clipPoint; } } break; case ManifoldType.FaceB: { Normal = cc.BodyB.GetWorldVector(cc.LocalPlaneNormal); Vec2 planePoint = cc.BodyB.GetWorldPoint(cc.LocalPoint); for (int i = 0; i < cc.PointCount; ++i) { Vec2 clipPoint = cc.BodyA.GetWorldPoint(cc.Points[i].LocalPoint); Separations[i] = Vec2.Dot(clipPoint - planePoint, Normal) - cc.Radius; Points[i] = clipPoint; } // Ensure normal points from A to B Normal = -Normal; } break; } }
static Vec2 ValidateActionPosition(IEntity player, PlayerAction action) { Vec2 position = action.Position; // If the position provided by the client seems legit, we take it. Otherwise, we ignore it // and log it (might be a hacker). if (Vec2.DistanceSquared(player.Position, position) >= MAX_TOLERATED_OFF_DISTANCE * MAX_TOLERATED_OFF_DISTANCE) { position = player.Position; } return(position); }
void SmoothTowardsInterpolatedPosition() { float distanceSq = Vec2.DistanceSquared(DrawnPosition, Position); if (distanceSq < POSITION_DISTANCE_TO_SNAP * POSITION_DISTANCE_TO_SNAP) { DrawnPosition = Vec2.Lerp(DrawnPosition, Position, SMOOTH_LERP_FACTOR); } else { ILogger.Log(String.Format("Snapping remote client position({0}) to simulated({1}). -> distance squared:{2}", DrawnPosition, Position, distanceSq), LogPriority.High); DrawnPosition = Position; } }
/// <summary> /// Lerps the drawn position towards our simulated position. /// </summary> void LerpTowardsSimulatedPosition(double deltaSeconds) { float distanceSq = Vec2.DistanceSquared(Position, DrawnPosition); if (distanceSq >= POSITION_DISTANCE_TO_SNAP * POSITION_DISTANCE_TO_SNAP) // if we must snap directly to the simulated position { ILogger.Log(String.Format("Snapping position({0}) to simulated({1}). -> distance squared:{2}", DrawnPosition, Position, distanceSq), LogPriority.High); DrawnPosition = Position; } else // If we must interpolate our position (we're not too far) { DrawnPosition = Vec2.Lerp(DrawnPosition, Position, SMOOTH_FACTOR); } }
public override float ComputeSweepRadius(Vec2 pivot) { int vCount = _vertexCount; Box2DNetDebug.Assert(vCount > 0); float sr = Vec2.DistanceSquared(_vertices[0], pivot); for (int i = 1; i < vCount; ++i) { sr = Common.Math.Max(sr, Vec2.DistanceSquared(_vertices[i], pivot)); } return(Common.Math.Sqrt(sr)); }
private void GetClosestPointTo(Vec2 point, out Vec2 closest, out int lineIndex) { closest = Vec2.Invalid; lineIndex = -1; float num1 = float.MaxValue; for (int index = 0; index < this.LineCount; ++index) { Vec2 lineSegmentToPoint = MBMath.GetClosestPointInLineSegmentToPoint(point, this._navigationData.Points[index], this._navigationData.Points[index + 1]); float num2 = lineSegmentToPoint.DistanceSquared(point); if ((double)num2 < (double)num1) { num1 = num2; closest = lineSegmentToPoint; lineIndex = index; } } }
protected override void CalculateCurrentOrder() { Vec2 vec2_1; if (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation != null && this._mainFormation != null) { Vec2 vec2_2 = (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MedianPosition.AsVec2 - this.formation.QuerySystem.AveragePosition).Normalized(); Vec2 v = (this._mainFormation.QuerySystem.MedianPosition.AsVec2 - this.formation.QuerySystem.AveragePosition).Normalized(); vec2_1 = (double)vec2_2.DotProduct(v) <= 0.5 ? vec2_2 : this._mainFormation.FacingOrder.GetDirection(this._mainFormation); } else { vec2_1 = this.formation.Direction; } WorldPosition medianPosition; if (this._mainFormation == null) { medianPosition = this.formation.QuerySystem.MedianPosition; medianPosition.SetVec2(this.formation.QuerySystem.AveragePosition); } else { medianPosition = this._mainFormation.QuerySystem.MedianPosition; medianPosition.SetVec2(medianPosition.AsVec2 - vec2_1 * (float)(((double)this._mainFormation.Depth + (double)this.formation.Depth) * 0.5)); } WorldPosition worldPosition = this.CurrentOrder.GetPosition(this.formation); if (worldPosition.IsValid && this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.IsRangedCavalryFormation) { Vec2 averagePosition = this.formation.QuerySystem.AveragePosition; ref Vec2 local = ref averagePosition; worldPosition = this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MedianPosition; Vec2 asVec2 = worldPosition.GetNavMeshVec3().AsVec2; if ((double)local.DistanceSquared(asVec2) < (double)this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MissileRange * (double)this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MissileRange) { worldPosition = this.CurrentOrder.GetPosition(this.formation); if ((double)worldPosition.GetNavMeshVec3().DistanceSquared(medianPosition.GetNavMeshVec3()) < (double)this.formation.Depth * (double)this.formation.Depth) { goto label_10; } } }
public override void Draw() { Canvas.Clear(Color.Black); foreach (var particle in Particles) { var color = Color.Lerp(Color.Cyan, Color.DarkCyan, particle.Velocity.LengthSquared() / 1000); Vec2?closestGravityPoint = null; foreach (var gravityPoints in GravityPoints) { if (closestGravityPoint is null) { closestGravityPoint = gravityPoints; } else if (closestGravityPoint?.DistanceSquared(particle.Position) > gravityPoints.DistanceSquared(particle.Position)) { closestGravityPoint = gravityPoints; } } color = Color.Lerp(Color.Red, color, Vec2.Distance(particle.Position, closestGravityPoint.Value) / 100); Canvas.DrawRectangle(particle.Position, new Vec2(5, 5), true, color); } Canvas.Present(); }
public static void CircleToPolygon(Manifold m, Body a, Body b) { Circle shapeA = a.shape as Circle; Polygon shapeB = b.shape as Polygon; m.contactCount = 0; // Transform circle center to Polygon model space Vec2 center = a.position; center = shapeB.transform.WorldToLocalPosition(center); // Find edge with minimum penetration // Exact concept as using support points in Polygon vs Polygon float separation = float.MinValue; int faceNormal = 0; for (int i = 0; i < shapeB.VertexCount; ++i) { float s = Vec2.Dot(shapeB.normals[i], center - shapeB.vertices[i]); if (s > shapeA.radius) { return; } if (s > separation) { separation = s; faceNormal = i; } } // Grab face's vertices Vec2 v1 = shapeB.vertices[faceNormal]; int i2 = faceNormal + 1 < shapeB.VertexCount ? faceNormal + 1 : 0; Vec2 v2 = shapeB.vertices[i2]; Contact c = new Contact(Vec2.Zero); // Check to see if center is within polygon if (separation < float.Epsilon) { m.normal = -shapeB.transform.LocalToWorldDirection(shapeB.normals[faceNormal]); c.position = m.normal * shapeA.radius + a.position; c.penetration = shapeA.radius; m.Update(1, c); return; } // Determine which voronoi region of the edge center of circle lies within float dot1 = Vec2.Dot(center - v1, v2 - v1); float dot2 = Vec2.Dot(center - v2, v1 - v2); c.penetration = shapeA.radius - separation; // Closest to v1 if (dot1 <= 0.0f) { if (Vec2.DistanceSquared(center, v1) > shapeA.radius * shapeA.radius) { return; } Vec2 n = v1 - center; n = shapeB.transform.LocalToWorldDirection(n); n.Normalize(); m.normal = n; v1 = shapeB.transform.LocalToWorldPosition(v1); c.position = v1; m.Update(1, c); } // Closest to v2 else if (dot2 <= 0.0f) { if (Vec2.DistanceSquared(center, v2) > shapeA.radius * shapeA.radius) { return; } Vec2 n = v2 - center; v2 = shapeB.transform.LocalToWorldPosition(v2); c.position = v2; m.Update(1, c); n = shapeB.transform.LocalToWorldDirection(n); n.Normalize(); m.normal = n; } // Closest to face else { Vec2 n = shapeB.normals[faceNormal]; if (Vec2.Dot(center - v1, n) > shapeA.radius) { return; } n = shapeB.transform.LocalToWorldDirection(n); m.normal = -n; c.position = m.normal * shapeA.radius + a.position; m.Update(1, c); } }
/// Evaluate the manifold with supplied transforms. This assumes /// modest motion from the original state. This does not change the /// point count, impulses, etc. The radii must come from the shapes /// that generated the manifold. public void Initialize(Manifold manifold, XForm xfA, float radiusA, XForm xfB, float radiusB) { if (manifold.PointCount == 0) { return; } switch (manifold.Type) { case ManifoldType.Circles: { Vec2 pointA = Math.Mul(xfA, manifold.LocalPoint); Vec2 pointB = Math.Mul(xfB, manifold.Points[0].LocalPoint); Vec2 normal = new Vec2(1.0f, 0.0f); if (Vec2.DistanceSquared(pointA, pointB) > Settings.FltEpsilonSquared) { normal = pointB - pointA; normal.Normalize(); } Normal = normal; Vec2 cA = pointA + radiusA * normal; Vec2 cB = pointB - radiusB * normal; Points[0] = 0.5f * (cA + cB); } break; case ManifoldType.FaceA: { Vec2 normal = Math.Mul(xfA.R, manifold.LocalPlaneNormal); Vec2 planePoint = Math.Mul(xfA, manifold.LocalPoint); // Ensure normal points from A to B. Normal = normal; for (int i = 0; i < manifold.PointCount; ++i) { Vec2 clipPoint = Math.Mul(xfB, manifold.Points[i].LocalPoint); Vec2 cA = clipPoint + (radiusA - Vec2.Dot(clipPoint - planePoint, normal)) * normal; Vec2 cB = clipPoint - radiusB * normal; Points[i] = 0.5f * (cA + cB); } } break; case ManifoldType.FaceB: { Vec2 normal = Math.Mul(xfB.R, manifold.LocalPlaneNormal); Vec2 planePoint = Math.Mul(xfB, manifold.LocalPoint); // Ensure normal points from A to B. Normal = -normal; for (int i = 0; i < manifold.PointCount; ++i) { Vec2 clipPoint = Math.Mul(xfA, manifold.Points[i].LocalPoint); Vec2 cA = clipPoint - radiusA * normal; Vec2 cB = clipPoint + (radiusB - Vec2.Dot(clipPoint - planePoint, normal)) * normal; Points[i] = 0.5f * (cA + cB); } } break; } }
// This implements 2-sided edge vs circle collision. public static void CollideEdgeAndCircle(ref Manifold manifold, EdgeShape edge, XForm transformA, CircleShape circle, XForm transformB) { manifold.PointCount = 0; Vec2 cLocal = Common.Math.MulT(transformA, Common.Math.Mul(transformB, circle._position)); Vec2 normal = edge._normal; Vec2 v1 = edge._v1; Vec2 v2 = edge._v2; float radius = edge._radius + circle._radius; // Barycentric coordinates float u1 = Vec2.Dot(cLocal - v1, v2 - v1); float u2 = Vec2.Dot(cLocal - v2, v1 - v2); if (u1 <= 0.0f) { // Behind v1 if (Vec2.DistanceSquared(cLocal, v1) > radius * radius) { return; } manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = cLocal - v1; manifold.LocalPlaneNormal.Normalize(); manifold.LocalPoint = v1; manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; } else if (u2 <= 0.0f) { // Ahead of v2 if (Vec2.DistanceSquared(cLocal, v2) > radius * radius) { return; } manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = cLocal - v2; manifold.LocalPlaneNormal.Normalize(); manifold.LocalPoint = v2; manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; } else { float separation = Vec2.Dot(cLocal - v1, normal); if (separation < -radius || radius < separation) { return; } manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = separation < 0.0f ? -normal : normal; manifold.LocalPoint = 0.5f * (v1 + v2); manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; } }
public void TestDistance(Vec2 a, Vec2 b, float dist, string msg, float eps = float.Epsilon) { Assert.AreEqual(dist, Vec2.Distance(a, b), eps, msg); Assert.AreEqual(dist * dist, Vec2.DistanceSquared(a, b), eps, msg + " squared"); }
protected override void CalculateCurrentOrder() { Vec2 averagePosition = this.formation.QuerySystem.AveragePosition; if (this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation == null) { WorldPosition medianPosition = this.formation.QuerySystem.MedianPosition; medianPosition.SetVec2(averagePosition); this.CurrentOrder = MovementOrder.MovementOrderMove(medianPosition); } else { WorldPosition medianPosition = this.formation.QuerySystem.ClosestSignificantlyLargeEnemyFormation.MedianPosition; IEnumerable <Formation> source = this.formation.Team.FormationsIncludingSpecial.Where <Formation>((Func <Formation, bool>)(f => f != this.formation)); Vec2 vec2_1 = source.Any <Formation>() ? new Vec2(source.Average <Formation>((Func <Formation, float>)(oa => oa.QuerySystem.MedianPosition.AsVec2.x)), source.Average <Formation>((Func <Formation, float>)(oa => oa.QuerySystem.MedianPosition.AsVec2.y))) : averagePosition; WorldPosition formationPosition = this.formation.QuerySystem.Team.MedianTargetFormationPosition; Vec2 vec2_2 = (formationPosition.AsVec2 - vec2_1).Normalized(); float missileRange = this.formation.QuerySystem.MissileRange; WorldPosition position; if (this._rushMode) { float num = averagePosition.DistanceSquared(medianPosition.AsVec2); if ((double)num > (double)this.formation.QuerySystem.MissileRange * (double)this.formation.QuerySystem.MissileRange) { position = formationPosition; position.SetVec2(position.AsVec2 - vec2_2 * (missileRange - (float)(10.0 + (double)this.formation.Depth * 0.5))); } else if (this.formation.QuerySystem.ClosestEnemyFormation.IsCavalryFormation || (double)num <= 400.0 || (double)this.formation.QuerySystem.UnderRangedAttackRatio >= 0.400000005960464) { position = this.formation.QuerySystem.Team.MedianPosition; position.SetVec2(vec2_1 - ((source.Any <Formation>() ? 30f : 80f) + this.formation.Depth) * vec2_2); this._rushMode = false; } else { position = this.formation.QuerySystem.Team.MedianPosition; Vec2 vec2_3 = (medianPosition.AsVec2 - averagePosition).Normalized(); position.SetVec2(medianPosition.AsVec2 - vec2_3 * (missileRange - (float)(10.0 + (double)this.formation.Depth * 0.5))); } } else { if (source.Any <Formation>()) { position = this.formation.QuerySystem.Team.MedianPosition; position.SetVec2(vec2_1 - (30f + this.formation.Depth) * vec2_2); } else { position = this.formation.QuerySystem.ClosestEnemyFormation.MedianPosition; position.SetVec2(position.AsVec2 - 80f * vec2_2); } if ((double)position.AsVec2.DistanceSquared(averagePosition) <= 400.0) { position = formationPosition; position.SetVec2(position.AsVec2 - vec2_2 * (missileRange - (float)(10.0 + (double)this.formation.Depth * 0.5))); this._rushMode = true; } } this.CurrentOrder = MovementOrder.MovementOrderMove(position); } }
public static void CollidePolygonAndCircle(ref Manifold manifold, PolygonShape polygon, XForm xf1, CircleShape circle, XForm xf2) { manifold.PointCount = 0; // Compute circle position in the frame of the polygon. Vec2 c = Common.Math.Mul(xf2, circle._position); Vec2 cLocal = Common.Math.MulT(xf1, c); // Find the min separating edge. int normalIndex = 0; float separation = -Settings.FLT_MAX; float radius = polygon._radius + circle._radius; int vertexCount = polygon._vertexCount; Vec2[] vertices = polygon._vertices; Vec2[] normals = polygon._normals; for (int i = 0; i < vertexCount; ++i) { float s = Vec2.Dot(normals[i], cLocal - vertices[i]); if (s > radius) { // Early out. return; } if (s > separation) { separation = s; normalIndex = i; } } // Vertices that subtend the incident face. int vertIndex1 = normalIndex; int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; Vec2 v1 = vertices[vertIndex1]; Vec2 v2 = vertices[vertIndex2]; // If the center is inside the polygon ... if (separation < Common.Settings.FLT_EPSILON) { manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = normals[normalIndex]; manifold.LocalPoint = 0.5f * (v1 + v2); manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; return; } // Compute barycentric coordinates float u1 = Vec2.Dot(cLocal - v1, v2 - v1); float u2 = Vec2.Dot(cLocal - v2, v1 - v2); if (u1 <= 0.0f) { if (Vec2.DistanceSquared(cLocal, v1) > radius * radius) { return; } manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = cLocal - v1; manifold.LocalPlaneNormal.Normalize(); manifold.LocalPoint = v1; manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; } else if (u2 <= 0.0f) { if (Vec2.DistanceSquared(cLocal, v2) > radius * radius) { return; } manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = cLocal - v2; manifold.LocalPlaneNormal.Normalize(); manifold.LocalPoint = v2; manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; } else { Vec2 faceCenter = 0.5f * (v1 + v2); float separation_ = Vec2.Dot(cLocal - faceCenter, normals[vertIndex1]); if (separation_ > radius) { return; } manifold.PointCount = 1; manifold.Type = ManifoldType.FaceA; manifold.LocalPlaneNormal = normals[vertIndex1]; manifold.LocalPoint = faceCenter; manifold.Points[0].LocalPoint = circle._position; manifold.Points[0].ID.Key = 0; } }
public bool ReachedMaxRange() { return(Vec2.DistanceSquared(Position, StartPosition) >= Info.Range * Info.Range); }