diff --git a/ace_advanced_ballistics.dll b/ace_advanced_ballistics.dll index f0290f0505..e2e8fe09d8 100644 Binary files a/ace_advanced_ballistics.dll and b/ace_advanced_ballistics.dll differ diff --git a/ace_advanced_ballistics_x64.dll b/ace_advanced_ballistics_x64.dll index 8c712f8cf3..d65f55f4bd 100644 Binary files a/ace_advanced_ballistics_x64.dll and b/ace_advanced_ballistics_x64.dll differ diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index 806f40c624..81a167696f 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -112,7 +112,9 @@ if (_caliber > 0 && _bulletLength > 0 && _bulletMass > 0 && _barrelTwist > 0) th GVAR(currentbulletID) = (GVAR(currentbulletID) + 1) % 10000; -"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17", GVAR(currentbulletID), _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _transonicStabilityCoef, getPosASL _projectile, _bulletVelocity, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6]; +private _ammoCount = _unit ammo _muzzle; + +"ace_advanced_ballistics" callExtension format["new:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17:%18", GVAR(currentbulletID), _ammoCount, _airFriction, _ballisticCoefficients, _velocityBoundaries, _atmosphereModel, _dragModel, _stabilityFactor, _twistDirection, _transonicStabilityCoef, getPosASL _projectile, _bulletVelocity, EGVAR(common,mapLatitude), EGVAR(weather,currentTemperature), EGVAR(common,mapAltitude), EGVAR(weather,currentHumidity), EGVAR(weather,currentOvercast), CBA_missionTime toFixed 6]; GVAR(allBullets) pushBack [_projectile, _caliber, _bulletTraceVisible, GVAR(currentbulletID)]; diff --git a/addons/advanced_ballistics/script_component.hpp b/addons/advanced_ballistics/script_component.hpp index 48344f8ca3..dafb4150e1 100644 --- a/addons/advanced_ballistics/script_component.hpp +++ b/addons/advanced_ballistics/script_component.hpp @@ -16,7 +16,6 @@ #include "\z\ace\addons\main\script_macros.hpp" -#define GRAVITY 9.80665 #define ABSOLUTE_ZERO_IN_CELSIUS -273.15 #define KELVIN(t) (t - ABSOLUTE_ZERO_IN_CELSIUS) #define CELSIUS(t) (t + ABSOLUTE_ZERO_IN_CELSIUS) diff --git a/addons/atragmx/functions/fnc_calculate_solution.sqf b/addons/atragmx/functions/fnc_calculate_solution.sqf index a37156de28..a7928d1ef0 100644 --- a/addons/atragmx/functions/fnc_calculate_solution.sqf +++ b/addons/atragmx/functions/fnc_calculate_solution.sqf @@ -58,7 +58,7 @@ private _bulletPos = [0, 0, 0]; private _bulletVelocity = [0, 0, 0]; private _bulletAccel = [0, 0, 0]; private _bulletSpeed = 0; -private _gravity = [0, sin(_scopeBaseAngle + _inclinationAngle) * -9.80665, cos(_scopeBaseAngle + _inclinationAngle) * -9.80665]; +private _gravity = [0, sin(_scopeBaseAngle + _inclinationAngle) * -GRAVITY, cos(_scopeBaseAngle + _inclinationAngle) * -GRAVITY]; private _deltaT = 1 / _simSteps; private _elevation = 0; @@ -95,7 +95,7 @@ if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) t private _eoetvoesMultiplier = 0; if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { - _eoetvoesMultiplier = 2 * (0.0000729 * _muzzleVelocity / -9.80665) * cos(_latitude) * sin(_directionOfFire); + _eoetvoesMultiplier = 2 * (0.0000729 * _muzzleVelocity / -GRAVITY) * cos(_latitude) * sin(_directionOfFire); }; _bulletPos set [0, 0]; diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index 06b9e3ab99..145134d388 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -109,6 +109,8 @@ #define TRACE_10(MESSAGE,A,B,C,D,E,F,G,H,I,J) /* disabled */ #endif +#define GRAVITY 9.8066 + // Angular unit conversion #define MRAD_TO_MOA(d) ((d) * 3.43774677) // Conversion factor: 54 / (5 * PI) #define MOA_TO_MRAD(d) ((d) * 0.29088821) // Conversion factor: (5 * PI) / 54 diff --git a/addons/rangecard/functions/fnc_calculateRangeCard.sqf b/addons/rangecard/functions/fnc_calculateRangeCard.sqf index 694d234caf..5bb12e220a 100644 --- a/addons/rangecard/functions/fnc_calculateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_calculateRangeCard.sqf @@ -46,7 +46,7 @@ private _bulletPos = [0, 0, 0]; private _bulletVelocity = [0, 0, 0]; private _bulletAccel = [0, 0, 0]; private _bulletSpeed = 0; -private _gravity = [0, sin(_scopeBaseAngle) * -9.80665, cos(_scopeBaseAngle) * -9.80665]; +private _gravity = [0, sin(_scopeBaseAngle) * -GRAVITY, cos(_scopeBaseAngle) * -GRAVITY]; private _deltaT = 1 / _simSteps; private _speedOfSound = 0; if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { diff --git a/addons/rangecard/functions/script_component.hpp b/addons/rangecard/functions/script_component.hpp index fdc4a3d486..d4a493206b 100644 --- a/addons/rangecard/functions/script_component.hpp +++ b/addons/rangecard/functions/script_component.hpp @@ -1 +1 @@ -#include "\z\ace\addons\rangecard\script_component.hpp" \ No newline at end of file +#include "\z\ace\addons\rangecard\script_component.hpp" diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index 4f32ddbb1c..79382e8580 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -8,8 +8,10 @@ #include #include -#define DELTA_T 0.02f -#define GRAVITY 9.80665f +#include "vector.hpp" + +#define DELTA_T 0.005 +#define GRAVITY 9.8066f #define DEGREES(X) (X * 180 / M_PI) #define ABSOLUTE_ZERO_IN_CELSIUS -273.15f #define KELVIN(t) (t - ABSOLUTE_ZERO_IN_CELSIUS) @@ -39,8 +41,8 @@ struct Bullet { double stabilityFactor; double twistDirection; double transonicStabilityCoef; - std::vector bulletVelocity; - std::vector origin; + ace::vector3 bulletVelocityPreviousFrame; + ace::vector3 origin; double latitude; double temperature; double altitude; @@ -48,7 +50,6 @@ struct Bullet { double overcast; double startTime; double lastFrame; - double bcDegradation; unsigned randSeed; std::default_random_engine randGenerator; }; @@ -138,7 +139,7 @@ double calculateRetard(int DragFunction, double DragCoefficient, double Velocity int idx = std::max(0, std::min(DragFunction, 9)); double m = Velocity / Mach; - for (int i = 0; i < machNumbers[idx].size(); i++) { + for (int i = 0; i < (int)machNumbers[idx].size(); i++) { if (machNumbers[idx][i] >= m) { int previousIdx = std::max(0, i - 1); double previousDragCoefficient = dragCoefficients[idx][previousIdx]; @@ -153,6 +154,7 @@ double calculateRetard(int DragFunction, double DragCoefficient, double Velocity double calculateVanillaZeroAngle(double zeroRange, double muzzleVelocity, double airFriction, double boreHeight) { double zeroAngle = 0.0f; + double deltaT = 1.0 / std::max(100.0, zeroRange); for (int i = 0; i < 10; i++) { double lx = 0.0f; @@ -181,14 +183,14 @@ double calculateVanillaZeroAngle(double zeroRange, double muzzleVelocity, double ax += gx; ay += gy; - px += vx * DELTA_T * 0.5; - py += vy * DELTA_T * 0.5; - vx += ax * DELTA_T; - vy += ay * DELTA_T; - px += vx * DELTA_T * 0.5; - py += vy * DELTA_T * 0.5; + px += vx * deltaT * 0.5; + py += vy * deltaT * 0.5; + vx += ax * deltaT; + vy += ay * deltaT; + px += vx * deltaT * 0.5; + py += vy * deltaT * 0.5; - tof += DELTA_T; + tof += deltaT; } double y = ly + (zeroRange - lx) * (py - ly) / (px - lx); @@ -205,6 +207,7 @@ double calculateVanillaZeroAngle(double zeroRange, double muzzleVelocity, double double calculateZeroAngle(double zeroRange, double muzzleVelocity, double boreHeight, double temperature, double pressure, double humidity, double ballisticCoefficient, int dragModel, char* atmosphereModel) { double zeroAngle = 0.0f; + double deltaT = 1.0 / std::max(100.0, zeroRange); ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, humidity, atmosphereModel); @@ -236,14 +239,14 @@ double calculateZeroAngle(double zeroRange, double muzzleVelocity, double boreHe ax += gx; ay += gy; - px += vx * DELTA_T * 0.5; - py += vy * DELTA_T * 0.5; - vx += ax * DELTA_T; - vy += ay * DELTA_T; - px += vx * DELTA_T * 0.5; - py += vy * DELTA_T * 0.5; + px += vx * deltaT * 0.5; + py += vy * deltaT * 0.5; + vx += ax * deltaT; + vy += ay * deltaT; + px += vx * deltaT * 0.5; + py += vy * deltaT * 0.5; - tof += DELTA_T; + tof += deltaT; } double y = ly + (zeroRange - lx) * (py - ly) / (px - lx); @@ -322,6 +325,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) EXTENSION_RETURN(); } else if (!strcmp(mode, "new")) { unsigned int index = 0; + unsigned int ammoCount = 0; double airFriction = 0.0; char* ballisticCoefficientArray; char* ballisticCoefficient; @@ -348,6 +352,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) double tickTime = 0.0; index = strtol(strtok_s(NULL, ":", &next_token), NULL, 10); + ammoCount = strtol(strtok_s(NULL, ":", &next_token), NULL, 10); airFriction = strtod(strtok_s(NULL, ":", &next_token), NULL); ballisticCoefficientArray = strtok_s(NULL, ":", &next_token); ballisticCoefficientArray++; @@ -406,8 +411,8 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].stabilityFactor = stabilityFactor; bulletDatabase[index].twistDirection = twistDirection; bulletDatabase[index].transonicStabilityCoef = transonicStabilityCoef; - bulletDatabase[index].bulletVelocity = bulletVelocity; - bulletDatabase[index].origin = origin; + bulletDatabase[index].bulletVelocityPreviousFrame = { bulletVelocity[0], bulletVelocity[1], bulletVelocity[2] }; + bulletDatabase[index].origin = { origin[0], origin[1], origin[2] }; bulletDatabase[index].latitude = latitude / 180 * M_PI; bulletDatabase[index].temperature = temperature; bulletDatabase[index].altitude = altitude; @@ -415,8 +420,12 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].overcast = overcast; bulletDatabase[index].startTime = tickTime; bulletDatabase[index].lastFrame = tickTime; - bulletDatabase[index].bcDegradation = 1.0; - bulletDatabase[index].randSeed = 0; + if (transonicStabilityCoef < 1) { + unsigned int k1 = (unsigned)round(tickTime / 2); + unsigned int k2 = ammoCount; + bulletDatabase[index].randSeed = (unsigned int)(0.5 * (k1 + k2) * (k1 + k2 + 1) + k2); + bulletDatabase[index].randGenerator.seed(bulletDatabase[index].randSeed); + } strncpy_s(output, outputSize, "", _TRUNCATE); EXTENSION_RETURN(); @@ -454,164 +463,139 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) heightAGL = strtod(strtok_s(NULL, ":", &next_token), NULL); tickTime = strtod(strtok_s(NULL, ":", &next_token), NULL); - if (bulletDatabase[index].randSeed == 0) { - int angle = (int)round(atan2(velocity[0], velocity[1]) * 360 / M_PI); - bulletDatabase[index].randSeed = (unsigned)(720 + angle) % 720; - bulletDatabase[index].randSeed *= 3; - bulletDatabase[index].randSeed += (unsigned)round(abs(velocity[2]) / 2); - bulletDatabase[index].randSeed *= 3; - bulletDatabase[index].randSeed += (unsigned)round(abs(bulletDatabase[index].origin[0] / 2)); - bulletDatabase[index].randSeed *= 3; - bulletDatabase[index].randSeed += (unsigned)round(abs(bulletDatabase[index].origin[1] / 2)); - bulletDatabase[index].randSeed *= 3; - bulletDatabase[index].randSeed += (unsigned)abs(bulletDatabase[index].temperature) * 10; - bulletDatabase[index].randSeed *= 3; - bulletDatabase[index].randSeed += (unsigned)abs(bulletDatabase[index].humidity) * 10; - bulletDatabase[index].randGenerator.seed(bulletDatabase[index].randSeed); - } - + ace::vector3 bulletVelocityCurrentFrame = { velocity[0], velocity[1], velocity[2] }; + ace::vector3 bulletPosition = { position[0], position[1], position[2] }; + ace::vector3 windVelocity = { wind[0], wind[1], wind[2] }; + ace::vector3 gravityAccel = { 0, 0, -GRAVITY }; double ballisticCoefficient = 1.0; double dragRef = 0.0; double drag = 0.0; - double accelRef[3] = { 0.0, 0.0, 0.0 }; - double accel[3] = { 0.0, 0.0, 0.0 }; double TOF = tickTime - bulletDatabase[index].startTime; double deltaT = tickTime - bulletDatabase[index].lastFrame; - double trueVelocity[3] = { 0.0, 0.0, 0.0 }; - double trueSpeed = 0.0; - double temperature = bulletDatabase[index].temperature - 0.0065 * position[2]; - double pressure = (1013.25 - 10 * bulletDatabase[index].overcast) * pow(1 - (0.0065 * (bulletDatabase[index].altitude + position[2])) / (KELVIN(temperature) + 0.0065 * bulletDatabase[index].altitude), 5.255754495); - double windSpeed = 0.0; - double windAttenuation = 1.0; - double velocityOffset[3] = { 0.0, 0.0, 0.0 }; - double bulletSpeed = sqrt(pow(bulletDatabase[index].bulletVelocity[0], 2) + pow(bulletDatabase[index].bulletVelocity[1], 2) + pow(bulletDatabase[index].bulletVelocity[2], 2)); + ace::vector3 trueVelocity; + double temperature = bulletDatabase[index].temperature - 0.0065 * bulletPosition.z(); + double pressure = (1013.25 - 10 * bulletDatabase[index].overcast) * pow(1 - (0.0065 * (bulletDatabase[index].altitude + bulletPosition.z())) / (KELVIN(temperature) + 0.0065 * bulletDatabase[index].altitude), 5.255754495); + ace::vector3 velocityOffset; bulletDatabase[index].lastFrame = tickTime; - windSpeed = sqrt(pow(wind[0], 2) + pow(wind[1], 2) + pow(wind[2], 2)); - if (windSpeed > 0.1) { - double windSourceTerrain[3]; + if (windVelocity.magnitude() > 0.1) { + double windAttenuation = 1.0; + ace::vector3 windSourceTerrain; - windSourceTerrain[0] = position[0] - wind[0] / windSpeed * 100; - windSourceTerrain[1] = position[1] - wind[1] / windSpeed * 100; - windSourceTerrain[2] = position[2] - wind[2] / windSpeed * 100; + windSourceTerrain = bulletPosition - windVelocity.normalize() * 100; - int gridX = (int)floor(windSourceTerrain[0] / 50); - int gridY = (int)floor(windSourceTerrain[1] / 50); + int gridX = (int)floor(windSourceTerrain.x() / 50); + int gridY = (int)floor(windSourceTerrain.y() / 50); int gridCell = gridX * map->mapGrids + gridY; if (gridCell >= 0 && (std::size_t)gridCell < map->gridHeights.size() && (std::size_t)gridCell < map->gridBuildingNums.size()) { double gridHeight = map->gridHeights[gridCell]; - if (gridHeight > position[2]) { - double angle = atan((gridHeight - position[2]) / 100); + if (gridHeight > bulletPosition.z()) { + double angle = atan((gridHeight - bulletPosition.z()) / 100); windAttenuation *= pow(abs(cos(angle)), 2); } } - } - - if (windSpeed > 0.1) { - double windSourceObstacles[3]; - - windSourceObstacles[0] = position[0] - wind[0] / windSpeed * 25; - windSourceObstacles[1] = position[1] - wind[1] / windSpeed * 25; - windSourceObstacles[2] = position[2] - wind[2] / windSpeed * 25; if (heightAGL > 0 && heightAGL < 20) { - double roughnessLength = calculateRoughnessLength(windSourceObstacles[0], windSourceObstacles[1]); + ace::vector3 windSourceObstacles; + + windSourceObstacles = bulletPosition - windVelocity.normalize() * 25; + + double roughnessLength = calculateRoughnessLength(windSourceObstacles.x(), windSourceObstacles.y()); windAttenuation *= abs(log(heightAGL / roughnessLength) / log(20 / roughnessLength)); } + + windVelocity = windVelocity * windAttenuation; } - if (windAttenuation < 1) { - wind[0] *= windAttenuation; - wind[1] *= windAttenuation; - wind[2] *= windAttenuation; - windSpeed = sqrt(pow(wind[0], 2) + pow(wind[1], 2) + pow(wind[2], 2)); + ace::vector3 bulletVelocity = bulletDatabase[index].bulletVelocityPreviousFrame; + double time = 0.0; + + while (time < deltaT) { + double dt = std::min(deltaT - time, DELTA_T); + + dragRef = -bulletDatabase[index].airFriction * bulletVelocity.magnitude_squared(); + + ace::vector3 accelRef = bulletVelocity.normalize() * dragRef; + + velocityOffset += accelRef * dt; + bulletVelocity -= accelRef * dt; + bulletVelocity += gravityAccel * dt; + + time += dt; } - trueVelocity[0] = bulletDatabase[index].bulletVelocity[0] - wind[0]; - trueVelocity[1] = bulletDatabase[index].bulletVelocity[1] - wind[1]; - trueVelocity[2] = bulletDatabase[index].bulletVelocity[2] - wind[2]; - trueSpeed = sqrt(pow(trueVelocity[0], 2) + pow(trueVelocity[1], 2) + pow(trueVelocity[2], 2)); + bulletVelocity = bulletDatabase[index].bulletVelocityPreviousFrame; + time = 0.0; + TOF -= deltaT; - if (bulletDatabase[index].transonicStabilityCoef < 1.0f && trueSpeed - 60 < SPEED_OF_SOUND(temperature) && trueSpeed > SPEED_OF_SOUND(temperature)) { - std::uniform_real_distribution distribution(-10.0, 10.0); - double coef = 1.0f - bulletDatabase[index].transonicStabilityCoef; + while (time < deltaT) { + double dt = std::min(deltaT - time, DELTA_T * 2); - trueVelocity[0] += distribution(bulletDatabase[index].randGenerator) * coef; - trueVelocity[1] += distribution(bulletDatabase[index].randGenerator) * coef; - trueVelocity[2] += distribution(bulletDatabase[index].randGenerator) * coef; - double speed = sqrt(pow(trueVelocity[0], 2) + pow(trueVelocity[1], 2) + pow(trueVelocity[2], 2)); + trueVelocity = bulletVelocity - windVelocity; - trueVelocity[0] *= trueSpeed / speed; - trueVelocity[1] *= trueSpeed / speed; - trueVelocity[2] *= trueSpeed / speed; + if (bulletDatabase[index].transonicStabilityCoef < 1.0f && trueVelocity.magnitude() < 1.2 * SPEED_OF_SOUND(temperature) && trueVelocity.magnitude() > SPEED_OF_SOUND(temperature)) { + std::uniform_real_distribution distribution(-10.0, 10.0); + ace::vector3 offset(distribution(bulletDatabase[index].randGenerator), distribution(bulletDatabase[index].randGenerator), distribution(bulletDatabase[index].randGenerator)); + double coef = 1.0f - bulletDatabase[index].transonicStabilityCoef; - bulletDatabase[index].bcDegradation *= pow(0.993, coef); - }; + double trueSpeed = trueVelocity.magnitude(); + trueVelocity += offset * coef; + trueVelocity = trueVelocity.normalize() * trueSpeed; + }; - dragRef = -bulletDatabase[index].airFriction * bulletSpeed * bulletSpeed; - - accelRef[0] = (bulletDatabase[index].bulletVelocity[0] / bulletSpeed) * dragRef; - accelRef[1] = (bulletDatabase[index].bulletVelocity[1] / bulletSpeed) * dragRef; - accelRef[2] = (bulletDatabase[index].bulletVelocity[2] / bulletSpeed) * dragRef; - - velocityOffset[0] += accelRef[0] * deltaT; - velocityOffset[1] += accelRef[1] * deltaT; - velocityOffset[2] += accelRef[2] * deltaT; - - if (bulletDatabase[index].ballisticCoefficients.size() == bulletDatabase[index].velocityBoundaries.size() + 1) { - ballisticCoefficient = bulletDatabase[index].ballisticCoefficients[0]; - for (int i = (int)bulletDatabase[index].velocityBoundaries.size() - 1; i >= 0; i = i - 1) { - if (trueSpeed < bulletDatabase[index].velocityBoundaries[i]) { - ballisticCoefficient = bulletDatabase[index].ballisticCoefficients[i + 1]; - break; + if (bulletDatabase[index].ballisticCoefficients.size() == bulletDatabase[index].velocityBoundaries.size() + 1) { + ballisticCoefficient = bulletDatabase[index].ballisticCoefficients[0]; + for (int i = (int)bulletDatabase[index].velocityBoundaries.size() - 1; i >= 0; i = i - 1) { + if (trueVelocity.magnitude() < bulletDatabase[index].velocityBoundaries[i]) { + ballisticCoefficient = bulletDatabase[index].ballisticCoefficients[i + 1]; + break; + } } + + ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, bulletDatabase[index].humidity, bulletDatabase[index].atmosphereModel); + + drag = calculateRetard(bulletDatabase[index].dragModel, ballisticCoefficient, trueVelocity.magnitude(), SPEED_OF_SOUND(temperature)); + } else { + double airDensity = calculateAirDensity(temperature, pressure, bulletDatabase[index].humidity); + double airFriction = bulletDatabase[index].airFriction * airDensity / STD_AIR_DENSITY_ICAO; + + drag = -airFriction * trueVelocity.magnitude_squared(); } - ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, bulletDatabase[index].humidity, bulletDatabase[index].atmosphereModel); - ballisticCoefficient *= bulletDatabase[index].bcDegradation; + ace::vector3 accel = trueVelocity.normalize() * drag; - drag = calculateRetard(bulletDatabase[index].dragModel, ballisticCoefficient, trueSpeed, SPEED_OF_SOUND(temperature)); - } else { - double airDensity = calculateAirDensity(temperature, pressure, bulletDatabase[index].humidity); - double airFriction = bulletDatabase[index].airFriction * airDensity / STD_AIR_DENSITY_ICAO; + velocityOffset -= accel * dt; + bulletVelocity -= accel * dt; - drag = -airFriction * trueSpeed * trueSpeed; + if (TOF > 0) { + double bulletDir = atan2(bulletVelocity.x(), bulletVelocity.y()); + double driftAccel = bulletDatabase[index].twistDirection * (0.0482251 * (bulletDatabase[index].stabilityFactor + 1.2)) / pow(TOF, 0.17); + double driftVelocity = 0.0581025 *(bulletDatabase[index].stabilityFactor + 1.2) * pow(TOF, 0.83); + double dragCorrection = (driftVelocity / trueVelocity.magnitude()) * drag; + double magnitude = (driftAccel + dragCorrection) * dt; + ace::vector3 offset(sin(bulletDir + M_PI / 2) * magnitude, cos(bulletDir + M_PI / 2) * magnitude, 0); + velocityOffset += offset; + bulletVelocity += offset; + } + + double lat = bulletDatabase[index].latitude; + accel.x(2 * EARTH_ANGULAR_SPEED * +(bulletVelocity.y() * sin(lat) - bulletVelocity.z() * cos(lat))); + accel.y(2 * EARTH_ANGULAR_SPEED * -(bulletVelocity.x() * sin(lat))); + accel.z(2 * EARTH_ANGULAR_SPEED * +(bulletVelocity.x() * cos(lat))); + + velocityOffset += accel * dt; + bulletVelocity += accel * dt + gravityAccel * dt; + + TOF += dt; + time += dt; } - accel[0] = (trueVelocity[0] / trueSpeed) * drag; - accel[1] = (trueVelocity[1] / trueSpeed) * drag; - accel[2] = (trueVelocity[2] / trueSpeed) * drag; + bulletDatabase[index].bulletVelocityPreviousFrame = bulletVelocityCurrentFrame + velocityOffset; - velocityOffset[0] -= accel[0] * deltaT; - velocityOffset[1] -= accel[1] * deltaT; - velocityOffset[2] -= accel[2] * deltaT; - - if (TOF > 0) { - double bulletDir = atan2(bulletDatabase[index].bulletVelocity[0], bulletDatabase[index].bulletVelocity[1]); - double driftAccel = bulletDatabase[index].twistDirection * (0.0482251 * (bulletDatabase[index].stabilityFactor + 1.2)) / pow(TOF, 0.17); - double driftVelocity = 0.0581025 *(bulletDatabase[index].stabilityFactor + 1.2) * pow(TOF, 0.83); - double dragCorrection = (driftVelocity / trueSpeed) * drag * deltaT; - velocityOffset[0] += sin(bulletDir + M_PI / 2) * (driftAccel * deltaT + dragCorrection); - velocityOffset[1] += cos(bulletDir + M_PI / 2) * (driftAccel * deltaT + dragCorrection); - } - - double lat = bulletDatabase[index].latitude; - accel[0] = 2 * EARTH_ANGULAR_SPEED * +(bulletDatabase[index].bulletVelocity[1] * sin(lat) - bulletDatabase[index].bulletVelocity[2] * cos(lat)); - accel[1] = 2 * EARTH_ANGULAR_SPEED * -(bulletDatabase[index].bulletVelocity[0] * sin(lat)); - accel[2] = 2 * EARTH_ANGULAR_SPEED * +(bulletDatabase[index].bulletVelocity[0] * cos(lat)); - - velocityOffset[0] += accel[0] * deltaT; - velocityOffset[1] += accel[1] * deltaT; - velocityOffset[2] += accel[2] * deltaT; - - bulletDatabase[index].bulletVelocity[0] = velocity[0] + velocityOffset[0]; - bulletDatabase[index].bulletVelocity[1] = velocity[1] + velocityOffset[1]; - bulletDatabase[index].bulletVelocity[2] = velocity[2] + velocityOffset[2]; - - outputStr << "[" << velocityOffset[0] << "," << velocityOffset[1] << "," << velocityOffset[2] << "]"; + outputStr << "[" << velocityOffset.x() << "," << velocityOffset.y() << "," << velocityOffset.z() << "]"; strncpy_s(output, outputSize, outputStr.str().c_str(), _TRUNCATE); EXTENSION_RETURN(); } else if (!strcmp(mode, "set")) { diff --git a/extensions/fcs/ace_fcs.cpp b/extensions/fcs/ace_fcs.cpp index c43b1c227f..8ab57a1c77 100644 --- a/extensions/fcs/ace_fcs.cpp +++ b/extensions/fcs/ace_fcs.cpp @@ -61,7 +61,7 @@ double traceBullet(double initSpeed, double airFriction, double angle, double an posX += velX * simulationStep * 0.5; posY += velY * simulationStep * 0.5; velX += simulationStep * (velX * velMag * airFriction); - velY += simulationStep * (velY * velMag * airFriction - 9.80665); + velY += simulationStep * (velY * velMag * airFriction - 9.8066); posX += velX * simulationStep * 0.5; posY += velY * simulationStep * 0.5; if (posX >= posTargetX) { break; }