1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
float timeToSimulate = 8f;
float timeStep = 0.0001f; // seconds
float gravity = 9.81f; // m/s/s
float muzzleVelocity; // m/s
float zeroingRange;// m
float targetRange; // m
float dragForce;
float mildots;
List<Vector2> positionList = new List<Vector2>();
List<Vector2> rotatedPositionList = new List<Vector2>();
public void InitializeValues()
{
targetRange = (float)numericUpDownRange.Value;
zeroingRange = (float)numericUpDownZero.Value;
muzzleVelocity = (float)numericUpDownBulletSpeed.Value;
dragForce = (float)numericUpDownDragForce.Value;
positionList.Clear();
rotatedPositionList.Clear();
}
public void DoMath()
{
//Initial simulation
var velocityVector = new Vector2(muzzleVelocity, 0);
var positionVector = new Vector2(0, 0);
positionList.Add(positionVector);
for (float t = 0; t <= timeToSimulate; t += timeStep)
{
var frictionAcceleration = dragForce * velocityVector.LengthSquared();
//compute total acceleration on the bullet
var accelerationVector = -Vector2.Normalize(velocityVector) * frictionAcceleration + new Vector2(0, -gravity);
//d = 1/2*a*t^2 + vi*t + d0;
positionVector += velocityVector * timeStep + 1 / 2 * accelerationVector * timeStep * timeStep;
positionList.Add(positionVector);
//vf = vi + at
velocityVector += accelerationVector * timeStep;
}
//Solve for zeroing position
Vector2 zeroingPosition = new Vector2(0, 0);
float smallestDistance = 100000;
for (int i = 0; i < positionList.Count; i++)
{
var thisPos = positionList[i];
var distanceFromOrigin = thisPos != Vector2.Zero ? thisPos.Length() : 0f;
var thisDistance = Math.Abs(distanceFromOrigin - zeroingRange);
if (thisDistance < smallestDistance)
{
zeroingPosition = thisPos;
smallestDistance = thisDistance;
}
}
//Get elevation angle for zeroing
var zeroingElevationAngle = zeroingPosition != Vector2.Zero ?Math.Atan(zeroingPosition.Y / -zeroingPosition.X) : 0.0;
var cos = (float)Math.Cos(zeroingElevationAngle);
var sin = (float)Math.Sin(zeroingElevationAngle);
//Create rotation matrix (matricies are transposed from math conventions)
var rotationMatrix = new Matrix3x2();
rotationMatrix.M11 = cos;
rotationMatrix.M12 = sin;
rotationMatrix.M21 = -sin;
rotationMatrix.M22 = cos;
//Rotate all of our values
for (int i = 0; i < positionList.Count; i++)
{
rotatedPositionList.Add(Vector2.TransformNormal(positionList[i], rotationMatrix));
}
//Solve for desired range
var targetPos = new Vector2(0, 0);
smallestDistance = 100000;
for (int i = 0; i < rotatedPositionList.Count; i++)
{
var thisPos = rotatedPositionList[i];
var thisDistance = Math.Abs(thisPos.X - targetRange);
if (thisDistance < smallestDistance)
{
targetPos = thisPos;
smallestDistance = thisDistance;
}
}
mildots = (float)Math.Atan(-targetPos.Y / targetPos.X) * 1000f;
string direction = mildots > 0 ? "above" : "below";
textBoxMildot.Text = $"Aim {Math.Abs(mildots):N2} mildots {direction} target";
} |
Partager