Changed: Entire frag system re-optimized to a single tracking/GC index-based PFH.

Changed: Spalling calculations now throttled across frames and limited; accurate but performant
Changed: All lookups are now index-based on a global projectiles array. This reduced runtime dramatically for all fragmentation.
This commit is contained in:
jaynus 2015-05-13 17:06:10 -07:00
parent aef896cc21
commit 58a55313cd
12 changed files with 120 additions and 72 deletions

View File

@ -1,15 +1,33 @@
class ACE_Settings {
class GVAR(enabled) {
class GVAR(Enabled) {
displayName = "$STR_ACE_frag_EnableFrag";
description = "$STR_ACE_frag_EnableFrag_Desc";
typeName = "BOOL";
value = 1;
};
class GVAR(spallEnabled) {
class GVAR(SpallEnabled) {
displayName = "$STR_ACE_frag_EnableSpall";
description = "$STR_ACE_frag_EnableSpall_Desc";
typeName = "BOOL";
value = 1;
};
class GVAR(maxTrack) {
displayName = "$STR_ACE_frag_MaxTrack";
description = "$STR_ACE_frag_MaxTrack_Desc";
typeName = "SCALAR";
value = 500;
};
class GVAR(MaxTrackPerFrame) {
displayName = "$STR_ACE_frag_MaxTrackPerFrame";
description = "$STR_ACE_frag_MaxTrackPerFrame_Desc";
typeName = "SCALAR";
value = 50;
};
class GVAR(EnableDebugTrace) {
displayName = "$STR_ACE_frag_EnableDebugTrace";
description = "$STR_ACE_frag_EnableDebugTrace_Desc";
typeName = "BOOL";
value = 0;
};
};

View File

@ -9,8 +9,6 @@ class CfgAmmo {
// GVAR(skip) = 1;
//};
#include "CfgAmmoReflections.hpp"
class Bo_GBU12_LGB;
class ACE_GBU12 : Bo_GBU12_LGB {
GVAR(enabled) = 1;
@ -473,4 +471,6 @@ class CfgAmmo {
class ACE_frag_spall_huge: ACE_frag_huge {
timeToLive = 0.3;
};
#include "CfgAmmoReflections.hpp"
};

View File

@ -1,7 +1,6 @@
//CfgAmmoReflections.hpp
#define ACE_EXPLOSION_REFLECTION(range, hit) class ace_explosion_reflection_##range##_##hit : ace_explosion_reflection_base { indirectHitRange = range; indirectHit = hit; dangerRadiusHit = range*3; suppressionRadiusHit = range*2; };
class Sh_120mm_HE;
class ace_explosion_reflection_base : Sh_120mm_HE {
CraterWaterEffects = "";
CraterEffects = "";

View File

@ -1,5 +1,10 @@
#include "script_component.hpp"
if(GVAR(EnableDebugTrace) && !isMultiplayer) then {
GVAR(traceFrags) = true;
GVAR(autoTrace) = true;
};
if(isServer) then {
[QGVAR(frag_eh), { _this call FUNC(frago); }] call ace_common_fnc_addEventHandler;
};

View File

@ -15,7 +15,7 @@ GVAR(TOTALFRAGS) = 0;
GVAR(spallHPData) = [];
GVAR(spallIsTrackingCount) = 0;
GVAR(autoTrace) = true;
GVAR(autoTrace) = false;
GVAR(traceID) = -1;
GVAR(traces) = [];
GVAR(tracesStarted) = false;
@ -43,6 +43,7 @@ PREP(doExplosions);
PREP(doReflections);
GVAR(lastIterationIndex) = 0;
GVAR(objects) = [];
GVAR(objectTypes) = [];
GVAR(arguments) = [];

View File

@ -1,20 +1,21 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
private ["_enabled", "_gun", "_type", "_round", "_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"];
private ["_enabled","_doFragTrack", "_doSpall", "_spallTrack", "_spallTrackID"];
PARAMS_3(_gun,_type,_round);
if (!GVAR(enabled)) exitWith {};
_gun = _this select 0;
_type = _this select 1;
_round = _this select 2;
_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled));
if(_enabled < 1) exitWith {};
//_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled));
//if(_enabled < 1) exitWith {};
if(_round in GVAR(blackList)) exitWith {
GVAR(blackList) = GVAR(blackList) - [_round];
};
// Exit on max track
if( (count GVAR(objects)) > GVAR(MaxTrack)) exitWith { };
_doFragTrack = false;
if(_gun == ACE_player) then {
_doFragTrack = true;
@ -27,7 +28,7 @@ if(_gun == ACE_player) then {
};
};
};
if(GVAR(spallEnabled)) then {
if(GVAR(SpallEnabled)) then {
if(GVAR(spallIsTrackingCount) <= 0) then {
GVAR(spallHPData) = [];
};
@ -40,12 +41,15 @@ if(GVAR(spallEnabled)) then {
};
// ACE_player sideChat format["c: %1", GVAR(spallIsTrackingCount)];
#ifdef DEBUG_MODE_FULL
[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack);
#endif
if(GVAR(autoTrace)) then {
[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack);
};
// We only do the single track object check here.
if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then {
// We should do an {!(_round in GVAR(objects))}
// But we leave that out here for optimization. So this cannot be a framework function
// Otherwise, it should only be added once and from the FiredEH
if(_doFragTrack && alive _round) then {
_spallTrack = [];
_spallTrackID = [];
@ -57,12 +61,12 @@ if(_doFragTrack && alive _round && {!(_round in GVAR(objects))} ) then {
(getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force))),
(getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt((getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange")))))
];
TRACE_1("Initializing track", _round);
GVAR(objects) pushBack _round;
GVAR(arguments) pushBack _args;
if(_doSpall) then {
[_round, 2, _spallTrack, _spallTrackID] call FUNC(spallTrack);
[_round, 1, _spallTrack, _spallTrackID] call FUNC(spallTrack);
};
// ACE_player sideChat "WTF2";
};

View File

@ -1,14 +1,10 @@
//fnc_doSpall.sqf
#include "script_component.hpp"
#ifdef DEBUG_MODE_FULL
GVAR(traceFrags) = true;
#endif
// ACE_player sideChat "WAAAAAAAAAAAAAAAAAAAAA";
private ["_params", "_hitData", "_initialData", "_hpData", "_object", "_foundObjects", "_index", "_foundObjecsts", "_roundType", "_round", "_caliber", "_explosive", "_idh", "_alive", "_exit", "_vm", "_velocity", "_oldVelocity", "_curVelocity", "_diff", "_polar", "_unitDir", "_spallPos", "_pos1", "_i", "_pos2", "_blah", "_data", "_spallPolar", "_warn", "_c", "_m", "_k", "_gC", "_fragPower", "_fragTypes", "_spread", "_spallCount", "_elev", "_dir", "_vel", "_spallFragVect", "_fragType", "_fragment", "_pos"];
_params = _this select 0;
[(_this select 1)] call cba_fnc_removePerFrameHandler;
_hitData = _params select 0;
_initialData = GVAR(spallHPData) select (_hitData select 0);
_hpData = (_hitData select 1) select (_params select 1);

View File

@ -163,11 +163,8 @@ if(_isArmed && (count _objects) > 0) then {
_fragObj setPosASL _lastPos;
_fragObj setVectorDir _vec;
_fragObj setVelocity _vel;
#ifdef DEBUG_MODE_FULL
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
GVAR(traceFrags) = true;
#endif
if(GVAR(traceFrags)) then {
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
[ACE_player, _fragObj, [1,0,0,1]] call FUNC(addTrack);
};
_fragCount = _fragCount + 1;
@ -200,11 +197,9 @@ if(_isArmed && (count _objects) > 0) then {
_fragObj setPosASL _lastPos;
_fragObj setVectorDir _vec;
_fragObj setVelocity _vel;
#ifdef DEBUG_MODE_FULL
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
GVAR(traceFrags) = true;
#endif
if(GVAR(traceFrags)) then {
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
[ACE_player, _fragObj, [1,0.5,0,1]] call FUNC(addTrack);
};
_fragCount = _fragCount + 1;

View File

@ -9,36 +9,48 @@
* Return Value:
* None
*/
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
PARAMS_2(_pfhArgs,_handle);
//PARAMS_2(_pfhArgs,_handle);
if (!GVAR(enabled)) exitWith {};
private["_gcIndex"];
_gcIndex = [];
{
_iter = 0;
while { (count GVAR(objects)) > 0 && { _iter < GVAR(MaxTrackPerFrame) } } do {
private["_object", "_args"];
_object = _x;
if(GVAR(lastIterationIndex) >= (count GVAR(objects))) then {
GVAR(lastIterationIndex) = 0;
};
_object = GVAR(objects) select GVAR(lastIterationIndex);
if(!isNil "_object") then {
if(isNull _object) then {
_gcIndex pushBack _forEachIndex;
_gcIndex pushBack GVAR(lastIterationIndex);
} else {
_args = GVAR(arguments) select _forEachIndex;
_args = GVAR(arguments) select GVAR(lastIterationIndex);
_args call FUNC(pfhRound);
};
if(!alive _object) then {
_gcIndex pushBack _forEachIndex;
if(!(_args call FUNC(pfhRound))) then {
_gcIndex pushBack GVAR(lastIterationIndex); // Add it to the GC if it returns false
};
// If its not alive anymore, remove it from the queue, it already ran once on dead
if(!alive _object) then {
_gcIndex pushBack GVAR(lastIterationIndex);
};
};
};
} forEach GVAR(objects);
_iter = _iter + 1;
GVAR(lastIterationIndex) = GVAR(lastIterationIndex) + 1;
};
// clean up dead object references
private["_deletionCount", "_deleteIndex"];
_deletionCount = 0;
{
_deleteIndex = _gcIndex - _deletionCount;
TRACE_1("GC Projectile", _x);
_deleteIndex = _x - _deletionCount;
GVAR(objects) deleteAt _deleteIndex;
GVAR(arguments) deleteAt _deleteIndex;

View File

@ -1,25 +1,28 @@
#include "script_component.hpp"
private ["_params", "_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"];
_params = _this select 0;
_round = _params select 0;
_lastPos = _params select 1;
_lastVel = _params select 2;
_type = _params select 3;
_time = _params select 4;
_doSpall = _params select 6;
_spallTrack = _params select 7;
_foundObjectHPIds = _params select 8;
_skip = _params select 9;
_explosive = _params select 10;
_indirectRange = _params select 11;
_force = _params select 12;
_fragPower = _params select 13;
private ["_round", "_lastPos", "_lastVel", "_type", "_time", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"];
_round = _this select 0;
_lastPos = _this select 1;
_lastVel = _this select 2;
_type = _this select 3;
_time = _this select 4;
_doSpall = _this select 6;
_spallTrack = _this select 7;
_foundObjectHPIds = _this select 8;
_skip = _this select 9;
_explosive = _this select 10;
_indirectRange = _this select 11;
_force = _this select 12;
_fragPower = _this select 13;
if(_round in GVAR(blackList)) exitWith {
false
};
if (!alive _round) then {
if(_time != time && {!(_round in GVAR(blackList))}) then {
if(_time != time) then {
if(_skip == 0) then {
if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then {
[QGVAR(frag_eh), _params] call ace_common_fnc_serverEvent;
[QGVAR(frag_eh), _this] call ace_common_fnc_serverEvent;
};
};
};
@ -33,13 +36,14 @@ if (!alive _round) then {
} forEach _spallTrack;
};
} else {
if(_round in GVAR(blackList)) exitWith {
[_round] call FUNC(removePfhRound);
};
_params set[1, (getPosASL _round)];
_params set[2, (velocity _round)];
if(_doSpall) then {
[_round, 1, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack);
private["_scale"];
_scale = ( (count GVAR(objects)) / GVAR(MaxTrackPerFrame) ) max 0.1;
[_round, _scale, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack);
};
};
true

View File

@ -22,7 +22,7 @@ if (count _intersectsWith > 0) then {
if(!(_x in _foundObjects)) then {
// diag_log text format["Adding HP: %1", _x];
_index = (count GVAR(spallHPData));
_hpId = _x addEventHandler ["hitPart", format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]];
_hpId = _x addEventHandler ["hitPart", compile format["[%1, _this] call " + QUOTE(FUNC(spallHP)), _index]];
_foundObjects set[(count _foundObjects), _x];
_foundObjectHPIds set[(count _foundObjectHPIds), _hpId];
_data = [_hpId, _x, typeOf _round, _round, _curPos, _velocity, 0, _foundObjects, _foundObjectHPIds];

View File

@ -3,19 +3,33 @@
<Package name="Frag">
<Key ID="STR_ACE_frag_EnableFrag">
<English>Fragmentation Simulation</English>
</Key>
<Key ID="STR_ACE_frag_EnableFrag_Desc">
<English>Enable the ACE Fragmentation Simulation</English>
</Key>
<Key ID="STR_ACE_frag_EnableSpall">
<English>Spalling Simulation</English>
</Key>
<Key ID="STR_ACE_frag_EnableSpall_Desc">
<English>Enable the ACE Spalling Simulation</English>
</Key>
<Key ID="STR_ACE_frag_MaxTrack">
<English>Maximum Projectiles Tracked</English>
</Key>
<Key ID="STR_ACE_frag_MaxTrack_Desc">
<English>This setting controls the maximum amount of projectiles the fragmentation & spalling system will track at any given time. If more projectiles are fired, they will not be tracked. Lower this setting if you do not want FPS drops at high-count projectile scenarios ( >200 rounds in the air at once)</English>
</Key>
<Key ID="STR_ACE_frag_MaxTrackPerFrame">
<English>Maximum Projectiles Per Frame</English>
</Key>
<Key ID="STR_ACE_frag_MaxTrackPerFrame_Desc">
<English>The number of spall track calculations to perform in any given frame. This helps spread the FPS impact of tracking spall rounds across multiple frames, limiting its impact even further.</English>
</Key>
<Key ID="STR_ACE_frag_EnableDebugTrace">
<English>(SP Only) Frag/Spall Debug Tracing</English>
</Key>
<Key ID="STR_ACE_frag_EnableDebugTrace_Desc">
<English>(SP Only) Requires a mission/editor restart. Enables visual tracing of fragmentation and spalling rounds in SP game mode only.</English>
</Key>
</Package>
</Project>