From 16f3f2ca3742896de4b4a0ccb69bea3b23c1238b Mon Sep 17 00:00:00 2001 From: ulteq Date: Sun, 13 Nov 2016 15:43:30 +0100 Subject: [PATCH] Optimized range card calculations * Removed dead code --- addons/rangecard/XEH_PREP.hpp | 2 +- .../functions/fnc_calculateRangeCard.sqf | 151 ++++++++++++++ .../functions/fnc_calculateSolution.sqf | 195 ------------------ .../functions/fnc_updateRangeCard.sqf | 4 +- 4 files changed, 154 insertions(+), 198 deletions(-) create mode 100644 addons/rangecard/functions/fnc_calculateRangeCard.sqf delete mode 100644 addons/rangecard/functions/fnc_calculateSolution.sqf diff --git a/addons/rangecard/XEH_PREP.hpp b/addons/rangecard/XEH_PREP.hpp index 6b13dcc45a..abbeaa2803 100644 --- a/addons/rangecard/XEH_PREP.hpp +++ b/addons/rangecard/XEH_PREP.hpp @@ -1,5 +1,5 @@ -PREP(calculateSolution); +PREP(calculateRangeCard); PREP(canCopy); PREP(canShow); PREP(canShowCopy); diff --git a/addons/rangecard/functions/fnc_calculateRangeCard.sqf b/addons/rangecard/functions/fnc_calculateRangeCard.sqf new file mode 100644 index 0000000000..7edd865ddc --- /dev/null +++ b/addons/rangecard/functions/fnc_calculateRangeCard.sqf @@ -0,0 +1,151 @@ +/* + * Author: Ruthberg + * Calculates the range card data + * + * Arguments: + * 0: Scope base angle + * 1: Bore height + * 2: air friction + * 3: muzzle velocity + * 4: temperature + * 5: barometric pressure + * 6: relative humidity + * 7: simulation steps + * 8: wind speed + * 9: target speed + * 10: target range + * 11: ballistic coefficient + * 12: drag model + * 13: atmosphere model + * 14: Range Card Slot + * 15: Use advanced ballistics config? + * + * Return Value: + * Nothing + * + * Example: + * call ace_rangecard_fnc_calculateRangeCard + * + * Public: No + */ +#include "script_component.hpp" +params [ + "_scopeBaseAngle", "_boreHeight", "_airFriction", "_muzzleVelocity", + "_temperature", "_barometricPressure", "_relativeHumidity", "_simSteps", + "_windSpeed", "_targetSpeed", "_targetRange", "_bc", "_dragModel", "_atmosphereModel", + "_rangeCardSlot", "_useABConfig" +]; + +GVAR(rangeCardDataMVs) set [_rangeCardSlot, format[" %1", round(_muzzleVelocity)]]; + +private ["_tx", "_tz", "_lastBulletPos", "_bulletPos", "_bulletVelocity", "_bulletAccel", "_bulletSpeed", "_gravity", "_deltaT", "_speedOfSound"]; +_tx = 0; +_tz = 0; +_lastBulletPos = [0, 0, 0]; +_bulletPos = [0, 0, 0]; +_bulletVelocity = [0, 0, 0]; +_bulletAccel = [0, 0, 0]; +_bulletSpeed = 0; +_gravity = [0, sin(_scopeBaseAngle) * -9.80665, cos(_scopeBaseAngle) * -9.80665]; +_deltaT = 1 / _simSteps; +_speedOfSound = 0; +if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { + _speedOfSound = _temperature call EFUNC(weather,calculateSpeedOfSound); +}; + +private ["_elevation", "_windage", "_lead", "_TOF", "_trueVelocity", "_trueSpeed"]; +_elevation = 0; +_windage = 0; +_lead = 0; +_TOF = 0; +_trueVelocity = [0, 0, 0]; +_trueSpeed = 0; + +private ["_n", "_range"]; +_n = 0; +_range = 0; + +if (_useABConfig) then { + _bc = parseNumber(("ace_advanced_ballistics" callExtension format["atmosphericCorrection:%1:%2:%3:%4:%5", _bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel])); +}; + +private ["_airFrictionCoef", "_airDensity"]; +_airFrictionCoef = 1; +if (!_useABConfig && (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) then { + _airDensity = [_temperature, _barometricPressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity); + _airFrictionCoef = _airDensity / 1.22498; +}; + +private ["_speedTotal", "_stepsTotal", "_speedAverage"]; +_speedTotal = 0; +_stepsTotal = 0; +_speedAverage = 0; + +_bulletPos set [0, 0]; +_bulletPos set [1, 0]; +_bulletPos set [2, -(_boreHeight / 100)]; + +_bulletVelocity set [0, 0]; +_bulletVelocity set [1, Cos(_scopeBaseAngle) * _muzzleVelocity]; +_bulletVelocity set [2, Sin(_scopeBaseAngle) * _muzzleVelocity]; + +while {_TOF < 6 && (_bulletPos select 1) < _targetRange} do { + _bulletSpeed = vectorMagnitude _bulletVelocity; + + _speedTotal = _speedTotal + _bulletSpeed; + _stepsTotal = _stepsTotal + 1; + _speedAverage = (_speedTotal / _stepsTotal); + + if (_speedAverage > 450 && _bulletSpeed < _speedOfSound) exitWith {}; + if (atan((_bulletPos select 2) / (abs(_bulletPos select 1) + 1)) < -2.254) exitWith {}; + + _trueVelocity = _bulletVelocity vectorDiff [-_windSpeed, 0, 0]; + _trueSpeed = vectorMagnitude _trueVelocity; + + if (_useABConfig) then { + private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed])); + _bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag); + } else { + _bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction * _airFrictionCoef); + }; + + _bulletAccel = _bulletAccel vectorAdd _gravity; + + _lastBulletPos = _bulletPos; + _bulletPos = _bulletPos vectorAdd (_bulletVelocity vectorMultiply (_deltaT * 0.5)); + _bulletVelocity = _bulletVelocity vectorAdd (_bulletAccel vectorMultiply _deltaT); + _bulletPos = _bulletPos vectorAdd (_bulletVelocity vectorMultiply (_deltaT * 0.5)); + + _TOF = _TOF + _deltaT; + + _range = GVAR(rangeCardStartRange) + _n * GVAR(rangeCardIncrement); + if ((_bulletPos select 1) >= _range && _range <= GVAR(rangeCardEndRange)) then { + if (_range != 0) then { + _tx = (_lastBulletPos select 0) + (_range - (_lastBulletPos select 1)) * ((_bulletPos select 0) - (_lastBulletPos select 0)) / ((_bulletPos select 1) - (_lastBulletPos select 1)); + _tz = (_lastBulletPos select 2) + (_range - (_lastBulletPos select 1)) * ((_bulletPos select 2) - (_lastBulletPos select 2)) / ((_bulletPos select 1) - (_lastBulletPos select 1)); + _elevation = - atan(_tz / _range); + _windage = - atan(_tx / _range); + _lead = (_targetSpeed * _TOF) / (Tan(3.38 / 60) * _range); + }; + private ["_elevationString", "_windageString", "_leadString"]; + _elevationString = Str(round(-_elevation * 60 / 3.38 * 10) / 10); + if (_elevationString == "0") then { + _elevationString = "-0.0"; + }; + if (_elevationString find "." == -1) then { + _elevationString = _elevationString + ".0"; + }; + _windageString = Str(round(_windage * 60 / 3.38 * 10) / 10); + if (_windageString find "." == -1) then { + _windageString = _windageString + ".0"; + }; + _leadString = Str(round(_lead * 10) / 10); + if (_leadString find "." == -1) then { + _leadString = _leadString + ".0"; + }; + (GVAR(rangeCardDataElevation) select _rangeCardSlot) set [_n, _elevationString]; + (GVAR(rangeCardDataWindage) select _rangeCardSlot) set [_n, _windageString]; + (GVAR(rangeCardDataLead) select _rangeCardSlot) set [_n, _leadString]; + _n = _n + 1; + }; +}; diff --git a/addons/rangecard/functions/fnc_calculateSolution.sqf b/addons/rangecard/functions/fnc_calculateSolution.sqf deleted file mode 100644 index 1e2cb38ba7..0000000000 --- a/addons/rangecard/functions/fnc_calculateSolution.sqf +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Author: Ruthberg - * Calculates the range card data - * - * Arguments: - * 0: Scope base angle - * 1: Bullet mass - * 2: Bore height - * 3: air friction - * 4: muzzle velocity - * 5: temperature - * 6: barometric pressure - * 7: relative humidity - * 8: simulation steps - * 9: wind speed - * 10: wind direction - * 11: inclination angle - * 12: target speed - * 13: target range - * 14: ballistic coefficient - * 15: drag model - * 16: atmosphere model - * 17: Store range card data? - * 18: Stability factor - * 19: Twist Direction - * 20: Latitude - * 21: Direction of Fire - * 22: Range Card Slot - * 23: Use advanced ballistics config? - * - * Return Value: - * 0: Elevation (MOA) - * 1: Windage (MOA) - * 2: Lead (MOA) - * 3: Time of fligth (SECONDS) - * 4: Remaining velocity (m/s) - * 5: Remaining kinetic energy (ft·lb) - * 6: Vertical coriolis drift (MOA) - * 7: Horizontal coriolis drift (MOA) - * 8: Spin drift (MOA) - * - * Example: - * call ace_rangecard_fnc_calculateSolution - * - * Public: No - */ -#include "script_component.hpp" -params [ - "_scopeBaseAngle", "_bulletMass", "_boreHeight", "_airFriction", "_muzzleVelocity", - "_temperature", "_barometricPressure", "_relativeHumidity", "_simSteps", "_windSpeed", - "_windDirection", "_inclinationAngle", "_targetSpeed", "_targetRange", "_bc", "_dragModel", - "_atmosphereModel", "_storeRangeCardData", "_stabilityFactor", "_twistDirection", "_latitude", - "_directionOfFire", "_rangeCardSlot", "_useABConfig" -]; -_windSpeed params ["_windSpeed1", "_windSpeed2"]; - -if (_storeRangeCardData) then { - GVAR(rangeCardDataMVs) set [_rangeCardSlot, format[" %1", round(_muzzleVelocity)]]; -}; - -private ["_bulletPos", "_bulletVelocity", "_bulletAccel", "_bulletSpeed", "_gravity", "_deltaT", "_speedOfSound"]; -_bulletPos = [0, 0, 0]; -_bulletVelocity = [0, 0, 0]; -_bulletAccel = [0, 0, 0]; -_bulletSpeed = 0; -_gravity = [0, sin(_scopeBaseAngle + _inclinationAngle) * -9.80665, cos(_scopeBaseAngle + _inclinationAngle) * -9.80665]; -_deltaT = 1 / _simSteps; -_speedOfSound = 0; -if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { - _speedOfSound = _temperature call EFUNC(weather,calculateSpeedOfSound); -}; - -private ["_elevation", "_windage1", "_windage2", "_lead", "_TOF", "_trueVelocity", "_trueSpeed", "_kineticEnergy", "_verticalCoriolis", "_verticalDeflection", "_horizontalCoriolis", "_horizontalDeflection", "_spinDrift", "_spinDeflection"]; -_elevation = 0; -_windage1 = 0; -_windage2 = 0; -_lead = 0; -_TOF = 0; -_trueVelocity = [0, 0, 0]; -_trueSpeed = 0; -_verticalCoriolis = 0; -_verticalDeflection = 0; -_horizontalCoriolis = 0; -_horizontalDeflection = 0; -_spinDrift = 0; -_spinDeflection = 0; - -private ["_n", "_range"]; -_n = 0; -_range = 0; - -private ["_wind1", "_wind2", "_windDrift"]; -_wind1 = [cos(270 - _windDirection * 30) * _windSpeed1, sin(270 - _windDirection * 30) * _windSpeed1, 0]; -_wind2 = [cos(270 - _windDirection * 30) * _windSpeed2, sin(270 - _windDirection * 30) * _windSpeed2, 0]; -_windDrift = 0; -if (_useABConfig) then { - _bc = parseNumber(("ace_advanced_ballistics" callExtension format["atmosphericCorrection:%1:%2:%3:%4:%5", _bc, _temperature, _barometricPressure, _relativeHumidity, _atmosphereModel])); -}; - -private ["_airFrictionCoef", "_airDensity"]; -_airFrictionCoef = 1; -if (!_useABConfig && (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) then { - _airDensity = [_temperature, _barometricPressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity); - _airFrictionCoef = _airDensity / 1.22498; -}; - -private ["_speedTotal", "_stepsTotal", "_speedAverage"]; -_speedTotal = 0; -_stepsTotal = 0; -_speedAverage = 0; - -_bulletPos set [0, 0]; -_bulletPos set [1, 0]; -_bulletPos set [2, -(_boreHeight / 100)]; - -_bulletVelocity set [0, 0]; -_bulletVelocity set [1, Cos(_scopeBaseAngle) * _muzzleVelocity]; -_bulletVelocity set [2, Sin(_scopeBaseAngle) * _muzzleVelocity]; - -while {_TOF < 6 && (_bulletPos select 1) < _targetRange} do { - _bulletSpeed = vectorMagnitude _bulletVelocity; - - _speedTotal = _speedTotal + _bulletSpeed; - _stepsTotal = _stepsTotal + 1; - _speedAverage = (_speedTotal / _stepsTotal); - - if (_speedAverage > 450 && _bulletSpeed < _speedOfSound) exitWith {}; - if (atan((_bulletPos select 2) / (abs(_bulletPos select 1) + 1)) < -2.254) exitWith {}; - - _trueVelocity = _bulletVelocity vectorDiff _wind1; - _trueSpeed = vectorMagnitude _trueVelocity; - - if (_useABConfig) then { - private _drag = parseNumber(("ace_advanced_ballistics" callExtension format["retard:%1:%2:%3", _dragModel, _bc, _trueSpeed])); - _bulletAccel = (vectorNormalized _trueVelocity) vectorMultiply (-1 * _drag); - } else { - _bulletAccel = _trueVelocity vectorMultiply (_trueSpeed * _airFriction * _airFrictionCoef); - }; - - _bulletAccel = _bulletAccel vectorAdd _gravity; - - _bulletVelocity = _bulletVelocity vectorAdd (_bulletAccel vectorMultiply _deltaT); - _bulletPos = _bulletPos vectorAdd (_bulletVelocity vectorMultiply _deltaT); - - _TOF = _TOF + _deltaT; - - if (_storeRangeCardData) then { - _range = GVAR(rangeCardStartRange) + _n * GVAR(rangeCardIncrement); - if ((_bulletPos select 1) >= _range && _range <= GVAR(rangeCardEndRange)) then { - if ((_bulletPos select 1) > 0) then { - _elevation = - atan((_bulletPos select 2) / (_bulletPos select 1)); - _windage1 = - atan((_bulletPos select 0) / (_bulletPos select 1)); - }; - if (_range != 0) then { - _lead = (_targetSpeed * _TOF) / (Tan(3.38 / 60) * _range); - }; - private ["_elevationString", "_windageString", "_leadString"]; - _elevationString = Str(round(-_elevation * 60 / 3.38 * 10) / 10); - if (_elevationString == "0") then { - _elevationString = "-0.0"; - }; - if (_elevationString find "." == -1) then { - _elevationString = _elevationString + ".0"; - }; - _windageString = Str(round(_windage1 * 60 / 3.38 * 10) / 10); - if (_windageString find "." == -1) then { - _windageString = _windageString + ".0"; - }; - _leadString = Str(round(_lead * 10) / 10); - if (_leadString find "." == -1) then { - _leadString = _leadString + ".0"; - }; - (GVAR(rangeCardDataElevation) select _rangeCardSlot) set [_n, _elevationString]; - (GVAR(rangeCardDataWindage) select _rangeCardSlot) set [_n, _windageString]; - (GVAR(rangeCardDataLead) select _rangeCardSlot) set [_n, _leadString]; - _n = _n + 1; - }; - }; -}; - -if ((_bulletPos select 1) > 0) then { - _elevation = - atan((_bulletPos select 2) / (_bulletPos select 1)); - _windage1 = - atan((_bulletPos select 0) / (_bulletPos select 1)); - _windDrift = (_wind2 select 0) * (_TOF - _targetRange / _muzzleVelocity); - _windage2 = - atan(_windDrift / (_bulletPos select 1)); -}; - -if (_targetRange != 0) then { - _lead = (_targetSpeed * _TOF) / (Tan(3.38 / 60) * _targetRange); -}; - -_kineticEnergy = 0.5 * (_bulletMass / 1000 * (_bulletSpeed ^ 2)); -_kineticEnergy = _kineticEnergy * 0.737562149; - -[_elevation * 60, [_windage1 * 60, _windage2 * 60], _lead, _TOF, _bulletSpeed, _kineticEnergy, _verticalCoriolis * 60, _horizontalCoriolis * 60, _spinDrift * 60] diff --git a/addons/rangecard/functions/fnc_updateRangeCard.sqf b/addons/rangecard/functions/fnc_updateRangeCard.sqf index 633df5e4c6..41234376fc 100644 --- a/addons/rangecard/functions/fnc_updateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_updateRangeCard.sqf @@ -170,10 +170,10 @@ if (isNil {_cacheEntry}) then { private _mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift); private _mv = _muzzleVelocity + _mvShift; - [_scopeBaseAngle,0,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),1000,[4,0],3,0,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,true,1.5,1,46,23,_forEachIndex,_useABConfig] call FUNC(calculateSolution); + [_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),100,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_forEachIndex,_useABConfig] call FUNC(calculateRangeCard); } forEach [-15, -5, 5, 10, 15, 20, 25, 30, 35]; } else { - [_scopeBaseAngle,0,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),1000,[4,0],3,0,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,true,1.5,1,46,23,4,_useABConfig] call FUNC(calculateSolution); + [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),100,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,4,_useABConfig] call FUNC(calculateRangeCard); }; for "_i" from 0 to 9 do {