public void Transfer(float radians, Gear target) { var ratio = this.NumberOfTeeth / (float)target.NumberOfTeeth; var targetRadians = radians * ratio; target.Spin(targetRadians * target.Direction); // Solve colisions due to small inaccuracies // 1. Find tooth closest to target gear var targetPosition2D = new Vector2(target.Position.X, target.Position.Z); var myClosestTooth = GetToothClosestToPoint(targetPosition2D); // 2. Find tooth from target gear to us var myClosestToothCom = myClosestTooth.CenterOfMassTransformed(); var targetClosestTooth = target.GetToothClosestToPoint(myClosestToothCom); // 3. Check if they overlap if (Direction == 1) { if (LineMath.PenetrationOfAIntoB(myClosestTooth.CounterClockwiseLine.OutlineTransformed, targetClosestTooth.ClockwiseLine.OutlineTransformed, out var point)) { var adjustment = (MathHelper.TwoPi / target.NumberOfTeeth) / 300.0f; target.Spin(adjustment * target.Direction); } else if (LineMath.PenetrationOfAIntoB(myClosestTooth.ClockwiseLine.OutlineTransformed, targetClosestTooth.CounterClockwiseLine.OutlineTransformed, out var point2)) { var adjustment = -(MathHelper.TwoPi / target.NumberOfTeeth) / 300.0f; target.Spin(adjustment * target.Direction); } } // TODO: code path for when we rotate in the other direction }
public void Update(GameTime gameTime, KeyboardState keyboard) { if (keyboard.IsKeyDown(Keys.Space)) { LineList[0].Spin(0.75); //LineList[1].Spin(-0.75); } else { //LineList[0].Spin(0); //LineList[1].Spin(0); } for (var i = 0; i < LineList.Count; i++) { LineList[i].Update(gameTime); } var shortest = LineMath.ShortestDistance(LineList[0].OutlineTransformed[0], LineList[0].OutlineTransformed[1], LineList[1].OutlineTransformed[0]); var shortestLine = LineMath.ShortestDistance(LineList[0].OutlineTransformed.ToArray(), LineList[1].OutlineTransformed.ToArray()); Indicators.Clear(); //Indicators.Add(new Shape(Device, Color.Green, PointToCross(LineList[1].OutlineTransformed[0], 0.2f), false)); //Indicators.Add(new Shape(Device, Color.Pink, PointToCross(LineList[0].OutlineTransformed[0], 0.2f), false)); //Indicators.Add(new Shape(Device, Color.Purple, PointToCross(LineList[0].OutlineTransformed[1], 0.2f), false)); //Indicators.Add(new Shape(Device, Color.Orange, PointToCross(shortest, 0.4f), false)); //Indicators.Add(new Shape(Device, Color.Yellow, PointToCross(shortestLine[0], 0.04f), false)); //Indicators.Add(new Shape(Device, Color.Yellow, PointToCross(shortestLine[1], 0.04f), false)); if (LineMath.Intersection(LineList[0].OutlineTransformed.ToArray(), LineList[1].OutlineTransformed.ToArray(), out var intersectionPoint)) { Indicators.Add(new Shape(Device, Color.Yellow, PointToCross(intersectionPoint, 0.1f), false)); // Proportional increase in angular velocity so that things get unstuck var d = LineMath.PenetrationOfAIntoB(LineList[0].OutlineTransformed.ToArray(), intersectionPoint); var dRatio = d / LineList[0].Length; LineList[1].Spin(-LineList[0].AngularVelocity * (1.0 + dRatio)); Console.WriteLine($"Penetration {d:F4}, L0: {LineList[0].AngularVelocity:F4}, L1: {LineList[1].AngularVelocity:F4}"); // TODO: what if things intersect and the velocity of line 0 is 0, or quickly decreases? } }
private double?Gear(Line a, Line b, float amount) { // TODO leading on leading should add speed, while trailing on trailing should reduce speed if (LineMath.Intersection(a.OutlineTransformed.ToArray(), b.OutlineTransformed.ToArray(), out var intersectionPoint)) { Indicators.Add(new Shape(Device, Color.Yellow, PointToCross(intersectionPoint, 0.1f), false)); // Proportional increase in angular velocity so that things get unstuck var d = LineMath.PenetrationOfAIntoB(a.OutlineTransformed.ToArray(), intersectionPoint); var dRatio = d / a.Length; var spin = -a.AngularVelocity * (1.0 + dRatio); return(amount); } return(null); }