Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#include "Headers/AIManager.h"

#include "AI/ActionInterface/Headers/AITeam.h"
#include "AI/PathFinding/Headers/DivideRecast.h"

#include "Core/Time/Headers/ApplicationTimer.h"

namespace Divide {

using namespace AI;

AIManager::AIManager()
    : _navMeshDebugDraw(false),
      _pauseUpdate(true),
      _updating(false),
      _deltaTime(0ULL),
      _currentTime(0ULL),
      _previousTime(0ULL)
{
    _shouldStop = false;
    _running = false;
    Navigation::DivideRecast::createInstance();
}

AIManager::~AIManager()
{
    Destroy();
}

/// Clear up any remaining AIEntities
void AIManager::Destroy() {
    {
        WriteLock w_lock(_updateMutex);
        for (AITeamMap::value_type& entity : _aiTeams) {
            MemoryManager::DELETE(entity.second);
        }
        _aiTeams.clear();
    }
    {
        WriteLock w_lock(_navMeshMutex);
        for (NavMeshMap::value_type& it : _navMeshes) {
            MemoryManager::DELETE(it.second);
        }
        _navMeshes.clear();

        Navigation::DivideRecast::destroyInstance();
    }
}

void AIManager::update() {
    static const U64 updateFreq = Time::MillisecondsToMicroseconds(Config::AI_THREAD_UPDATE_FREQUENCY);
    _previousTime = Time::ElapsedMicroseconds(true);
    _running = true;

    while(true) {
        if (_shouldStop) {
            break;
        }

        _currentTime = Time::ElapsedMicroseconds(true);
        if (_currentTime >= _previousTime + updateFreq) {
            
            /// use internal delta time calculations
            _deltaTime = _currentTime - _previousTime;

            {
                /// Lock the entities during update() adding or deleting entities is
                /// suspended until this returns
                ReadLock r_lock(_updateMutex);
                if (!_aiTeams.empty() && !_pauseUpdate) {
                    _updating = true;
                    if (_sceneCallback) {
                        _sceneCallback();
                    }

                    if (processInput(_deltaTime)) {  // sensors
                        if (processData(_deltaTime)) {  // think
                            updateEntities(_deltaTime);  // react
                        }
                    }
    
                    _updating = false;
                }
            }
            _previousTime = Time::ElapsedMicroseconds(true);

            if (Config::AI_THREAD_UPDATE_FREQUENCY > Config::MIN_SLEEP_THRESHOLD_MS) {
                //ToDo: this needs adjustment to account for AI execution time
                std::this_thread::sleep_for(std::chrono::microseconds(updateFreq));
            }
        }
    }

    _running = false;
}

bool AIManager::processInput(const U64 deltaTime) {  // sensors
    for (AITeamMap::value_type& team : _aiTeams) {
        if (!team.second->processInput(deltaTime)) {
            return false;
        }
    }
    return true;
}

bool AIManager::processData(const U64 deltaTime) {  // think
    for (AITeamMap::value_type& team : _aiTeams) {
        if (!team.second->processData(deltaTime)) {
            return false;
        }
    }
    return true;
}

bool AIManager::updateEntities(const U64 deltaTime) {  // react
    for (AITeamMap::value_type& team : _aiTeams) {
        if (!team.second->update(deltaTime)) {
            return false;
        }
    }
    return true;
}

bool AIManager::registerEntity(U32 teamID, AIEntity* entity) {
    WriteLock w_lock(_updateMutex);
    AITeamMap::const_iterator it = _aiTeams.find(teamID);
    DIVIDE_ASSERT(it != std::end(_aiTeams),
                  "AIManager error: attempt to register an AI Entity to a "
                  "non-existent team!");
    it->second->addTeamMember(entity);
    return true;
}

void AIManager::unregisterEntity(AIEntity* entity) {
    for (AITeamMap::value_type& team : _aiTeams) {
        unregisterEntity(team.second->getTeamID(), entity);
    }
}

void AIManager::unregisterEntity(U32 teamID, AIEntity* entity) {
    WriteLock w_lock(_updateMutex);
    AITeamMap::const_iterator it = _aiTeams.find(teamID);
    DIVIDE_ASSERT(it != std::end(_aiTeams),
                  "AIManager error: attempt to remove an AI Entity from a "
                  "non-existent team!");
    it->second->removeTeamMember(entity);
}

bool AIManager::addNavMesh(AIEntity::PresetAgentRadius radius,
                           Navigation::NavigationMesh* const navMesh) {
    WriteLock w_lock(_navMeshMutex);
    NavMeshMap::iterator it = _navMeshes.find(radius);
    DIVIDE_ASSERT(it == std::end(_navMeshes),
                  "AIManager error: NavMesh for specified dimensions already "
                  "exists. Remove it first!");
    DIVIDE_ASSERT(navMesh != nullptr,
                  "AIManager error: Invalid navmesh specified!");

    navMesh->debugDraw(_navMeshDebugDraw);
    hashAlg::emplace(_navMeshes, radius, navMesh);
    w_lock.unlock();

    WriteLock w_lock2(_updateMutex);
    for (AITeamMap::value_type& team : _aiTeams) {
        team.second->addCrowd(radius, navMesh);
    }

    return true;
}

void AIManager::destroyNavMesh(AIEntity::PresetAgentRadius radius) {
    WriteLock w_lock(_navMeshMutex);
    NavMeshMap::iterator it = _navMeshes.find(radius);
    DIVIDE_ASSERT(it != std::end(_navMeshes),
                  "AIManager error: Can't destroy NavMesh for specified radius "
                  "(NavMesh not found)!");
    MemoryManager::DELETE(it->second);
    _navMeshes.erase(it);
    w_lock.unlock();

    WriteLock w_lock2(_updateMutex);
    for (AITeamMap::value_type& team : _aiTeams) {
        team.second->removeCrowd(radius);
    }
}

void AIManager::registerTeam(AITeam* const team) {
    WriteLock w_lock(_updateMutex);
    U32 teamID = team->getTeamID();
    DIVIDE_ASSERT(_aiTeams.find(teamID) == std::end(_aiTeams),
                  "AIManager error: attempt to double register an AI team!");

    hashAlg::insert(_aiTeams, std::make_pair(teamID, team));
}

void AIManager::unregisterTeam(AITeam* const team) {
    WriteLock w_lock(_updateMutex);
    U32 teamID = team->getTeamID();
    AITeamMap::iterator it = _aiTeams.find(teamID);
    DIVIDE_ASSERT(it != std::end(_aiTeams),
                  "AIManager error: attempt to unregister an invalid AI team!");
    _aiTeams.erase(it);
}

void AIManager::toggleNavMeshDebugDraw(bool state) {
    WriteLock w_lock(_navMeshMutex);
    for (NavMeshMap::value_type& it : _navMeshes) {
        it.second->debugDraw(state);
    }

    _navMeshDebugDraw = state;
}

void AIManager::debugDraw(bool forceAll) {
    WriteLock w_lock(_navMeshMutex);
    for (NavMeshMap::value_type& it : _navMeshes) {
        it.second->update(_deltaTime);
        if (forceAll || it.second->debugDraw()) {
            it.second->render();
        }
    }
}

};  // namespace Divide

