public static bool Intersects(ref Circle a, ref RectangleF b, out float depth, out Vector2 normal) { normal = new Vector2(a.Center.X - (b.X + b.Width / 2), a.Center.Y - (b.Y + b.Height / 2)); #if NETSTANDARD2_1 Vector2 distance = new Vector2(MathF.Abs(normal.X), MathF.Abs(normal.Y)); #else Vector2 distance = new Vector2(Math.Abs(normal.X), Math.Abs(normal.Y)); #endif normal = Vector2.Normalize(normal); depth = distance.Length(); if (float.IsNaN(depth)) { normal = new Vector2(0, 0); depth = 0f; return(false); } if (distance.X > b.Width / 2 + a.Radius / 2 || distance.Y > b.Height / 2 + a.Radius / 2) { return(false); } if (distance.X <= b.Width / 2 || distance.Y <= b.Height / 2) { return(true); } #if NETSTANDARD2_1 float distanceSq = MathF.Pow(distance.X - b.Width / 2, 2) + MathF.Pow(distance.Y - b.Height / 2, 2); return(distanceSq <= MathF.Pow(a.Radius, 2)); #else double distanceSq = Math.Pow(distance.X - b.Width / 2, 2) + Math.Pow(distance.Y - b.Height / 2, 2); return(distanceSq <= Math.Pow(a.Radius, 2)); #endif }
void RenderVerts(System.Numerics.Vector2 position, System.Numerics.Vector2 lightPos, System.Numerics.Vector2[] verts) { // TODO: should we check to see if the light is inside the verts and early out? for (var i = 0; i < verts.Length; i++) { var vertex = verts[i] + position; var nextVertex = verts[(i + 1) % verts.Length] + position; var startToEnd = nextVertex - vertex; var lightToStart = lightPos - vertex; var normal = new System.Numerics.Vector2(startToEnd.Y, -startToEnd.X); normal.Normalize(); var nDotL = System.Numerics.Vector2.Dot(normal, lightToStart); if (nDotL > 0) { var midpoint = (nextVertex + vertex) * 0.5f; Debug.DrawLine(vertex, nextVertex, Color.Green); Debug.DrawLine(midpoint, midpoint + normal * 20, Color.Green); var point1 = nextVertex + (System.Numerics.Vector2.Normalize(nextVertex - lightPos) * Screen.Width); var point2 = vertex + (System.Numerics.Vector2.Normalize(vertex - lightPos) * Screen.Width); var poly = new System.Numerics.Vector2[] { nextVertex, point1, point2, vertex }; _vertBuffer[0] = nextVertex; _vertBuffer[1] = point1; _vertBuffer[2] = point2; _vertBuffer[3] = vertex; _primitiveBatch.DrawPolygon(poly, 4, Color.Black); } } }
public static float IncludedAngleCos(Vector2 v1, Vector2 v2) { v1.Normalize(); v2.Normalize(); float dot = Vector2.Dot(v1, v2); return(2 * dot / (v1.Length() + v2.Length())); }
public override void OnFixedUpdate() { if (Owner.NetIdentity == null || !Owner.NetIdentity.IsOwner) { return; } if (PhysicsObject == null) { PhysicsObject = Owner.GetComponent <PhysicsObject>(); } Vector2 velocity = Vector2.Zero; if (UIManager.IsKeyboardFree()) { velocity.Y = InputManager.AxisState(PlayerIndex, "PlayerVertical") * 256; velocity.X = InputManager.AxisState(PlayerIndex, "PlayerHorizontal") * 256; } if (MathF.Abs(velocity.Y) > 128f && MathF.Abs(velocity.X) > 128f) { velocity = Vector2.Normalize(velocity); velocity *= 256; } PhysicsObject.Body.LinearVelocity = velocity; base.OnUpdate(); }
void IUpdatable.Update() { if (Math.Abs(_shakeIntensity) > 0f) { _shakeOffset = _shakeDirection; if (_shakeOffset.X != 0f || _shakeOffset.Y != 0f) { _shakeOffset.Normalize(); } else { _shakeOffset.X = _shakeOffset.X + Random.NextFloat() - 0.5f; _shakeOffset.Y = _shakeOffset.Y + Random.NextFloat() - 0.5f; } // TODO: this needs to be multiplied by camera zoom so that less shake gets applied when zoomed in _shakeOffset *= _shakeIntensity; _shakeIntensity *= -_shakeDegredation; if (Math.Abs(_shakeIntensity) <= 0.01f) { _shakeIntensity = 0f; Enabled = false; } } Entity.Scene.Camera.Position += _shakeOffset; }
protected override void OnUpdate() { timer -= Time.DeltaTime; if (timer < 0) { nodes = NavigationManager.NavGrids[0].FindPath(Owner.Transform.GlobalPositionInternal, Screen.MousePoint.HasValue ? Screen.MousePoint.Value : new Vector2(9999, 9999)); timer = 0.333f; } if (nodes != null && nodes.Count > 0) { if (node == null || ((NavigationManager.NavGrids[0].GetPosition(node) - Owner.Transform.GlobalPositionInternal).Length() < 0.5f)) { node = nodes.Pop(); } if (node != null) { Vector2 diff = NavigationManager.NavGrids[0].GetPosition(node) - Owner.Transform.GlobalPositionInternal; lookAt = NavigationManager.NavGrids[0].GetPosition(node); diff = Vector2.Normalize(diff); myPhysics.Body.LinearVelocity = diff * 192; } } Owner.Transform.Rotation = Owner.Transform.GlobalPositionInternal.GetRotationFacing(lookAt); base.OnUpdate(); }
public void DrawArrow(System.Numerics.Vector2 start, System.Numerics.Vector2 end, float length, float width, bool drawStartIndicator, Color color) { // Draw connection segment between start- and end-point //drawLine( start, end, color ); // Precalculate halfwidth var halfWidth = width / 2; // Create directional reference System.Numerics.Vector2 rotation = (start - end); rotation.Normalize(); // Calculate angle of directional vector float angle = (float)Math.Atan2(rotation.X, -rotation.Y); // Create matrix for rotation Matrix2D rotMatrix = Matrix2D.CreateRotation(angle); // Create translation matrix for end-point Matrix2D endMatrix = Matrix2D.CreateTranslation(end.X, end.Y); // Setup arrow end shape System.Numerics.Vector2[] verts = new System.Numerics.Vector2[3]; verts[0] = new System.Numerics.Vector2(0, 0); verts[1] = new System.Numerics.Vector2(-halfWidth, -length); verts[2] = new System.Numerics.Vector2(halfWidth, -length); // Rotate end shape Vector2Ext.Transform(verts, ref rotMatrix, verts); // Translate end shape Vector2Ext.Transform(verts, ref endMatrix, verts); // Draw arrow end shape DrawPolygon(verts, 3, color); if (drawStartIndicator) { // Create translation matrix for start Matrix2D startMatrix = Matrix2D.CreateTranslation(start.X, start.Y); // Setup arrow start shape System.Numerics.Vector2[] baseVerts = new System.Numerics.Vector2[4]; baseVerts[0] = new System.Numerics.Vector2(-halfWidth, length / 4); baseVerts[1] = new System.Numerics.Vector2(halfWidth, length / 4); baseVerts[2] = new System.Numerics.Vector2(halfWidth, 0); baseVerts[3] = new System.Numerics.Vector2(-halfWidth, 0); // Rotate start shape Vector2Ext.Transform(baseVerts, ref rotMatrix, baseVerts); // Translate start shape Vector2Ext.Transform(baseVerts, ref startMatrix, baseVerts); // Draw start shape DrawPolygon(baseVerts, 4, color); } }
private static void _FillSegmentVertices(Span <POINT2> dst, POINT2 a, POINT2 b, float diameter) { var aa = a.XY; var bb = b.XY; var axisX = VECTOR2.Normalize(bb - aa) * diameter * 0.25f; var axisY = new VECTOR2(axisX.Y, -axisX.X); dst[0] = aa - axisY; dst[1] = aa + axisY; dst[2] = bb + axisY; dst[3] = bb - axisY; }
static bool FindMinimumTranslationDistance(int iNumAxes, out System.Numerics.Vector2 normal, out float timeOfIntersection) { // find collision first var mini = -1; timeOfIntersection = 0f; normal = new System.Numerics.Vector2(0, 0); for (var i = 0; i < iNumAxes; i++) { if (_satTimerPerAxis[i] > 0 && _satTimerPerAxis[i] > timeOfIntersection) { mini = i; timeOfIntersection = _satTimerPerAxis[i]; normal = _satAxisArray[i]; normal.Normalize(); } } // found one if (mini != -1) { return(true); } // nope, find overlaps mini = -1; for (var i = 0; i < iNumAxes; i++) { var n = _satAxisArray[i].Length(); _satAxisArray[i].Normalize(); _satTimerPerAxis[i] /= n; if (_satTimerPerAxis[i] > timeOfIntersection || mini == -1) { mini = i; timeOfIntersection = _satTimerPerAxis[i]; normal = _satAxisArray[i]; } } if (mini == -1) { Debug.Error("Error"); } return(mini != -1); }
public static bool Intersects(ref Circle a, ref Circle b, out float depth, out Vector2 normal) { Vector2 distance = a.Center - b.Center; depth = distance.Length(); if (float.IsNaN(depth)) { normal = new Vector2(0, 0); depth = 0f; return(false); } float radiusSum = a.Radius > b.Radius ? b.Radius : a.Radius; normal = Vector2.Normalize(distance); return(depth <= radiusSum); }
public Prismatic() { Body ground; { var bd = new BodyDef(); ground = World.CreateBody(bd); var shape = new EdgeShape(); shape.Set(new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f)); ground.CreateFixture(shape, 0.0f); } { var shape = new PolygonShape(); shape.SetAsBox(2.0f, 0.5f); var bd = new BodyDef(); bd.BodyType = BodyType.DynamicBody; bd.Position.Set(-10.0f, 10.0f); bd.Angle = 0.5f * Settings.Pi; bd.AllowSleep = false; var body = World.CreateBody(bd); body.CreateFixture(shape, 5.0f); var pjd = new PrismaticJointDef(); // Bouncy limit var axis = new Vector2(2.0f, 1.0f); axis = Vector2.Normalize(axis); pjd.Initialize(ground, body, new Vector2(0.0f, 0.0f), axis); // Non-bouncy limit //pjd.Initialize(ground, body, new Vector2(-10.0f, 10.0f), new Vector2(1.0f, 0.0f)); pjd.MotorSpeed = 10.0f; pjd.MaxMotorForce = 10000.0f; pjd.EnableMotor = true; pjd.LowerTranslation = 0.0f; pjd.UpperTranslation = 20.0f; pjd.EnableLimit = true; _joint = (PrismaticJoint)World.CreateJoint(pjd); } }
public static void FillRectangleVertices(this Span <POINT2> vertices, XFORM2 rect, float borderRadius, int arcVertexCount = 6) { var scaleX = new VECTOR2(rect.M11, rect.M12); var scaleY = new VECTOR2(rect.M21, rect.M22); var origin = new VECTOR2(rect.M31, rect.M32); if (vertices.Length == 4) { vertices[0] = origin; vertices[1] = origin + scaleX; vertices[2] = origin + scaleX + scaleY; vertices[3] = origin + scaleY; return; } int idx = 0; var sizeX = scaleX.Length(); var axisX = VECTOR2.Normalize(scaleX); var sizeY = scaleY.Length(); var axisY = VECTOR2.Normalize(scaleY); throw new NotImplementedException(); // top vertices[idx++] = origin + axisX * borderRadius; vertices[idx++] = origin + axisX * (sizeX - borderRadius); // top right var center = origin + axisX * (sizeX - borderRadius) + axisY * borderRadius; foreach (var p in _GetRectangleCornerVertices(arcVertexCount, PI * 0.5f, 0f)) { vertices[idx++] = center + (axisX * p.X + axisY * p.Y) * borderRadius; } // right vertices[idx++] = origin + axisX * (sizeX - borderRadius); vertices[idx++] = origin + new POINT2(sizeX, sizeY - borderRadius); // bottom right center = origin + new VECTOR2(sizeX - borderRadius, sizeY - borderRadius); foreach (var p in _GetRectangleCornerVertices(arcVertexCount, 0, -PI * 0.5f)) { vertices[idx++] = center + p * borderRadius; } // bottom vertices[idx++] = origin + new POINT2(sizeX - borderRadius, sizeY); vertices[idx++] = origin + new POINT2(borderRadius, sizeY); // bottom left center = origin + new VECTOR2(borderRadius, sizeY - borderRadius); foreach (var p in _GetRectangleCornerVertices(arcVertexCount, -PI * 0.5f, -PI)) { vertices[idx++] = center + p * borderRadius; } // left vertices[idx++] = origin + new POINT2(0, sizeY - borderRadius); vertices[idx++] = origin + new POINT2(0, borderRadius); // top left center = origin + new VECTOR2(borderRadius, borderRadius); foreach (var p in _GetRectangleCornerVertices(arcVertexCount, -PI, -PI * 1.5f)) { vertices[idx++] = center + p * borderRadius; } }
/// <summary> /// 朝向方向(入参为一个代表方向的向量) /// </summary> /// <param name="body"></param> /// <param name="targetPoint"></param> /// <param name="angularVelocityProc"></param> /// <returns></returns> public static float MoveForward(this Body body, Vector2 targetPoint, float angularVelocityProc) { targetPoint.Normalize(); return(FowardToTarget(body, targetPoint + body.GetPosition(), angularVelocityProc)); }
private void CreateOutline(IEnumerable <Vector2> shape, bool createFace) { Contract.Requires(shape != null); var vertices = (IReadOnlyList <Vertex>)shape.Select(_mesh.GetOrConstructVertex).ToArray(); var edges = new List <HalfEdge>(vertices.Count * 3); // Create the outer edges of the floor for (var i = 0; i < vertices.Count; i++) { //Start and end vertex of this wall var b = vertices[i]; var c = vertices[(i + 1) % vertices.Count]; //Create a series of edges between these two vertices (not just one edge, because we drop seeds along the line as we go) CreateImpassableEdge(b, c, edges); //We want to measure the internal angle at vertex "b", for that we need the previous vertex (which we'll call "a") var a = vertices[(i + vertices.Count - 1) % vertices.Count]; //Calculate the inner angle between these vectors (not always clockwise!) var ab = Vector2.Normalize(b.Position - a.Position); var bc = Vector2.Normalize(c.Position - b.Position); var dot = Vector2.Dot(bc, -ab); var det = bc.Cross(-ab); var angle = (float)(Math.Atan2(det, dot) % (Math.PI * 2)); angle = det < 0 ? angle * -1 : (float)Math.PI * 2 - angle; if (angle < Math.PI * 0.51) { //0 -> 90 degrees //Do nothing! } else if (angle <= Math.PI * 1.01) { //90 -> 180 if (_random.RandomBoolean()) { PerpendicularSeed(b, ab); } else { PerpendicularSeed(b, bc); } } else if (angle <= Math.PI * 1.51) { //180 -> 270 //if (_random.RandomBoolean()) // BisectorSeed(b, -ab, -bc); //Negated, to ensure bisection is on the correct side (angle is > 180, so by default bisection would be on wrong side) //else { PerpendicularSeed(b, ab); PerpendicularSeed(b, bc); } } else { //270 -> 360 //BisectorSeed(b, -ab, -bc); //Negated, to ensure bisection is on the correct side (angle is > 180, so by default bisection would be on wrong side) PerpendicularSeed(b, ab); PerpendicularSeed(b, bc); } } if (createFace) { //Ensure we're always creating the clockwise face if (!edges.Select(a => a.EndVertex.Position).IsClockwise()) { edges.Reverse(); for (var i = 0; i < edges.Count; i++) { edges[i] = edges[i].Pair; } } //Create face //todo: attach spacespec metadata (passed in instead of bool:createFace) var f = _mesh.GetOrConstructFace(edges); f.Tag = new FloorplanFaceTag(false); } }