Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
AIEntity.cpp
Go to the documentation of this file.
1
2
3#include "Headers/AIEntity.h"
4
9
12
13namespace Divide {
14using namespace AI;
15
16constexpr F32 DESTINATION_RADIUS = 2.f;
20
21AIEntity::AIEntity( NPC* parent, const vec3<F32>& currentPosition, std::string_view name)
22 : GUIDWrapper(),
23 _name(MOV(name)),
24 _teamPtr(nullptr),
25 _processor(nullptr),
26 _unitRef( parent ),
27 _agentID(-1),
28 _detourCrowd(nullptr),
29 _agent(nullptr),
30 _distanceToTarget(-1.f),
31 _previousDistanceToTarget(-1.f),
32 _moveWaitTimer(0ULL),
33 _stopped(false)
34{
35 _currentPosition.set(currentPosition);
37}
38
40{
41 if (_detourCrowd) {
43 }
44
45 if (!setAndSurrenderAIProcessor( nullptr ))
46 {
48 }
49}
50
51void AIEntity::load( const vec3<F32>& currentPosition )
52{
53 if (!setPosition( currentPosition ))
54 {
56 }
57
58 if (!isAgentLoaded() && _detourCrowd) {
59 _agentID = _detourCrowd->addAgent( currentPosition,
62 : to_F32(_detourCrowd->getAgentHeight() / 2 * 3.5f),
65 : 5.0f);
66
68 _destination = currentPosition;
69 }
70}
71
73 if (!isAgentLoaded()) {
74 return;
75 }
76
77 if (_detourCrowd) {
79 }
80
81 _agentID = -1;
82 _agent = nullptr;
83}
84
86 const AIMsg msg,
87 const std::any& msg_content) {
88
89 if (getGUID() != receiver.getGUID()) {
90 receiver.receiveMessage(*this, msg, msg_content);
91 }
92}
93
95 const AIMsg msg,
96 const std::any& msg_content) {
97 processMessage(sender, msg, msg_content);
98}
99
101 const AIMsg msg,
102 const std::any& msg_content) {
103 assert(_processor);
105 _processor->processMessage(sender, msg, msg_content);
106}
107
110 const SensorMap::const_iterator it = _sensorList.find(type);
111 if (it != std::end(_sensorList)) {
112 return it->second.get();
113 }
114 return nullptr;
115}
116
118{
120 std::unique_ptr<Sensor>& sensor = _sensorList[type];
121 switch (type)
122 {
124 {
125 sensor = std::make_unique<AudioSensor>(this);
126 } break;
128 {
129 sensor = std::make_unique<VisualSensor>(this);
130 } break;
131 case SensorType::NONE:{
132
133 } break;
134 }
135
136 return true;
137}
138
140{
142 _processor.reset(processor);
143 if (_processor)
144 {
145 _processor->addEntityRef(this);
146 processor = nullptr;
147 }
148
149 return true;
150}
151
152bool AIEntity::processInput(const U64 deltaTimeUS) {
153 if (_processor) {
154 _processor->init();
155 if (!_processor->processInput(deltaTimeUS)) {
156 return false;
157 }
158 }
159
160 return true;
161}
162
163bool AIEntity::processData(const U64 deltaTimeUS) {
164 if (_processor) {
165 if (!_processor->processData(deltaTimeUS)) {
166 return false;
167 }
168 }
169
170 return true;
171}
172
173bool AIEntity::update(const U64 deltaTimeUS) {
174 if (_processor) {
175 _processor->update(deltaTimeUS, _unitRef);
176 }
177 if (_unitRef) {
178 _unitRef->update(deltaTimeUS);
179 if (!_detourCrowd) {
180 resetCrowd();
181 }
182 }
183 updatePosition(deltaTimeUS);
184
185 return true;
186}
187
189{
190 if (_teamPtr)
191 {
192 return _teamPtr->teamID();
193 }
194 return U32_MAX;
195}
196
197void AIEntity::setTeamPtr(AITeam* const teamPtr) {
198 if (_teamPtr) {
200 }
201 _teamPtr = teamPtr;
202}
203
204
206 return _detourCrowd ? _detourCrowd->getAgentHeight() : 0.f;
207}
208
210 return _detourCrowd ? _detourCrowd->getAgentRadius() : 0.f;
211}
212
214{
215 if (_detourCrowd)
216 {
217 unload();
218 }
219
221
222 if (_detourCrowd) {
225 }
226}
227
228bool AIEntity::setPosition(const vec3<F32>& position) {
229 if (!isAgentLoaded()) {
230 if (_unitRef) {
231 _unitRef->setPosition(position);
232 }
233 return false;
234 }
235
237 return false;
238 }
239
240 // Find position on NavMesh
241 vec3<F32> result;
242 const bool isPointOnNavMesh = _detourCrowd->getNavMesh().getClosestPosition(position,
243 vec3<F32>(5),
245 result);
246 DIVIDE_ASSERT(isPointOnNavMesh, "AIEntity::setPosition error: Invalid NavMesh position returned!");
247
248 // Remove agent from crowd and re-add at position
253 : to_F32(_detourCrowd->getAgentHeight() / 2 * 3.5f),
256 : 5.0f);
257
259
260 if (_unitRef) {
261 _unitRef->setPosition(result);
262 }
263
264 return true;
265}
266
267void AIEntity::updatePosition(const U64 deltaTimeUS)
268{
269 if (isAgentLoaded() && getAgent()->active)
270 {
273 const F32 distanceDelta = std::abs(_previousDistanceToTarget - _distanceToTarget);
274
275 // if we are walking but did not change distance in a while
276 if (distanceDelta < DESTINATION_RADIUS_SQ)
277 {
278 _moveWaitTimer += deltaTimeUS;
279
280 if (Time::MicrosecondsToSeconds<F32>(_moveWaitTimer) > 5.f)
281 {
282 // DISABLED FOR NOW!
283 if constexpr(false)
284 {
285 _moveWaitTimer = 0;
286 stop();
287 if (_detourCrowd)
288 {
289 vec3<F32> result;
290 const bool isPointOnNavMesh = _detourCrowd->getNavMesh().getClosestPosition(_currentPosition, vec3<F32>(5), DESTINATION_RADIUS_F, result);
291
292 DIVIDE_ASSERT(isPointOnNavMesh, "AIEntity::updatePosition error: Invalid NavMesh position returned!");
293 if (!_unitRef->moveTo(result, deltaTimeUS))
294 {
296 }
297 }
298 return;
299 }
300 }
301 } else {
302 _moveWaitTimer = 0;
303 }
306 }
307
308 if (_unitRef) {
311 }
312}
313
314bool AIEntity::updateDestination(const vec3<F32>& destination, const bool updatePreviousPath) {
315 if (!isAgentLoaded()) {
316 return false;
317 }
318
319 // Skip very small updates
321 return true;
322 }
323
324 // Find position on navmesh
325 vec3<F32> result;
326 bool isPointOnNavMesh =
329 vec3<F32>(5),
330 result,
331 10);
332 if (!isPointOnNavMesh) {
333 isPointOnNavMesh =
335 vec3<F32>(5),
337 result);
338 }
339
340 if (isPointOnNavMesh) {
341 _detourCrowd->setMoveTarget(_agentID, result, updatePreviousPath);
342 _destination = result;
343 _stopped = false;
344 }
345
346 return isPointOnNavMesh;
347}
348
349const vec3<F32>& AIEntity::getPosition() const noexcept {
350 return _currentPosition;
351}
352
353const vec3<F32>& AIEntity::getDestination() const noexcept {
354 if (isAgentLoaded()) {
355 return _destination;
356 }
357
358 // TODO: this is not ideal! -Ionut
359 return getPosition();
360}
361
363 if (!isAgentLoaded()) {
364 return false;
365 }
366
369}
370
371void AIEntity::setDestination(const vec3<F32>& destination) noexcept {
372 if (!isAgentLoaded()) {
373 return;
374 }
375
376 _destination = destination;
377 _stopped = false;
378}
379
381 const vec3<F32> lookDirection(_unitRef != nullptr
384
385 setVelocity(lookDirection * to_F32(getMaxSpeed()));
386}
387
389 const vec3<F32> lookDirection(_unitRef != nullptr
392
393 setVelocity(lookDirection * to_F32(getMaxSpeed()) * -1.0f);
394}
395
396void AIEntity::setVelocity(const vec3<F32>& velocity) {
397 _stopped = false;
399
400 if (!isAgentLoaded() || !_detourCrowd->requestVelocity(getAgentID(), velocity)) {
402 }
403}
404
406 if (!isAgentLoaded()) {
407 _stopped = true;
408 return;
409 }
410
413 _stopped = true;
414 }
415}
416
418 return isAgentLoaded() ? vec3<F32>(getAgent()->nvel) : vec3<F32>();
419}
420
422{
423 return isAgentLoaded() ? getAgent()->params.maxSpeed : 0.f;
424}
425
427{
428 return isAgentLoaded() ? getAgent()->params.maxAcceleration : 0.f;
429}
430
431string AIEntity::toString() const {
432 if (_processor) {
433 return _processor->toString();
434 }
435
436 return "Error_" + name();
437}
438} // namespace Divide
#define MOV(...)
#define DIVIDE_ASSERT(...)
#define DIVIDE_UNEXPECTED_CALL()
Based on OgreCrowd.
Definition: AIEntity.h:60
const string & name() const noexcept
Definition: AIEntity.h:88
bool setAndSurrenderAIProcessor(AIProcessor *processor)
Definition: AIEntity.cpp:139
bool updateDestination(const vec3< F32 > &destination, bool updatePreviousPath=false)
Definition: AIEntity.cpp:314
bool update(U64 deltaTimeUS)
Definition: AIEntity.cpp:173
AIEntity(NPC *parent, const vec3< F32 > &currentPosition, std::string_view name)
Definition: AIEntity.cpp:21
void resetCrowd()
Update the crowding system.
Definition: AIEntity.cpp:213
vec3< F32 > _currentPosition
Definition: AIEntity.h:202
F32 _previousDistanceToTarget
Definition: AIEntity.h:205
bool _stopped
True if this character is stopped.
Definition: AIEntity.h:208
F32 getAgentRadius() const noexcept
The radius of the agent for this character.
Definition: AIEntity.cpp:209
bool processData(U64 deltaTimeUS)
Definition: AIEntity.cpp:163
bool isAgentLoaded() const noexcept
Definition: AIEntity.h:97
F32 getMaxAcceleration() const noexcept
Definition: AIEntity.cpp:426
void processMessage(AIEntity &sender, AIMsg msg, const std::any &msg_content)
Definition: AIEntity.cpp:100
void moveBackwards()
Manually control the character moving it backwards.
Definition: AIEntity.cpp:388
void setTeamPtr(AITeam *teamPtr)
Definition: AIEntity.cpp:197
void updatePosition(U64 deltaTimeUS)
Definition: AIEntity.cpp:267
U32 getTeamID() const
Definition: AIEntity.cpp:188
void receiveMessage(AIEntity &sender, AIMsg msg, const std::any &msg_content)
Definition: AIEntity.cpp:94
string toString() const
Definition: AIEntity.cpp:431
I32 getAgentID() const noexcept
Definition: AIEntity.h:94
const dtCrowdAgent * _agent
The agent controlling this character.
Definition: AIEntity.h:192
vec3< F32 > _destination
Definition: AIEntity.h:201
vec3< F32 > getVelocity() const noexcept
Definition: AIEntity.cpp:417
void setVelocity(const vec3< F32 > &velocity)
Definition: AIEntity.cpp:396
F32 getAgentHeight() const noexcept
The height of the agent for this character.
Definition: AIEntity.cpp:205
bool processInput(U64 deltaTimeUS)
Definition: AIEntity.cpp:152
F32 getMaxSpeed() const noexcept
Definition: AIEntity.cpp:421
Navigation::DivideDtCrowd * _detourCrowd
Crowd in which the agent of this character is.
Definition: AIEntity.h:190
const dtCrowdAgent * getAgent() const noexcept
The agent that steers this character within the crowd.
Definition: AIEntity.h:96
bool setPosition(const vec3< F32 > &position)
Place agent at new position.
Definition: AIEntity.cpp:228
void sendMessage(AIEntity &receiver, AIMsg msg, const std::any &msg_content)
Definition: AIEntity.cpp:85
const vec3< F32 > & getPosition() const noexcept
Definition: AIEntity.cpp:349
void setDestination(const vec3< F32 > &destination) noexcept
Definition: AIEntity.cpp:371
bool destinationReached() const
Returns true when this agent has reached its set destination.
Definition: AIEntity.cpp:362
void load(const vec3< F32 > &currentPosition)
Definition: AIEntity.cpp:51
bool addSensor(SensorType type)
Definition: AIEntity.cpp:117
~AIEntity() override
Definition: AIEntity.cpp:39
SharedMutex _updateMutex
Definition: AIEntity.h:180
const vec3< F32 > & getDestination() const noexcept
The destination set for this agent.
Definition: AIEntity.cpp:353
std::unique_ptr< AIProcessor > _processor
Definition: AIEntity.h:178
Sensor * getSensor(SensorType type)
Definition: AIEntity.cpp:108
PresetAgentRadius _agentRadiusCategory
Definition: AIEntity.h:193
void moveForward()
Manually control the character moving it forward.
Definition: AIEntity.cpp:380
PresetAgentRadius getAgentRadiusCategory() const noexcept
The radius category of this character.
Definition: AIEntity.h:105
vec3< F32 > _currentVelocity
Definition: AIEntity.h:203
SensorMap _sensorList
Definition: AIEntity.h:184
Provides a scene-level AI implementation.
Definition: AIProcessor.h:46
bool removeTeamMember(AIEntity *entity)
Definition: AITeam.cpp:180
Navigation::DivideDtCrowd * getCrowd(const AIEntity::PresetAgentRadius radius) const
Definition: AITeam.h:78
vec3< F32 > getLastDestination() const noexcept
Definition: DivideCrowd.h:188
void setMoveTarget(const vec3< F32 > &position, bool adjust)
static bool destinationReached(const dtCrowdAgent *agent, F32 maxDistanceFromTarget)
const dtCrowdAgent * getAgent(const I32 id) const
Retrieve agent with specified ID from the crowd.
Definition: DivideCrowd.h:107
bool isValidNavMesh() const
Check if the navMesh is valid.
F32 getAgentHeight() const noexcept
Definition: DivideCrowd.h:166
void removeAgent(I32 idx)
Remove agent with specified ID from the crowd.
bool stopAgent(I32 agentID) const
const NavigationMesh & getNavMesh() const noexcept
Get the navigation mesh associated with this crowd.
Definition: DivideCrowd.h:175
F32 getAgentRadius() const noexcept
Definition: DivideCrowd.h:171
bool requestVelocity(I32 agentID, const vec3< F32 > &velocity) const
I32 addAgent(const vec3< F32 > &position, F32 maxSpeed, F32 acceleration)
bool getClosestPosition(const vec3< F32 > &destination, const vec3< F32 > &extents, F32 delta, vec3< F32 > &result) const
Definition: NavMesh.cpp:858
bool getRandomPositionInCircle(const vec3< F32 > &center, F32 radius, const vec3< F32 > &extents, vec3< F32 > &result, U8 maxIters=15) const
Definition: NavMesh.cpp:872
virtual vec3< F32 > getPosition() const
The current position of this character.
Definition: Character.cpp:72
virtual void setVelocity(const vec3< F32 > &newVelocity)
Update character velocity.
Definition: Character.cpp:67
virtual void setPosition(const vec3< F32 > &newPosition)
Set the current position of this charater.
Definition: Character.cpp:62
virtual vec3< F32 > getLookingDirection()
The direction in which the character is currently looking.
Definition: Character.cpp:76
Utility class that adds basic GUID management to objects.
Definition: GUIDWrapper.h:44
FORCE_INLINE I64 getGUID() const noexcept
Definition: GUIDWrapper.h:51
NPC base class. Every character in the game is an NPC by default except the Player.
Definition: NPC.h:46
void update(U64 deltaTimeUS) override
Definition: NPC.cpp:15
virtual bool moveTo(const vec3< F32 > &targetPosition, const U64 deltaTimeUS)
Definition: Unit.cpp:42
virtual F32 getMovementSpeed() const
Get the unit's current movement speed.
Definition: Unit.h:107
virtual F32 getAcceleration() const
Get the unit's acceleration rate.
Definition: Unit.h:109
void reset() noexcept
set all the components back to 0
Definition: MathVectors.h:742
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:707
T distanceSquared(const vec3 &v) const noexcept
compute the vector's squared distance to another specified vector
SensorType
Definition: Sensor.h:39
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
vec2< T > Normalized(vec2< T > vector) noexcept
Definition: MathVectors.inl:98
bool load() override
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
constexpr F32 DESTINATION_RADIUS
Definition: AIEntity.cpp:16
constexpr F32 to_F32(const T value)
std::shared_lock< mutex > SharedLock
Definition: SharedMutex.h:49
Project & parent
Definition: DefaultScene.h:41
constexpr F32 DESTINATION_RADIUS_SQ
Definition: AIEntity.cpp:17
constexpr F32 DESTINATION_RADIUS_F
Definition: AIEntity.cpp:19
static const vec3< F32 > WORLD_Z_NEG_AXIS
Definition: MathVectors.h:1444
constexpr U32 U32_MAX
uint32_t U32
uint64_t U64