Commits for Divide-Framework/trunk/Source Code/Managers/AIManager.cpp

Diff revisions: vs.
Revision Author Commited Message
693 Diff Diff IonutCava picture IonutCava Thu 28 Apr, 2016 16:19:35 +0000

[IonutCava]
- Cleanup Time and Profiling code

674 Diff Diff IonutCava picture IonutCava Mon 11 Apr, 2016 16:17:10 +0000

[IonutCava]
- Some profile guided optimizations:
— Remove the task state hashmap and replace with flat array
— Allow PhysX to load collision meshes from a RAM cache first -> then file -> then recompute
- Improve memory logger output

670 Diff Diff IonutCava picture IonutCava Wed 06 Apr, 2016 16:21:35 +0000

[IonutCava]
- getInstance() renamed to instance() for simplicity (should really go away altogether, but that’s a different issue)
- some particle emitter threading updates

659 Diff Diff IonutCava picture IonutCava Thu 17 Mar, 2016 16:28:19 +0000

[IonutCava]
- Refactor threadpool/task system:
— Simpler, faster code
— callback functions should handle their own looping logic
— Allow room for future implementation of parent <-> children dependencies of tasks

457 Diff Diff IonutCava picture IonutCava Mon 01 Jun, 2015 21:45:52 +0000

[Ionut]
- Windows build fix for previous commit

444 Diff Diff IonutCava picture IonutCava Thu 21 May, 2015 16:06:53 +0000

[Ionut]
- More platform independent code cleanup:
— Moved platform specific defines to their respective header files (e.g. THREAD_LOCAL)
— Moved most preprocessor defines from the VisualC++ projects into source code
— Removed compiler specific code (e.g. warning disables) and fixed most warning resulting from this

434 Diff Diff IonutCava picture IonutCava Wed 13 May, 2015 22:26:29 +0000

[Ionut]
- Simplified SceneGraph/SceneGraphNode classes:
— RAII style. Dropped load/unload
— SGN deletion callbacks are tracked by ID
— Better node deletion System
- Better scoring system with manual override:
— Key 1 adds a point to team A
— Key 2 adds a point to team B
- Safer scene pointer management in SceneManager

412 Diff Diff IonutCava picture IonutCava Mon 27 Apr, 2015 15:37:55 +0000

[Ionut]
- Bug fixes relating to ApplicationTimer (bad conversions, higher precision changes, etc)
- NavMesh loading updates.

404 Diff Diff IonutCava picture IonutCava Sun 19 Apr, 2015 20:37:32 +0000

[Ionut]
- Threading work regarding texture loading (W.I.P.)
- Animation system cleanup (W.I.P.)
- ShaderManager shutdown cleanup improvements

393 IonutCava picture IonutCava Tue 31 Mar, 2015 16:10:48 +0000

[Ionut]
- Experimental async command generation code. Functional, but improvements require performance profiling to ensure that the overhead cost is minimal.
- Simplified Singleton base class for improved performance (thanks to C++11 static initialization guarantee in a multi-threaded environment)
- Added separate alignment checking for UBOs and SSBOs
- Fixed a type on config.h affecting release builds